diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
index 9ddf63f..a2b81d4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="1.0.132.0" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AIMP.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AIMP.png
new file mode 100644
index 0000000..3b1f6e8
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AIMP.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AMLLPlayer.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AMLLPlayer.png
new file mode 100644
index 0000000..9eb5101
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AMLLPlayer.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AppleMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AppleMusic.png
new file mode 100644
index 0000000..f98f4a4
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/AppleMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Chrome.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Chrome.png
new file mode 100644
index 0000000..ab51947
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Chrome.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Edge.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Edge.png
new file mode 100644
index 0000000..6d1a52e
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Edge.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/HyPlayer.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/HyPlayer.png
new file mode 100644
index 0000000..0d0552a
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/HyPlayer.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/KugouMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/KugouMusic.png
new file mode 100644
index 0000000..b6d8555
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/KugouMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/LXMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/LXMusic.png
new file mode 100644
index 0000000..096988d
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/LXMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Listen1.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Listen1.png
new file mode 100644
index 0000000..521f6aa
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Listen1.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MediaPlayerWindows11.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MediaPlayerWindows11.png
new file mode 100644
index 0000000..309af9a
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MediaPlayerWindows11.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MoeKoeMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MoeKoeMusic.png
new file mode 100644
index 0000000..9d97f80
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MoeKoeMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MusicBee.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MusicBee.png
new file mode 100644
index 0000000..6c1aa54
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/MusicBee.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/NetEaseCloudMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/NetEaseCloudMusic.png
new file mode 100644
index 0000000..47c4ddd
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/NetEaseCloudMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PlanetMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PlanetMusic.png
new file mode 100644
index 0000000..8bacdc9
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PlanetMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PotPlayer.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PotPlayer.png
new file mode 100644
index 0000000..d7acd93
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/PotPlayer.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQMusic.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQMusic.png
new file mode 100644
index 0000000..355cdeb
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/QQMusic.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Question.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Question.png
new file mode 100644
index 0000000..ca4e343
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Question.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/SaltPlayerForWindows.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/SaltPlayerForWindows.png
new file mode 100644
index 0000000..205eff9
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/SaltPlayerForWindows.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Spotify.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Spotify.png
new file mode 100644
index 0000000..9d58c7c
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Spotify.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/foobar2000.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/foobar2000.png
new file mode 100644
index 0000000..5b72c8d
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/foobar2000.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/iTunes.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/iTunes.png
new file mode 100644
index 0000000..71d8460
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/iTunes.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
index a28c12b..89f7eb7 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
@@ -67,6 +67,7 @@
+
@@ -118,12 +119,27 @@
+
+ Always
+
Always
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
@@ -136,24 +152,72 @@
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
Always
+
+ Always
+
Always
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
Always
+
+ Always
+
Always
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs
new file mode 100644
index 0000000..778004c
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs
@@ -0,0 +1,28 @@
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class PlayerID
+ {
+ public const string LXMusic = "cn.toside.music.desktop";
+ public const string LXMusicPortable = "lx-music-desktop.exe";
+ public const string MediaPlayerWindows11 = "Microsoft.ZuneMusic_8wekyb3d8bbwe!Microsoft.ZuneMusic";
+ public const string AIMP = "AIMP.exe";
+ public const string Foobar2000 = "foobar2000.exe";
+ public const string MusicBee = "MusicBee.exe";
+ public const string PotPlayer = "PotPlayerMini64.exe";
+ public const string Spotify = "Spotify.exe";
+ public const string AppleMusic = "AppleInc.AppleMusicWin_nzyj5cx40ttqa!App";
+ public const string AppleMusicAlternative = "AppleMusic.exe";
+ public const string NetEaseCloudMusic = "cloudmusic.exe";
+ public const string KugouMusic = "kugou";
+ public const string QQMusic = "QQMusic.exe";
+ public const string iTunes = "49586DaveAntoine.MediaControllerforiTunes_9bzempp7dntjg!App";
+ public const string Chrome = "Chrome";
+ public const string Edge = "MSEdge";
+ public const string BetterLyrics = "37412.BetterLyrics_rd1g0rsrrtxw8!App";
+ public const string BetterLyricsDebug = "37412.BetterLyrics_c8mj3v9sysxb4!App";
+ public const string SaltPlayerForWindows = "Sakawish.SaltPlayerforWindows_q65q631pyh094!SaltPlayerforWindows";
+ public const string MoeKoeMusic = "cn.MoeKoe.Music";
+ public const string MoeKoeMusicAlternative = "electron.app.MoeKoe Music";
+ public const string Listen1 = "com.listen1.listen1";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs
new file mode 100644
index 0000000..1f42b91
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public class PlayerName
+ {
+ public const string LXMusic = "LX Music";
+ public const string LXMusicPortable = "LX Music (Portable)";
+ public const string MediaPlayerWindows11 = "Media Player";
+ public const string AIMP = "AIMP";
+ public const string Foobar2000 = "foobar2000";
+ public const string MusicBee = "MusicBee";
+ public const string PotPlayer = "PotPlayer";
+ public const string Spotify = "Spotify";
+ public const string AppleMusic = "Apple Music";
+ public const string AppleMusicAlternative = "Apple Music";
+ public const string NetEaseCloudMusic = "网易云音乐";
+ public const string KugouMusic = "酷狗音乐";
+ public const string QQMusic = "QQ 音乐";
+ public const string iTunes = "iTunes";
+ public const string Chrome = "Google Chrome";
+ public const string Edge = "Microsoft Edge";
+ public const string BetterLyrics = "BetterLyrics";
+ public const string BetterLyricsDebug = "BetterLyrics (Debug)";
+ public const string SaltPlayerForWindows = "Salt Player for Windows";
+ public const string MoeKoeMusic = "MoeKoe Music";
+ public const string Listen1 = "Listen 1";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/SpecialHandlePlayerID.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/SpecialHandlePlayerID.cs
deleted file mode 100644
index 9fa3337..0000000
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/SpecialHandlePlayerID.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace BetterLyrics.WinUI3.Constants
-{
- public static class SpecialHandlePlayerID
- {
- public const string LXMusic = "cn.toside.music.desktop";
- public const string LXMusicPortable = "lx-music-desktop.exe";
- public const string AppleMusic = "AppleInc.AppleMusicWin_nzyj5cx40ttqa!App";
- public const string AppleMusicAlternative = "AppleMusic.exe";
- }
-}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml
index e13f604..50bbfac 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/AppSettingsControl.xaml
@@ -71,6 +71,10 @@
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml
index c655c43..9c8910f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Controls/LyricsSearchControl.xaml
@@ -137,21 +137,67 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
-
-
+
+
-
-
-
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsFormat.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsFormat.cs
index 6cc6442..43234b5 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsFormat.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsFormat.cs
@@ -11,72 +11,4 @@ namespace BetterLyrics.WinUI3.Enums
Krc,
NotSpecified,
}
-
- public static class LyricsFormatExtensions
- {
- public static LyricsFormat? DetectFormat(this string content)
- {
- if (string.IsNullOrWhiteSpace(content))
- return null;
-
- // TTML: 检查 ]*\bxmlns\s*=\s*[""']http://www\.w3\.org/ns/ttml[""']",
- System.Text.RegularExpressions.RegexOptions.IgnoreCase))
- {
- return LyricsFormat.Ttml;
- }
- // KRC: 检测主内容格式 [start,duration]字...
- else if (System.Text.RegularExpressions.Regex.IsMatch(
- content,
- @"^\[\d+,\d+\](<\d+,\d+,0>.+)+",
- System.Text.RegularExpressions.RegexOptions.Multiline))
- {
- return LyricsFormat.Krc;
- }
- // QRC: 检测主内容格式 [start,duration]字(offset,duration)
- else if (System.Text.RegularExpressions.Regex.IsMatch(
- content,
- @"^\[\d+,\d+\].*?\(\d+,\d+\)",
- System.Text.RegularExpressions.RegexOptions.Multiline))
- {
- return LyricsFormat.Qrc;
- }
- // 标准LRC和增强型LRC
- else if (System.Text.RegularExpressions.Regex.IsMatch(content, @"\[\d{1,2}:\d{2}") ||
- System.Text.RegularExpressions.Regex.IsMatch(content, @"<\d{1,2}:\d{2}\.\d{2,3}>"))
- {
- return LyricsFormat.Lrc;
- }
- else
- {
- return null;
- }
- }
-
- public static string ToFileExtension(this LyricsFormat format)
- {
- return format switch
- {
- LyricsFormat.Lrc => ".lrc",
- LyricsFormat.Qrc => ".qrc",
- LyricsFormat.Krc => ".krc",
- LyricsFormat.Eslrc => ".eslrc",
- LyricsFormat.Ttml => ".ttml",
- _ => ".*",
- };
- }
-
- public static LyricsSearchProvider? ToLyricsSearchProvider(this LyricsFormat format)
- {
- return format switch
- {
- LyricsFormat.Lrc => LyricsSearchProvider.LocalLrcFile,
- LyricsFormat.Eslrc => LyricsSearchProvider.LocalEslrcFile,
- LyricsFormat.Ttml => LyricsSearchProvider.LocalTtmlFile,
- _ => null,
- };
- }
- }
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchProvider.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchProvider.cs
index cd58591..4f19ad7 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchProvider.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchProvider.cs
@@ -17,70 +17,4 @@ namespace BetterLyrics.WinUI3.Enums
LocalTtmlFile,
AppleMusic,
}
-
- public static class LyricsSearchProviderExtensions
- {
- public static string GetCacheDirectory(this LyricsSearchProvider provider)
- {
- return provider switch
- {
- LyricsSearchProvider.LrcLib => PathHelper.LrcLibLyricsCacheDirectory,
- LyricsSearchProvider.QQ => PathHelper.QQLyricsCacheDirectory,
- LyricsSearchProvider.Netease => PathHelper.NeteaseLyricsCacheDirectory,
- LyricsSearchProvider.Kugou => PathHelper.KugouLyricsCacheDirectory,
- LyricsSearchProvider.AmllTtmlDb => PathHelper.AmllTtmlDbLyricsCacheDirectory,
- LyricsSearchProvider.AppleMusic => PathHelper.AppleMusicCacheDirectory,
- _ => throw new System.ArgumentOutOfRangeException(nameof(provider)),
- };
- }
-
- public static LyricsFormat GetLyricsFormat(this LyricsSearchProvider provider)
- {
- return provider switch
- {
- LyricsSearchProvider.LrcLib => LyricsFormat.Lrc,
- LyricsSearchProvider.QQ => LyricsFormat.Qrc,
- LyricsSearchProvider.Kugou => LyricsFormat.Krc,
- LyricsSearchProvider.Netease => LyricsFormat.Lrc,
- LyricsSearchProvider.AmllTtmlDb => LyricsFormat.Ttml,
- LyricsSearchProvider.AppleMusic => LyricsFormat.Ttml,
- LyricsSearchProvider.LocalLrcFile => LyricsFormat.Lrc,
- LyricsSearchProvider.LocalEslrcFile => LyricsFormat.Eslrc,
- LyricsSearchProvider.LocalTtmlFile => LyricsFormat.Ttml,
- _ => LyricsFormat.NotSpecified,
- };
- }
-
- public static bool IsLocal(this LyricsSearchProvider provider)
- {
- return provider
- is LyricsSearchProvider.LocalMusicFile
- or LyricsSearchProvider.LocalLrcFile
- or LyricsSearchProvider.LocalEslrcFile
- or LyricsSearchProvider.LocalTtmlFile;
- }
-
- public static bool IsRemote(this LyricsSearchProvider provider)
- {
- return !provider.IsLocal();
- }
-
- public static TranslationSearchProvider? ToTranslationSearchProvider(this LyricsSearchProvider? provider)
- {
- return provider switch
- {
- LyricsSearchProvider.LrcLib => TranslationSearchProvider.LrcLib,
- LyricsSearchProvider.QQ => TranslationSearchProvider.QQ,
- LyricsSearchProvider.Kugou => TranslationSearchProvider.Kugou,
- LyricsSearchProvider.Netease => TranslationSearchProvider.Netease,
- LyricsSearchProvider.AmllTtmlDb => TranslationSearchProvider.AmllTtmlDb,
- LyricsSearchProvider.AppleMusic => TranslationSearchProvider.AppleMusic,
- LyricsSearchProvider.LocalMusicFile => TranslationSearchProvider.LocalMusicFile,
- LyricsSearchProvider.LocalLrcFile => TranslationSearchProvider.LocalLrcFile,
- LyricsSearchProvider.LocalEslrcFile => TranslationSearchProvider.LocalEslrcFile,
- LyricsSearchProvider.LocalTtmlFile => TranslationSearchProvider.LocalTtmlFile,
- _ => null,
- };
- }
- }
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchType.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchType.cs
new file mode 100644
index 0000000..e49f098
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Enums/LyricsSearchType.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Enums
+{
+ public enum LyricsSearchType
+ {
+ Sequential,
+ BestMatch
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsFormatExtensions.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsFormatExtensions.cs
new file mode 100644
index 0000000..eea2c84
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsFormatExtensions.cs
@@ -0,0 +1,37 @@
+using BetterLyrics.WinUI3.Enums;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Extensions
+{
+ public static class LyricsFormatExtensions
+ {
+ extension(LyricsFormat format)
+ {
+ public string ToFileExtension()
+ {
+ return format switch
+ {
+ LyricsFormat.Lrc => ".lrc",
+ LyricsFormat.Qrc => ".qrc",
+ LyricsFormat.Krc => ".krc",
+ LyricsFormat.Eslrc => ".eslrc",
+ LyricsFormat.Ttml => ".ttml",
+ _ => ".*",
+ };
+ }
+
+ public LyricsSearchProvider? ToLyricsSearchProvider()
+ {
+ return format switch
+ {
+ LyricsFormat.Lrc => LyricsSearchProvider.LocalLrcFile,
+ LyricsFormat.Eslrc => LyricsSearchProvider.LocalEslrcFile,
+ LyricsFormat.Ttml => LyricsSearchProvider.LocalTtmlFile,
+ _ => null,
+ };
+ }
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsSearchProviderExtensions.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsSearchProviderExtensions.cs
new file mode 100644
index 0000000..a725858
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/LyricsSearchProviderExtensions.cs
@@ -0,0 +1,62 @@
+using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Helper;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Extensions
+{
+ public static class LyricsSearchProviderExtensions
+ {
+ extension(LyricsSearchProvider provider)
+ {
+ public string GetCacheDirectory() => provider switch
+ {
+ LyricsSearchProvider.LrcLib => PathHelper.LrcLibLyricsCacheDirectory,
+ LyricsSearchProvider.QQ => PathHelper.QQLyricsCacheDirectory,
+ LyricsSearchProvider.Netease => PathHelper.NeteaseLyricsCacheDirectory,
+ LyricsSearchProvider.Kugou => PathHelper.KugouLyricsCacheDirectory,
+ LyricsSearchProvider.AmllTtmlDb => PathHelper.AmllTtmlDbLyricsCacheDirectory,
+ LyricsSearchProvider.AppleMusic => PathHelper.AppleMusicCacheDirectory,
+ _ => throw new ArgumentOutOfRangeException(nameof(provider)),
+ };
+
+ public LyricsFormat GetLyricsFormat() => provider switch
+ {
+ LyricsSearchProvider.LrcLib => LyricsFormat.Lrc,
+ LyricsSearchProvider.QQ => LyricsFormat.Qrc,
+ LyricsSearchProvider.Kugou => LyricsFormat.Krc,
+ LyricsSearchProvider.Netease => LyricsFormat.Lrc,
+ LyricsSearchProvider.AmllTtmlDb => LyricsFormat.Ttml,
+ LyricsSearchProvider.AppleMusic => LyricsFormat.Ttml,
+ LyricsSearchProvider.LocalLrcFile => LyricsFormat.Lrc,
+ LyricsSearchProvider.LocalEslrcFile => LyricsFormat.Eslrc,
+ LyricsSearchProvider.LocalTtmlFile => LyricsFormat.Ttml,
+ _ => LyricsFormat.NotSpecified,
+ };
+
+ public bool IsLocal() => provider
+ is LyricsSearchProvider.LocalMusicFile
+ or LyricsSearchProvider.LocalLrcFile
+ or LyricsSearchProvider.LocalEslrcFile
+ or LyricsSearchProvider.LocalTtmlFile;
+
+ public bool IsRemote() => !provider.IsLocal();
+
+ public TranslationSearchProvider? ToTranslationSearchProvider() => provider switch
+ {
+ LyricsSearchProvider.LrcLib => TranslationSearchProvider.LrcLib,
+ LyricsSearchProvider.QQ => TranslationSearchProvider.QQ,
+ LyricsSearchProvider.Kugou => TranslationSearchProvider.Kugou,
+ LyricsSearchProvider.Netease => TranslationSearchProvider.Netease,
+ LyricsSearchProvider.AmllTtmlDb => TranslationSearchProvider.AmllTtmlDb,
+ LyricsSearchProvider.AppleMusic => TranslationSearchProvider.AppleMusic,
+ LyricsSearchProvider.LocalMusicFile => TranslationSearchProvider.LocalMusicFile,
+ LyricsSearchProvider.LocalLrcFile => TranslationSearchProvider.LocalLrcFile,
+ LyricsSearchProvider.LocalEslrcFile => TranslationSearchProvider.LocalEslrcFile,
+ LyricsSearchProvider.LocalTtmlFile => TranslationSearchProvider.LocalTtmlFile,
+ _ => null,
+ };
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
index 282ec17..689cfb1 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/StringExtensions.cs
@@ -1,4 +1,5 @@
-using NTextCat.Commons;
+using BetterLyrics.WinUI3.Enums;
+using NTextCat.Commons;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -37,6 +38,47 @@ namespace BetterLyrics.WinUI3.Extensions
return [str];
}
}
+
+ public LyricsFormat? DetectFormat()
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ return null;
+
+ // TTML: 检查 ]*\bxmlns\s*=\s*[""']http://www\.w3\.org/ns/ttml[""']",
+ System.Text.RegularExpressions.RegexOptions.IgnoreCase))
+ {
+ return LyricsFormat.Ttml;
+ }
+ // KRC: 检测主内容格式 [start,duration]字...
+ else if (System.Text.RegularExpressions.Regex.IsMatch(
+ str,
+ @"^\[\d+,\d+\](<\d+,\d+,0>.+)+",
+ System.Text.RegularExpressions.RegexOptions.Multiline))
+ {
+ return LyricsFormat.Krc;
+ }
+ // QRC: 检测主内容格式 [start,duration]字(offset,duration)
+ else if (System.Text.RegularExpressions.Regex.IsMatch(
+ str,
+ @"^\[\d+,\d+\].*?\(\d+,\d+\)",
+ System.Text.RegularExpressions.RegexOptions.Multiline))
+ {
+ return LyricsFormat.Qrc;
+ }
+ // 标准LRC和增强型LRC
+ else if (System.Text.RegularExpressions.Regex.IsMatch(str, @"\[\d{1,2}:\d{2}") ||
+ System.Text.RegularExpressions.Regex.IsMatch(str, @"<\d{1,2}:\d{2}\.\d{2,3}>"))
+ {
+ return LyricsFormat.Lrc;
+ }
+ else
+ {
+ return null;
+ }
+ }
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs
index d3e3367..c200bfa 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FileHelper.cs
@@ -1,7 +1,10 @@
// 2025/6/23 by Zhe Fang
using BetterLyrics.WinUI3.Enums;
+using BetterLyrics.WinUI3.Extensions;
using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Models.Settings;
+using BetterLyrics.WinUI3.Serialization;
using System;
using System.IO;
using System.Text;
@@ -36,12 +39,17 @@ namespace BetterLyrics.WinUI3.Helper
return sb.ToString();
}
- public static string? ReadLyricsCache(SongInfo songInfo, LyricsFormat format, string cacheFolderPath)
+ public static LyricsSearchResult? ReadLyricsCache(SongInfo songInfo, LyricsSearchProvider lyricsSearchProvider)
{
- var cacheFilePath = Path.Combine(cacheFolderPath, SanitizeFileName($"{songInfo.DisplayArtists} - {songInfo.Title} - {songInfo.Album}{format.ToFileExtension()}"));
+ var cacheFilePath = Path.Combine(
+ lyricsSearchProvider.GetCacheDirectory(),
+ SanitizeFileName($"{songInfo.ToFileName()}.json"));
+
if (File.Exists(cacheFilePath))
{
- return File.ReadAllText(cacheFilePath);
+ var json = File.ReadAllText(cacheFilePath);
+ var data = System.Text.Json.JsonSerializer.Deserialize(json, SourceGenerationContext.Default.LyricsSearchResult);
+ return data;
}
return null;
}
@@ -56,10 +64,13 @@ namespace BetterLyrics.WinUI3.Helper
return null;
}
- public static void WriteLyricsCache(SongInfo songInfo, string lyrics, LyricsFormat format, string cacheFolderPath)
+ public static void WriteLyricsCache(SongInfo songInfo, LyricsSearchResult lyricsSearchResult)
{
- var cacheFilePath = Path.Combine(cacheFolderPath, SanitizeFileName($"{songInfo.DisplayArtists} - {songInfo.Title} - {songInfo.Album}{format.ToFileExtension()}"));
- File.WriteAllText(cacheFilePath, lyrics);
+ var cacheFilePath = Path.Combine(
+ lyricsSearchResult.Provider.GetCacheDirectory(),
+ SanitizeFileName($"{songInfo.ToFileName()}.json"));
+ var json = System.Text.Json.JsonSerializer.Serialize(lyricsSearchResult, SourceGenerationContext.Default.LyricsSearchResult);
+ File.WriteAllText(cacheFilePath, json);
}
public static void WriteAlbumArtCache(SongInfo songInfo, byte[] img, string format, string cacheFolderPath)
@@ -68,17 +79,6 @@ namespace BetterLyrics.WinUI3.Helper
File.WriteAllBytes(cacheFilePath, img);
}
- public static bool IsSwitchableNormalizedMatch(string fileName, string q1, string q2)
- {
- var normFileName = StringHelper.Normalize(fileName);
- var normQ1 = StringHelper.Normalize(q1);
- var normQ2 = StringHelper.Normalize(q2);
-
- // 常见两种顺序
- return normFileName == normQ1 + normQ2
- || normFileName == normQ2 + normQ1;
- }
-
public static readonly string[] MusicExtensions = {
".mp3", ".aac", ".m4a", ".ogg", ".opus", ".wma", ".amr",
".flac", ".alac", ".ape", ".wv", ".tak",
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
index d8df627..da5f548 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
@@ -17,98 +17,48 @@ namespace BetterLyrics.WinUI3.Helper
{
public List LyricsDataArr { get; private set; } = [];
- public void Parse(List mappedSongSearchQueries, Models.SongInfo songInfo, string? raw, LyricsSearchProvider? lyricsSearchProvider)
+ public void Parse(SongInfo? songInfo, LyricsSearchResult? lyricsSearchResult)
{
- var overridenTitle = songInfo.Title;
- var overridenArtist = songInfo.Artists;
- var overridenAlbum = songInfo.Album;
-
- var found = mappedSongSearchQueries
- .FirstOrDefault(x =>
- x.OriginalTitle == overridenTitle &&
- x.OriginalArtist == overridenArtist.Join(ATL.Settings.DisplayValueSeparator.ToString()) &&
- x.OriginalAlbum == overridenAlbum);
-
- if (found != null)
- {
- overridenTitle = found.MappedTitle;
- overridenArtist = found.MappedArtist.Split(ATL.Settings.DisplayValueSeparator);
- overridenAlbum = found.MappedAlbum;
- }
-
LyricsDataArr = [];
- if (raw == null)
+ if (lyricsSearchResult?.Raw == null)
{
- LyricsDataArr.Add(LyricsData.GetNotfoundPlaceholder((int)songInfo.DurationMs));
+ LyricsDataArr.Add(LyricsData.GetNotfoundPlaceholder((int)(songInfo?.DurationMs ?? 0)));
}
else
{
- switch (raw.DetectFormat())
+ switch (lyricsSearchResult.Raw.DetectFormat())
{
case LyricsFormat.Lrc:
case LyricsFormat.Eslrc:
- ParseLrc(raw);
+ ParseLrc(lyricsSearchResult.Raw);
break;
case LyricsFormat.Qrc:
- ParseQrcKrc(QrcParser.Parse(raw).Lines);
+ ParseQrcKrc(QrcParser.Parse(lyricsSearchResult.Raw).Lines);
break;
case LyricsFormat.Krc:
- ParseQrcKrc(KrcParser.Parse(raw).Lines);
+ ParseQrcKrc(KrcParser.Parse(lyricsSearchResult.Raw).Lines);
break;
case LyricsFormat.Ttml:
- ParseTtml(raw);
+ ParseTtml(lyricsSearchResult.Raw);
break;
default:
break;
}
}
FillRomanizationLyricsData();
- FillTranslationFromCache(
- ((SongInfo)songInfo.Clone())
- .WithTitle(overridenTitle)
- .WithArtist(overridenArtist)
- .WithAlbum(overridenAlbum),
- lyricsSearchProvider);
+ FillTranslationFromCache(lyricsSearchResult);
}
- private void FillTranslationFromCache(SongInfo songInfo, LyricsSearchProvider? provider)
+ private void FillTranslationFromCache(LyricsSearchResult? lyricsSearchResult)
{
- string? translationRaw = null;
- switch (provider)
+ if (lyricsSearchResult?.Translation != null)
{
- case LyricsSearchProvider.QQ:
- translationRaw = FileHelper.ReadLyricsCache(songInfo, LyricsFormat.Lrc, PathHelper.QQTranslationCacheDirectory);
- break;
- case LyricsSearchProvider.Kugou:
- translationRaw = FileHelper.ReadLyricsCache(songInfo, LyricsFormat.Lrc, PathHelper.KugouTranslationCacheDirectory);
- break;
- case LyricsSearchProvider.Netease:
- translationRaw = FileHelper.ReadLyricsCache(songInfo, LyricsFormat.Lrc, PathHelper.NeteaseTranslationCacheDirectory);
- break;
- case LyricsSearchProvider.LrcLib:
- break;
- case LyricsSearchProvider.AmllTtmlDb:
- break;
- case LyricsSearchProvider.LocalMusicFile:
- break;
- case LyricsSearchProvider.LocalLrcFile:
- break;
- case LyricsSearchProvider.LocalEslrcFile:
- break;
- case LyricsSearchProvider.LocalTtmlFile:
- break;
- default:
- break;
- }
-
- if (translationRaw != null)
- {
- switch (provider)
+ switch (lyricsSearchResult.Provider)
{
case LyricsSearchProvider.QQ:
case LyricsSearchProvider.Kugou:
case LyricsSearchProvider.Netease:
- ParseLrc(translationRaw);
+ ParseLrc(lyricsSearchResult.Translation);
break;
default:
break;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataComparer.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataComparer.cs
new file mode 100644
index 0000000..e04b908
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataComparer.cs
@@ -0,0 +1,96 @@
+using BetterLyrics.WinUI3.Models;
+using F23.StringSimilarity;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BetterLyrics.WinUI3.Helper
+{
+ public static class MetadataComparer
+ {
+ // 权重配置 (总和 1.0)
+ private const double WeightTitle = 0.40;
+ private const double WeightArtist = 0.40;
+ private const double WeightAlbum = 0.10;
+ private const double WeightDuration = 0.10;
+
+ // 实例化算法 (JaroWinkler 适合短字符串匹配)
+ private static readonly JaroWinkler _algo = new JaroWinkler();
+
+ ///
+ /// 计算 SongInfo 和 LyricsSearchResult 的相似度 (0-100)
+ ///
+ public static int CalculateScore(SongInfo local, LyricsSearchResult remote)
+ {
+ if (local == null || remote == null) return 0;
+
+ // 1. 标题相似度
+ double titleScore = GetStringSimilarity(local.Title, remote.Title);
+
+ // 2. 艺术家相似度 (需要处理数组顺序)
+ double artistScore = GetArtistSimilarity(local.Artists, remote.Artists);
+
+ // 3. 专辑相似度
+ double albumScore = GetStringSimilarity(local.Album, remote.Album);
+
+ // 4. 时长相似度 (基于毫秒 vs 秒的转换和容差)
+ double durationScore = GetDurationSimilarity(local.DurationMs, remote.Duration);
+
+ // 5. 加权汇总
+ double totalScore = (titleScore * WeightTitle) +
+ (artistScore * WeightArtist) +
+ (albumScore * WeightAlbum) +
+ (durationScore * WeightDuration);
+
+ return (int)Math.Round(totalScore * 100);
+ }
+
+ private static double GetStringSimilarity(string? s1, string? s2)
+ {
+ // 归一化:转小写,去空白
+ s1 = s1?.Trim().ToLowerInvariant() ?? "";
+ s2 = s2?.Trim().ToLowerInvariant() ?? "";
+
+ if (string.IsNullOrEmpty(s1) && string.IsNullOrEmpty(s2)) return 1.0; // 都是空,视为匹配
+ if (string.IsNullOrEmpty(s1) || string.IsNullOrEmpty(s2)) return 0.0; // 其中一个为空
+
+ return _algo.Similarity(s1, s2);
+ }
+
+ private static double GetArtistSimilarity(string[]? localArtists, string[]? remoteArtists)
+ {
+ if (localArtists == null || localArtists.Length == 0) return 0.0;
+ if (remoteArtists == null || remoteArtists.Length == 0) return 0.0;
+
+ // 技巧:将艺术家数组排序并连接,避免顺序不同导致的不匹配
+ // 例如: ["Jay-Z", "Linkin Park"] 和 ["Linkin Park", "Jay-Z"] 应该是一样的
+ var s1 = string.Join(" ", localArtists.OrderBy(a => a).Select(a => a.Trim().ToLowerInvariant()));
+ var s2 = string.Join(" ", remoteArtists.OrderBy(a => a).Select(a => a.Trim().ToLowerInvariant()));
+
+ return _algo.Similarity(s1, s2);
+ }
+
+ private static double GetDurationSimilarity(double localMs, double? remoteSeconds)
+ {
+ if (remoteSeconds == null || remoteSeconds == 0) return 0.0; // 远程没有时长数据,不匹配
+
+ double localSeconds = localMs / 1000.0;
+ double diff = Math.Abs(localSeconds - remoteSeconds.Value);
+
+ // 容差逻辑:
+ // 差距 <= 3秒:100% 相似
+ // 差距 >= 20秒:0% 相似
+ // 中间线性插值
+
+ const double PerfectTolerance = 3.0;
+ const double MaxTolerance = 20.0;
+
+ if (diff <= PerfectTolerance) return 1.0;
+ if (diff >= MaxTolerance) return 0.0;
+
+ // 线性递减公式
+ return 1.0 - ((diff - PerfectTolerance) / (MaxTolerance - PerfectTolerance));
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
index c84a5f0..cc4cbc1 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
@@ -14,9 +14,26 @@ namespace BetterLyrics.WinUI3.Helper
public static string SettingsFilePath => Path.Combine(SettingsDirectory, "settings.json");
public static string LanguageProfilePath => Path.Combine(AssetsFolder, "Wiki82.profile.xml");
-
- public static string AlbumArtPlaceholderPath => Path.Combine(AssetsFolder, "AlbumArtPlaceholder.png");
public static string LogoPath => Path.Combine(AssetsFolder, "Logo.ico");
+ public static string AlbumArtPlaceholderPath => Path.Combine(AssetsFolder, "AlbumArtPlaceholder.png");
+ public static string AIMPLogoPath => Path.Combine(AssetsFolder, "AIMP.png");
+ public static string Foobar2000LogoPath => Path.Combine(AssetsFolder, "foobar2000.png");
+ public static string MusicBeeLogoPath => Path.Combine(AssetsFolder, "MusicBee.png");
+ public static string SpotifyLogoPath => Path.Combine(AssetsFolder, "Spotify.png");
+ public static string AppleMusicLogoPath => Path.Combine(AssetsFolder, "AppleMusic.png");
+ public static string iTunesLogoPath => Path.Combine(AssetsFolder, "iTunes.png");
+ public static string KugouMusicLogoPath => Path.Combine(AssetsFolder, "KugouMusic.png");
+ public static string NetEaseCloudMusicLogoPath => Path.Combine(AssetsFolder, "NetEaseCloudMusic.png");
+ public static string QQMusicLogoPath => Path.Combine(AssetsFolder, "QQMusic.png");
+ public static string LXMusicLogoPath => Path.Combine(AssetsFolder, "LXMusic.png");
+ public static string MediaPlayerWindows11LogoPath => Path.Combine(AssetsFolder, "MediaPlayerWindows11.png");
+ public static string PotPlayerLogoPath => Path.Combine(AssetsFolder, "PotPlayer.png");
+ public static string ChromeLogoPath => Path.Combine(AssetsFolder, "Chrome.png");
+ public static string EdgeLogoPath => Path.Combine(AssetsFolder, "Edge.png");
+ public static string SaltPlayerForWindowsLogoPath => Path.Combine(AssetsFolder, "SaltPlayerForWindows.png");
+ public static string MoeKoeMusicLogoPath => Path.Combine(AssetsFolder, "MoeKoeMusic.png");
+ public static string Listen1LogoPath => Path.Combine(AssetsFolder, "Listen1.png");
+ public static string UnknownPlayerLogoPath => Path.Combine(AssetsFolder, "Question.png");
public static string LogDirectory => Path.Combine(CacheFolder, "logs");
public static string LogFilePattern => Path.Combine(LogDirectory, "log-.txt");
@@ -28,14 +45,9 @@ namespace BetterLyrics.WinUI3.Helper
public static string KugouLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "kugou");
public static string AmllTtmlDbLyricsCacheDirectory => Path.Combine(LyricsCacheDirectory, "amll-ttml-db");
public static string AppleMusicCacheDirectory => Path.Combine(LyricsCacheDirectory, "apple-music");
- public static string AmllTtmlDbIndexPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-index.json");
+ public static string AmllTtmlDbIndexPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-index.jsonl");
public static string AmllTtmlDbLastUpdatedPath => Path.Combine(LyricsCacheDirectory, "amll-ttml-db-last-updated.txt");
- public static string TranslationCacheDirectory => Path.Combine(CacheFolder, "translations");
- public static string QQTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "qq");
- public static string NeteaseTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "netease");
- public static string KugouTranslationCacheDirectory => Path.Combine(TranslationCacheDirectory, "kugou");
-
public static string AlbumArtCacheDirectory => Path.Combine(CacheFolder, "album-art");
public static string iTunesAlbumArtCacheDirectory => Path.Combine(AlbumArtCacheDirectory, "itunes");
@@ -54,11 +66,7 @@ namespace BetterLyrics.WinUI3.Helper
Directory.CreateDirectory(AmllTtmlDbLyricsCacheDirectory);
Directory.CreateDirectory(AppleMusicCacheDirectory);
- Directory.CreateDirectory(QQTranslationCacheDirectory);
- Directory.CreateDirectory(NeteaseTranslationCacheDirectory);
- Directory.CreateDirectory(KugouTranslationCacheDirectory);
-
Directory.CreateDirectory(iTunesAlbumArtCacheDirectory);
}
}
-}
+}
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIDHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIDHelper.cs
new file mode 100644
index 0000000..8023ee4
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIDHelper.cs
@@ -0,0 +1,86 @@
+using BetterLyrics.WinUI3.Constants;
+using Lyricify.Lyrics.Providers;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace BetterLyrics.WinUI3.Helper
+{
+ public static class PlayerIDHelper
+ {
+ private static readonly List neteaseFamilyRegex =
+ [
+ "cloudmusic.exe", //NetEaseCloudMusic
+ "^17588BrandonWong\\.LyricEase_", //LyricEase
+ "^48848aaaaaaccd\\.HyPlayer_" //HyPlayer
+ ];
+
+ public static bool IsNeteaseFamily(string? id)
+ {
+ if (id is null) return false;
+
+ foreach (var regex in neteaseFamilyRegex)
+ {
+ var isMatch = Regex.IsMatch(id, regex);
+ if (isMatch) return true;
+ }
+ return false;
+ }
+
+ public static bool IsLXMusic(string? id) => id is PlayerID.LXMusic or PlayerID.LXMusicPortable;
+
+ public static bool IsAppleMusic(string? id) => id is PlayerID.AppleMusic or PlayerID.AppleMusicAlternative;
+
+ public static string? GetDisplayName(string? id) => id switch
+ {
+ PlayerID.Spotify => PlayerName.Spotify,
+ PlayerID.AppleMusic => PlayerName.AppleMusic,
+ PlayerID.iTunes => PlayerName.iTunes,
+ PlayerID.KugouMusic => PlayerName.KugouMusic,
+ PlayerID.NetEaseCloudMusic => PlayerName.NetEaseCloudMusic,
+ PlayerID.QQMusic => PlayerName.QQMusic,
+ PlayerID.LXMusic => PlayerName.LXMusic,
+ PlayerID.LXMusicPortable => PlayerName.LXMusicPortable,
+ PlayerID.MediaPlayerWindows11 => PlayerName.MediaPlayerWindows11,
+ PlayerID.AIMP => PlayerName.AIMP,
+ PlayerID.Foobar2000 => PlayerName.Foobar2000,
+ PlayerID.MusicBee => PlayerName.MusicBee,
+ PlayerID.PotPlayer => PlayerName.PotPlayer,
+ PlayerID.Chrome => PlayerName.Chrome,
+ PlayerID.Edge => PlayerName.Edge,
+ PlayerID.BetterLyrics => PlayerName.BetterLyrics,
+ PlayerID.BetterLyricsDebug => PlayerName.BetterLyricsDebug,
+ PlayerID.SaltPlayerForWindows => PlayerName.SaltPlayerForWindows,
+ PlayerID.MoeKoeMusic => PlayerName.MoeKoeMusic,
+ PlayerID.MoeKoeMusicAlternative => PlayerName.MoeKoeMusic,
+ PlayerID.Listen1 => PlayerName.Listen1,
+ _ => id,
+ };
+
+ public static string GetLogoPath(string? id) => id switch
+ {
+ PlayerID.Spotify => PathHelper.SpotifyLogoPath,
+ PlayerID.AppleMusic => PathHelper.AppleMusicLogoPath,
+ PlayerID.AppleMusicAlternative => PathHelper.AppleMusicLogoPath,
+ PlayerID.iTunes => PathHelper.iTunesLogoPath,
+ PlayerID.KugouMusic => PathHelper.KugouMusicLogoPath,
+ PlayerID.NetEaseCloudMusic => PathHelper.NetEaseCloudMusicLogoPath,
+ PlayerID.QQMusic => PathHelper.QQMusicLogoPath,
+ PlayerID.LXMusic => PathHelper.LXMusicLogoPath,
+ PlayerID.LXMusicPortable => PathHelper.LXMusicLogoPath,
+ PlayerID.MediaPlayerWindows11 => PathHelper.MediaPlayerWindows11LogoPath,
+ PlayerID.AIMP => PathHelper.AIMPLogoPath,
+ PlayerID.Foobar2000 => PathHelper.Foobar2000LogoPath,
+ PlayerID.MusicBee => PathHelper.MusicBeeLogoPath,
+ PlayerID.PotPlayer => PathHelper.PotPlayerLogoPath,
+ PlayerID.Chrome => PathHelper.ChromeLogoPath,
+ PlayerID.Edge => PathHelper.EdgeLogoPath,
+ PlayerID.BetterLyrics => PathHelper.LogoPath,
+ PlayerID.BetterLyricsDebug => PathHelper.LogoPath,
+ PlayerID.SaltPlayerForWindows => PathHelper.SaltPlayerForWindowsLogoPath,
+ PlayerID.MoeKoeMusic => PathHelper.MoeKoeMusicLogoPath,
+ PlayerID.MoeKoeMusicAlternative => PathHelper.MoeKoeMusicLogoPath,
+ PlayerID.Listen1 => PathHelper.Listen1LogoPath,
+ _ => PathHelper.UnknownPlayerLogoPath,
+ };
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIdMatcher.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIdMatcher.cs
deleted file mode 100644
index a4a691f..0000000
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PlayerIdMatcher.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using BetterLyrics.WinUI3.Constants;
-using System.Collections.Generic;
-using System.Text.RegularExpressions;
-
-namespace BetterLyrics.WinUI3.Helper
-{
- public static class PlayerIDMatcher
- {
- private static readonly List neteaseFamilyRegex =
- [
- "cloudmusic.exe", //NetEaseCloudMusic
- "^17588BrandonWong\\.LyricEase_", //LyricEase
- "^48848aaaaaaccd\\.HyPlayer_" //HyPlayer
- ];
-
- public static bool IsNeteaseFamily(string? id)
- {
- if (id is null) return false;
-
- foreach (var regex in neteaseFamilyRegex)
- {
- var isMatch = Regex.IsMatch(id, regex);
- if (isMatch) return true;
- }
- return false;
- }
-
- public static bool IsLXMusic(string? id) => id is SpecialHandlePlayerID.LXMusic or SpecialHandlePlayerID.LXMusicPortable;
-
- public static bool IsAppleMusic(string? id) => id is SpecialHandlePlayerID.AppleMusic or SpecialHandlePlayerID.AppleMusicAlternative;
- }
-}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs
index 1ea2fed..d87c807 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/StringHelper.cs
@@ -11,5 +11,16 @@ namespace BetterLyrics.WinUI3.Helper
.ToArray())
.ToLowerInvariant();
public static string NewLine = "\n";
+
+ public static bool IsSwitchableNormalizedMatch(string source, string q1, string q2)
+ {
+ var normFileName = Normalize(source);
+ var normQ1 = Normalize(q1);
+ var normQ2 = Normalize(q2);
+
+ // 常见两种顺序
+ return normFileName == normQ1 + normQ2
+ || normFileName == normQ2 + normQ1;
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Hooks/AppHook.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Hooks/AppHook.cs
index 6d04369..5866d76 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Hooks/AppHook.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Hooks/AppHook.cs
@@ -31,6 +31,7 @@ namespace BetterLyrics.WinUI3.Hooks
if (hIconCopy.IsNull)
{
+ User32.DestroyIcon(hIconCopy);
return null;
}
else
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
index 8e1d4b0..567071b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsSearchResult.cs
@@ -1,17 +1,23 @@
using BetterLyrics.WinUI3.Enums;
+using CommunityToolkit.Mvvm.ComponentModel;
using NTextCat.Commons;
+using System;
namespace BetterLyrics.WinUI3.Models
{
- public class LyricsSearchResult
+ public partial class LyricsSearchResult : ObservableObject, ICloneable
{
- public LyricsSearchProvider? Provider { get; set; }
+ public LyricsSearchProvider Provider { get; set; }
public string? Raw { get; set; }
+ public string? Translation { get; set; }
public string? Title { get; set; }
public string[]? Artists { get; set; }
public string? Album { get; set; }
+ public double? Duration { get; set; }
+ [ObservableProperty] public partial int MatchPercentage { get; set; } = -1;
+ [ObservableProperty] public partial string Reference { get; set; } = "about:blank";
public bool IsFound => !string.IsNullOrEmpty(Raw);
@@ -19,6 +25,22 @@ namespace BetterLyrics.WinUI3.Models
public string? DisplayArtists => Artists?.Join("; ");
+ public object Clone()
+ {
+ return new LyricsSearchResult()
+ {
+ Album = this.Album,
+ Duration = this.Duration,
+ Raw = this.Raw,
+ Translation = this.Translation,
+ Title = this.Title,
+ Artists = this.Artists,
+ MatchPercentage = this.MatchPercentage,
+ Provider = this.Provider,
+ Reference = this.Reference
+ };
+ }
+
public void CopyFromSongInfo(SongInfo songInfo)
{
Title = songInfo.Title;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
index 4cb06af..1353d69 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
@@ -37,12 +37,13 @@ namespace BetterLyrics.WinUI3.Models
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection LyricsSearchProvidersInfo { get; set; } = [.. Enum.GetValues().Select(p => new LyricsSearchProviderInfo(p, true))];
[ObservableProperty][NotifyPropertyChangedRecipients] public partial FullyObservableCollection AlbumArtSearchProvidersInfo { get; set; } = [.. Enum.GetValues().Select(p => new AlbumArtSearchProviderInfo(p, true))];
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchType LyricsSearchType { get; set; } = LyricsSearchType.Sequential;
- [ObservableProperty] public partial BitmapImage? Logo { get; private set; }
+ public string LogoPath => PlayerIDHelper.GetLogoPath(Provider);
- public bool IsLXMusic => PlayerIDMatcher.IsLXMusic(Provider);
+ public string? DisplayName => PlayerIDHelper.GetDisplayName(Provider);
- [ObservableProperty] public partial string? DisplayName { get; private set; }
+ public bool IsLXMusic => PlayerIDHelper.IsLXMusic(Provider);
public MediaSourceProviderInfo()
{
@@ -56,7 +57,7 @@ namespace BetterLyrics.WinUI3.Models
IsEnabled = isEnable;
switch (provider)
{
- case Constants.SpecialHandlePlayerID.AppleMusic:
+ case Constants.PlayerID.AppleMusic:
// Apple Music 的特性
TimelineSyncThreshold = 1000;
PositionOffset = 1000;
@@ -112,43 +113,5 @@ namespace BetterLyrics.WinUI3.Models
{
OnPropertyChanged(nameof(LyricsSearchProvidersInfo));
}
-
- partial void OnProviderChanged(string value)
- {
- var dispatcherQueue = App.Current.Resources.DispatcherQueue;
-
- STATaskHelper.RunAsSTATask(() =>
- {
- var shellItem = AppHook.GetShellItem(Provider);
- if (shellItem != null)
- {
- var displayName = AppHook.GetDisplayName(shellItem);
-
- dispatcherQueue.TryEnqueue(async () =>
- {
- DisplayName = displayName;
- });
-
- var icon = AppHook.GetIcon(shellItem);
-
- shellItem.Dispose();
-
- if (icon != null)
- {
- dispatcherQueue.TryEnqueue(async () =>
- {
- Logo = await AppHook.ToBitmapImageAsync(icon.Value);
- });
- }
- }
- else
- {
- dispatcherQueue.TryEnqueue(async () =>
- {
- DisplayName = Provider;
- });
- }
- });
- }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
index f3ffc52..8f1b22e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/Settings/GeneralSettings.cs
@@ -12,6 +12,7 @@ namespace BetterLyrics.WinUI3.Models.Settings
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List ShowOrHideLyricsWindowShortcut { get; set; } = new List { "Ctrl", "Alt", "H" };
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ExitOnLyricsWindowClosed { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ListenOnNewPlaybackSource { get; set; } = true;
+ [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IgnoreCacheWhenSearching { get; set; } = false;
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List BorderlessShortcut { get; set; } = new List() { "Ctrl", "Alt", "B" };
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List ClickThroughShortcut { get; set; } = new List() { "Ctrl", "Alt", "C" };
[ObservableProperty][NotifyPropertyChangedRecipients] public partial List LyricsWindowSwitchShortcut { get; set; } = new List() { "Ctrl", "Alt", "S" };
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/SongInfo.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/SongInfo.cs
index e8efe1e..157919f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/SongInfo.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/SongInfo.cs
@@ -51,13 +51,18 @@ namespace BetterLyrics.WinUI3.Models
public override string ToString()
{
return
- $"Title: {Title}\n" +
- $"Artist: {Artists}\n" +
- $"Album: {Album}\n" +
- $"Duration: {Duration} sec\n" +
- $"Plauer ID: {PlayerId}\n" +
- $"Song ID: {SongId}\n" +
- $"Linked file name: {LinkedFileName}";
+ $"Title: {Title}, " +
+ $"Artist: {DisplayArtists}, " +
+ $"Album: {Album}, " +
+ $"Duration: {Duration} sec, " +
+ $"Plauer ID: {PlayerId}, " +
+ $"Song ID: {SongId}, " +
+ $"Linked file name: {LinkedFileName}.";
+ }
+
+ public string ToFileName()
+ {
+ return $"{DisplayArtists} - {Title} - {Album} - {Duration}";
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Providers/AppleMusic.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Providers/AppleMusic.cs
index f082559..8e51f05 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Providers/AppleMusic.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Providers/AppleMusic.cs
@@ -14,6 +14,7 @@ namespace BetterLyrics.WinUI3.Providers
private string _accessToken = "";
private string _storefront = "";
private string _language = "";
+ private bool _isInited = false;
public AppleMusic()
{
@@ -26,11 +27,18 @@ namespace BetterLyrics.WinUI3.Providers
public async Task InitAsync()
{
- await GetAccessTokenAsync();
- await SetMediaUserTokenAsync();
- return
- !string.IsNullOrEmpty(_accessToken) &&
- !string.IsNullOrEmpty(PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey));
+ if (!_isInited)
+ {
+ var mediaUserToken = PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey);
+ if (!string.IsNullOrEmpty(mediaUserToken))
+ {
+ await GetAccessTokenAsync();
+ await SetMediaUserTokenAsync(mediaUserToken);
+ _isInited = !string.IsNullOrEmpty(_accessToken);
+ }
+ }
+
+ return _isInited;
}
private async Task GetAccessTokenAsync()
@@ -47,11 +55,10 @@ namespace BetterLyrics.WinUI3.Providers
_client.DefaultRequestHeaders.Add("Authorization", $"Bearer {_accessToken}");
}
- private async Task SetMediaUserTokenAsync()
+ private async Task SetMediaUserTokenAsync(string token)
{
_client.DefaultRequestHeaders.Remove("media-user-token");
- _client.DefaultRequestHeaders.Add("media-user-token",
- PasswordVaultHelper.Get(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey));
+ _client.DefaultRequestHeaders.Add("media-user-token", token);
var resp = await _client.GetStringAsync("https://amp-api.music.apple.com/v1/me/storefront");
var json = JsonSerializer.Deserialize(resp, Serialization.SourceGenerationContext.Default.JsonElement);
_storefront = json.GetProperty("data")[0].GetProperty("id").ToString();
@@ -60,10 +67,8 @@ namespace BetterLyrics.WinUI3.Providers
_client.DefaultRequestHeaders.Add("Accept-Language", $"{_language},en;q=0.9");
}
- public async Task GetLyricsAsync(string title, string artist)
+ public async Task GetLyricsAsync(string id)
{
- string id = await SearchSongInfoAsync(artist, title);
-
var apiUrl = $"https://amp-api.music.apple.com/v1/catalog/{_storefront}/songs/{id}";
var url = apiUrl + $"?include[songs]=lyrics,syllable-lyrics&l={_language}";
var resp = await _client.GetStringAsync(url);
@@ -104,7 +109,7 @@ namespace BetterLyrics.WinUI3.Providers
return null;
}
- private async Task SearchSongInfoAsync(string artist, string title)
+ public async Task SearchSongInfoAsync(string artist, string title)
{
var query = $"{artist} {title}";
var apiUrl = $"https://amp-api.music.apple.com/v1/catalog/{_storefront}/search";
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Serialization/SourceGenerationContext.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Serialization/SourceGenerationContext.cs
index c33d1f0..8da78f9 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Serialization/SourceGenerationContext.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Serialization/SourceGenerationContext.cs
@@ -10,6 +10,7 @@ namespace BetterLyrics.WinUI3.Serialization
[JsonSerializable(typeof(TranslateResponse))]
[JsonSerializable(typeof(JsonElement))]
[JsonSerializable(typeof(AppSettings))]
+ [JsonSerializable(typeof(LyricsSearchResult))]
[JsonSourceGenerationOptions(WriteIndented = true)]
internal partial class SourceGenerationContext : JsonSerializerContext { }
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
index c7c4a22..fed2e82 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
@@ -88,7 +88,7 @@ namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
if (FileHelper.MusicExtensions.Contains(Path.GetExtension(file)))
{
Track track = new(file);
- if ((track.Title == songInfo.Title && track.Artist == songInfo.DisplayArtists) || FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), songInfo.DisplayArtists, songInfo.Title))
+ if ((track.Title == songInfo.Title && track.Artist == songInfo.DisplayArtists) || StringHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), songInfo.DisplayArtists, songInfo.Title))
{
var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData;
if (bytes != null)
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
index 0c3b0d1..701955b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
@@ -1,5 +1,6 @@
// 2025/6/23 by Zhe Fang
+using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Models;
using System.Collections.Generic;
using System.Threading;
@@ -9,8 +10,8 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
public interface ILyricsSearchService
{
- Task SearchSmartlyAsync(SongInfo songInfo, CancellationToken token);
+ Task SearchSmartlyAsync(SongInfo songInfo, bool checkCache, LyricsSearchType? lyricsSearchType, CancellationToken token);
- Task> SearchAllAsync(SongInfo songInfo, CancellationToken token);
+ Task> SearchAllAsync(SongInfo songInfo, bool checkCache, CancellationToken token);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
index 5ec1109..f9f40a2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
@@ -21,6 +21,7 @@ using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
+using System.Windows.Documents;
namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
@@ -91,8 +92,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
}
}
- public async Task SearchSmartlyAsync(SongInfo songInfo, CancellationToken token)
+ public async Task SearchSmartlyAsync(SongInfo songInfo, bool checkCache, LyricsSearchType? lyricsSearchType, CancellationToken token)
{
+ if (lyricsSearchType == null)
+ {
+ return null;
+ }
+
var lyricsSearchResult = new LyricsSearchResult();
string overridenTitle = songInfo.Title;
@@ -101,6 +107,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
_logger.LogInformation("SearchSmartlyAsync {SongInfo}", songInfo);
+ // 先检查该曲目是否已被用户映射
var found = _settingsService.AppSettings.MappedSongSearchQueries
.FirstOrDefault(x =>
x.OriginalTitle == overridenTitle &&
@@ -133,45 +140,63 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
.WithTitle(overridenTitle)
.WithArtist(overridenArtists)
.WithAlbum(overridenAlbum),
- targetProvider.Value, token);
+ targetProvider.Value, checkCache, token);
}
}
+ List lyricsSearchResults = [];
+
+ // 曲目没有被映射
foreach (var provider in _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == songInfo.PlayerId)?.LyricsSearchProvidersInfo ?? [])
{
if (!provider.IsEnabled)
{
continue;
}
+
lyricsSearchResult = await SearchSingleAsync(
((SongInfo)songInfo.Clone())
.WithTitle(overridenTitle)
.WithArtist(overridenArtists)
.WithAlbum(overridenAlbum),
- provider.Provider, token);
+ provider.Provider, checkCache, token);
if (lyricsSearchResult.IsFound)
{
- return lyricsSearchResult;
+ switch (lyricsSearchType)
+ {
+ case LyricsSearchType.Sequential:
+ return lyricsSearchResult;
+ case LyricsSearchType.BestMatch:
+ lyricsSearchResults.Add((LyricsSearchResult)lyricsSearchResult.Clone());
+ break;
+ default:
+ break;
+ }
}
}
- return lyricsSearchResult;
+ return lyricsSearchType switch
+ {
+ LyricsSearchType.Sequential => lyricsSearchResult,
+ LyricsSearchType.BestMatch => lyricsSearchResults.OrderByDescending(x => x.MatchPercentage).FirstOrDefault(),
+ _ => null,
+ };
}
- public async Task> SearchAllAsync(SongInfo songInfo, CancellationToken token)
+ public async Task> SearchAllAsync(SongInfo songInfo, bool checkCache, CancellationToken token)
{
_logger.LogInformation("SearchAllAsync {SongInfo}", songInfo);
var results = new List();
foreach (var provider in Enum.GetValues())
{
- var searchResult = await SearchSingleAsync(songInfo, provider, token);
+ var searchResult = await SearchSingleAsync(songInfo, provider, checkCache, token);
results.Add(searchResult);
}
return results;
}
- private async Task SearchSingleAsync(SongInfo songInfo, LyricsSearchProvider provider, CancellationToken token)
+ private async Task SearchSingleAsync(SongInfo songInfo, LyricsSearchProvider provider, bool checkCache, CancellationToken token)
{
var lyricsSearchResult = new LyricsSearchResult
{
@@ -182,14 +207,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
LyricsFormat lyricsFormat = provider.GetLyricsFormat();
- // Check cache first
- if (provider.IsRemote())
+ // Check cache first if allowed
+ if (checkCache && provider.IsRemote())
{
- var cachedLyrics = FileHelper.ReadLyricsCache(songInfo, lyricsFormat, provider.GetCacheDirectory());
- if (!string.IsNullOrWhiteSpace(cachedLyrics))
+ var cached = FileHelper.ReadLyricsCache(songInfo, provider);
+ if (cached != null)
{
- lyricsSearchResult.Raw = cachedLyrics;
- lyricsSearchResult.CopyFromSongInfo(songInfo);
+ lyricsSearchResult = cached;
return lyricsSearchResult;
}
}
@@ -234,30 +258,36 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
if (token.IsCancellationRequested)
{
+ lyricsSearchResult.MatchPercentage = MetadataComparer.CalculateScore(songInfo, lyricsSearchResult);
return lyricsSearchResult;
}
- if (lyricsSearchResult.IsFound)
- {
- if (provider.IsRemote())
- {
- FileHelper.WriteLyricsCache(songInfo, lyricsSearchResult.Raw!, lyricsFormat, provider.GetCacheDirectory());
- }
- }
}
catch (Exception)
{
}
+ lyricsSearchResult.MatchPercentage = MetadataComparer.CalculateScore(songInfo, lyricsSearchResult);
+
+ if (lyricsSearchResult.IsFound)
+ {
+ if (provider.IsRemote())
+ {
+ FileHelper.WriteLyricsCache(songInfo, lyricsSearchResult);
+ }
+ }
+
return lyricsSearchResult;
}
private async Task SearchFile(SongInfo songInfo, LyricsFormat format)
{
- var lyricsSearchResult = new LyricsSearchResult
+ var lyricsSearchResult = new LyricsSearchResult();
+
+ if (format.ToLyricsSearchProvider() is LyricsSearchProvider lyricsSearchProvider)
{
- Provider = format.ToLyricsSearchProvider(),
- };
+ lyricsSearchResult.Provider = lyricsSearchProvider;
+ }
foreach (var folder in _settingsService.AppSettings.LocalMediaFolders)
{
@@ -268,13 +298,14 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
foreach (var file in DirectoryHelper.GetAllFiles(folder.Path, $"*{format.ToFileExtension()}"))
{
var fileName = Path.GetFileNameWithoutExtension(file);
- if (FileHelper.IsSwitchableNormalizedMatch(fileName, songInfo.Title, songInfo.DisplayArtists) || songInfo.LinkedFileName == fileName)
+ if (StringHelper.IsSwitchableNormalizedMatch(fileName, songInfo.Title, songInfo.DisplayArtists) || songInfo.LinkedFileName == fileName)
{
string? raw = await File.ReadAllTextAsync(file, FileHelper.GetEncoding(file));
if (raw != null)
{
lyricsSearchResult.Raw = raw;
lyricsSearchResult.CopyFromSongInfo(songInfo);
+ lyricsSearchResult.Reference = file;
return lyricsSearchResult;
}
@@ -307,13 +338,14 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var track = new Track(file);
if ((songInfo.Album != "" && track.Title == songInfo.Title && track.Artist == songInfo.DisplayArtists && track.Album == songInfo.Album)
|| (songInfo.Album == "" && track.Title == songInfo.Title && track.Artist == songInfo.DisplayArtists)
- || (songInfo.Album == "" && FileHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), songInfo.Title, songInfo.DisplayArtists)))
+ || (songInfo.Album == "" && StringHelper.IsSwitchableNormalizedMatch(Path.GetFileNameWithoutExtension(file), songInfo.Title, songInfo.DisplayArtists)))
{
var plain = track.GetRawLyrics();
if (!plain.IsNullOrEmpty())
{
lyricsSearchResult.Raw = plain;
lyricsSearchResult.CopyFromSongInfo(songInfo);
+ lyricsSearchResult.Reference = file;
return lyricsSearchResult;
}
@@ -344,6 +376,10 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
string? rawLyricFile = null;
await foreach (var line in File.ReadLinesAsync(PathHelper.AmllTtmlDbIndexPath))
{
+ lyricsSearchResult.Title = null;
+ lyricsSearchResult.Artists = null;
+ lyricsSearchResult.Album = null;
+
if (string.IsNullOrWhiteSpace(line))
continue;
try
@@ -352,8 +388,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var root = doc.RootElement;
if (!root.TryGetProperty("metadata", out var metadataArr))
continue;
- string? musicName = null;
- string? artists = null;
+
foreach (var meta in metadataArr.EnumerateArray())
{
if (meta.GetArrayLength() != 2)
@@ -361,14 +396,14 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var key = meta[0].GetString();
var valueArr = meta[1];
if (key == "musicName" && valueArr.GetArrayLength() > 0)
- musicName = valueArr[0].GetString();
+ lyricsSearchResult.Title = valueArr[0].GetString();
if (key == "artists" && valueArr.GetArrayLength() > 0)
- artists = valueArr.EnumerateArray().Select(x=>x.GetString()).Join(ATL.Settings.DisplayValueSeparator.ToString());
+ lyricsSearchResult.Artists = valueArr.EnumerateArray().Select(x => x.GetString() ?? "").ToArray();
+ if (key == "album" && valueArr.GetArrayLength() > 0)
+ lyricsSearchResult.Album = valueArr[0].GetString();
}
- if (musicName == null || artists == null)
- continue;
- if (FileHelper.IsSwitchableNormalizedMatch($"{artists} - {musicName}", songInfo.Title, songInfo.DisplayArtists))
+ if (MetadataComparer.CalculateScore(songInfo, lyricsSearchResult) > 0)
{
if (root.TryGetProperty("rawLyricFile", out var rawLyricFileProp))
{
@@ -387,6 +422,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
// 下载歌词内容
var url = $"{_settingsService.AppSettings.GeneralSettings.AmllTtmlDbBaseUrl}/{Constants.AmllTTmlDB.QueryPrefix}/{rawLyricFile}";
+ lyricsSearchResult.Reference = url;
try
{
using var response = await _amllTtmlDbHttpClient.GetAsync(url);
@@ -397,9 +433,6 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
string lyrics = await response.Content.ReadAsStringAsync();
lyricsSearchResult.Raw = lyrics;
- lyricsSearchResult.Title = songInfo.Title;
- lyricsSearchResult.Artists = songInfo.Artists;
- lyricsSearchResult.Album = songInfo.Album;
}
catch
{
@@ -440,6 +473,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
string? searchedTitle = null;
string? searchedArtist = null;
string? searchedAlbum = null;
+ double? searchedDuration = null;
if (jArr.ValueKind == JsonValueKind.Array && jArr.GetArrayLength() > 0)
{
@@ -448,12 +482,16 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
searchedTitle = first.GetProperty("trackName").GetString();
searchedArtist = first.GetProperty("artistName").GetString();
searchedAlbum = first.GetProperty("albumName").GetString();
+ searchedDuration = first.GetProperty("duration").GetDouble();
}
lyricsSearchResult.Raw = original;
lyricsSearchResult.Title = searchedTitle;
- lyricsSearchResult.Artists = searchedArtist?.Split(ATL.Settings.DisplayValueSeparator);
+ lyricsSearchResult.Artists = searchedArtist?.SplitByCommonSplitter();
lyricsSearchResult.Album = searchedAlbum;
+ lyricsSearchResult.Duration = searchedDuration;
+
+ lyricsSearchResult.Reference = url;
return lyricsSearchResult;
}
@@ -493,7 +531,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
AlbumArtists = songInfo.Artists.ToList(),
Artists = songInfo.Artists.ToList(),
Title = songInfo.Title,
- }, searcher, Lyricify.Lyrics.Searchers.Helpers.CompareHelper.MatchType.Medium);
+ }, searcher, Lyricify.Lyrics.Searchers.Helpers.CompareHelper.MatchType.NoMatch);
}
if (result != null)
@@ -501,41 +539,24 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
if (result is QQMusicSearchResult qqResult)
{
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.QQMusicApi.GetLyricsAsync(qqResult.Id);
- var original = response?.Lyrics;
- var translated = response?.Trans;
- if (!string.IsNullOrEmpty(translated))
- {
- FileHelper.WriteLyricsCache(
- songInfo,
- translated,
- LyricsFormat.Lrc,
- PathHelper.QQTranslationCacheDirectory
- );
- }
- lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Raw = response?.Lyrics;
+ lyricsSearchResult.Translation = response?.Trans;
+ lyricsSearchResult.Reference = $"https://y.qq.com/n/ryqq/songDetail/{qqResult.Mid}";
}
else if (result is NeteaseSearchResult neteaseResult)
{
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.NeteaseApi.GetLyric(neteaseResult.Id);
- var original = response?.Lrc?.Lyric;
- var translated = response?.Tlyric?.Lyric;
- if (!string.IsNullOrEmpty(translated))
- {
- FileHelper.WriteLyricsCache(
- songInfo,
- translated,
- LyricsFormat.Lrc,
- PathHelper.NeteaseTranslationCacheDirectory
- );
- }
- lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Raw = response?.Lrc?.Lyric;
+ lyricsSearchResult.Translation = response?.Tlyric?.Lyric;
+ lyricsSearchResult.Reference = $"https://music.163.com/song?id={neteaseResult.Id}";
}
else if (result is KugouSearchResult kugouResult)
{
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.KugouApi.GetSearchLyrics(hash: kugouResult.Hash);
string? original = null;
+ string? translated = null;
var candidate = response?.Candidates.FirstOrDefault();
if (candidate != null)
{
@@ -545,7 +566,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
var parsedList = Lyricify.Lyrics.Parsers.KrcParser.ParseLyrics(original);
if (parsedList != null)
{
- string translated = "";
+ translated = "";
foreach (var item in parsedList)
{
if (item is Lyricify.Lyrics.Models.FullSyllableLineInfo fullSyllableLineInfo)
@@ -556,26 +577,20 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
translated += $"[{startTimeStr}]{chTranslation}\n";
}
}
- if (!string.IsNullOrEmpty(translated))
- {
- FileHelper.WriteLyricsCache(
- songInfo,
- translated,
- LyricsFormat.Lrc,
- PathHelper.KugouTranslationCacheDirectory
- );
- }
}
}
+ lyricsSearchResult.Reference = $"https://www.kugou.com/";
}
lyricsSearchResult.Raw = original;
+ lyricsSearchResult.Translation = translated;
}
}
lyricsSearchResult.Title = result?.Title;
lyricsSearchResult.Artists = result?.Artists;
lyricsSearchResult.Album = result?.Album;
+ lyricsSearchResult.Duration = result?.DurationMs / 1000;
return lyricsSearchResult;
}
@@ -589,12 +604,14 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
if (await _appleMusic.InitAsync())
{
- var raw = await _appleMusic.GetLyricsAsync(songInfo.Title, songInfo.DisplayArtists);
+ string id = await _appleMusic.SearchSongInfoAsync(songInfo.DisplayArtists, songInfo.Title);
+ string? raw = await _appleMusic.GetLyricsAsync(id);
_logger.LogInformation("SearchAppleMusicAsync");
lyricsSearchResult.Raw = raw;
lyricsSearchResult.Title = songInfo.Title;
lyricsSearchResult.Artists = songInfo.Artists;
lyricsSearchResult.Album = "";
+ lyricsSearchResult.Reference = $"https://music.apple.com/song/{id}";
}
return lyricsSearchResult;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
index a74a4f0..f9b9fa3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.LyricsUpdater.cs
@@ -158,13 +158,16 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
if (CurrentSongInfo != null)
{
- CurrentLyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(CurrentSongInfo, token), token);
+ CurrentLyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
+ CurrentSongInfo,
+ !_settingsService.AppSettings.GeneralSettings.IgnoreCacheWhenSearching,
+ CurrentMediaSourceProviderInfo?.LyricsSearchType,
+ token),
+ token);
if (token.IsCancellationRequested) return;
var lyricsParser = new LyricsParser();
- lyricsParser.Parse(
- _settingsService.AppSettings.MappedSongSearchQueries.ToList(),
- CurrentSongInfo, CurrentLyricsSearchResult?.Raw, CurrentLyricsSearchResult?.Provider);
+ lyricsParser.Parse(CurrentSongInfo, CurrentLyricsSearchResult);
_lyricsDataArr = lyricsParser.LyricsDataArr;
ApplyChinesePreference();
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
index a196092..0c21914 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
@@ -25,6 +25,7 @@ using CommunityToolkit.Mvvm.Messaging.Messages;
using CommunityToolkit.WinUI;
using DevWinUI;
using EvtSource;
+using Lyricify.Lyrics.Providers;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
using System;
@@ -32,6 +33,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
using Vanara.Windows.Shell;
using Windows.Media.Control;
@@ -180,6 +182,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
case nameof(MediaSourceProviderInfo.LyricsSearchProvidersInfo):
UpdateLyrics();
break;
+ case nameof(MediaSourceProviderInfo.LyricsSearchType):
+ UpdateLyrics();
+ break;
default:
break;
}
@@ -300,7 +305,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{
CurrentSongInfo = SongInfoExtensions.Placeholder;
- if (PlayerIDMatcher.IsLXMusic(sessionId))
+ if (PlayerIDHelper.IsLXMusic(sessionId))
{
StopSSE();
}
@@ -319,12 +324,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
string fixedAlbum = mediaProperties?.AlbumTitle ?? "N/A";
string? songId = null;
- if (PlayerIDMatcher.IsAppleMusic(sessionId))
+ if (PlayerIDHelper.IsAppleMusic(sessionId))
{
fixedArtist = mediaProperties?.Artist.Split(" — ").FirstOrDefault() ?? (mediaProperties?.Artist ?? "N/A");
fixedAlbum = mediaProperties?.Artist.Split(" — ").LastOrDefault() ?? (mediaProperties?.AlbumTitle ?? "N/A");
}
- else if (PlayerIDMatcher.IsNeteaseFamily(sessionId))
+ else if (PlayerIDHelper.IsNeteaseFamily(sessionId))
{
songId = mediaProperties?.Genres
.FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.NetEaseCloudMusicTrackID))?
@@ -349,7 +354,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
mediaProperties?.Title, mediaProperties?.Artist, mediaProperties?.AlbumTitle);
- if (PlayerIDMatcher.IsLXMusic(sessionId))
+ if (PlayerIDHelper.IsLXMusic(sessionId))
{
StartSSE();
}
@@ -358,7 +363,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
StopSSE();
}
- if (PlayerIDMatcher.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null)
+ if (PlayerIDHelper.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null)
{
_SMTCAlbumArtBuffer = _lxMusicAlbumArtBytes.AsBuffer();
}
@@ -551,7 +556,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
{
- if (PlayerIDMatcher.IsLXMusic(CurrentSongInfo?.PlayerId))
+ if (PlayerIDHelper.IsLXMusic(CurrentSongInfo?.PlayerId))
{
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
if (data.ValueKind == JsonValueKind.Number)
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
index ea09c1e..9557d5a 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
@@ -237,6 +237,9 @@
Lyrics Window Management Shortcut Settings
+
+ Match percentage
+
Play source shortcut settings
@@ -270,9 +273,15 @@
Artist
+
+ Duration
+
* Save changes take effect immediately, after which the track lyrics will be retrieved with mapping information and target lyrics; marking as pure music will directly return to pure music placeholder lyrics. Reset to retrieve by original data.
+
+ Ignore cache when searching
+
mapped as
@@ -907,6 +916,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Light
+
+ Linked local file
+
Enable monitoring for new playback sources
@@ -1039,9 +1051,21 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Right
+
+ Best match
+
Configure lyrics source
+
+ Sequential
+
+
+ In order: Find according to the priority of the list below and return the first lyrics found; Best Match: Search through all enabled lyrics sources and automatically select the best match
+
+
+ Lyrics search strategy
+
Semi Bold
@@ -1168,6 +1192,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Playback source
+
+ Playback source ID
+
Play "Cut To The Feeling" on "soundcloud.com"
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
index 5756f30..59435b9 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
@@ -237,6 +237,9 @@
歌詞ウィンドウ管理ショートカット設定
+
+ マッチ率
+
再生ソースクイック設定
@@ -270,9 +273,15 @@
アーティスト
+
+ 間隔
+
*保存変更はすぐに有効になります。その後、トラックの歌詞がマッピング情報とターゲット歌詞で取得されます。純粋な音楽としてのマーキングは、純粋な音楽プレースホルダーの歌詞に直接戻ります。元のデータで取得するためにリセット。
+
+ 検索時にキャッシュを無視してください
+
としてマッピングされました
@@ -907,6 +916,9 @@
ライト
+
+ リンクされたローカルファイル
+
新しい再生ソースの監視を有効にします
@@ -1039,9 +1051,21 @@
右
+
+ ベストマッチ
+
歌詞ソースを構成します
+
+ 順次処理
+
+
+ 順番:以下のリストの優先順位に従って検索し、最初に見つかった歌詞を返します。ベストマッチ:有効になっているすべての歌詞ソースを検索し、自動的に最適なものを選択します
+
+
+ 歌詞検索戦略
+
セミボールド
@@ -1168,6 +1192,9 @@
再生ソース
+
+ 再生ソースID
+
「SoundCloud.com」で「Cut to the Feeling」を再生する
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
index c84e996..ed4ee66 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
@@ -237,6 +237,9 @@
가사 창 관리 바로 가기 설정
+
+ 매치 퍼센트
+
재생 소스 빠른 설정
@@ -270,9 +273,15 @@
아티스트
+
+ 지속
+
* 변경 사항 저장 변경은 즉시 적용되며, 그 후 트랙 가사는 맵핑 정보와 대상 가사로 검색됩니다. 순수한 음악으로 표시하면 순수한 음악 자리 표시 자 가사로 직접 돌아갑니다. 원래 데이터로 검색하도록 재설정하십시오.
+
+ 검색 시 캐시를 무시하세요
+
로 매핑됨
@@ -907,6 +916,9 @@
빛
+
+ 연결된 로컬 파일
+
새로운 재생 소스에 대한 모니터링을 활성화하십시오
@@ -1039,9 +1051,21 @@
오른쪽
+
+ 최상의 검색 결과
+
가사 소스를 구성하십시오
+
+ 수열
+
+
+ 순서대로: 아래 목록의 우선 순위에 따라 찾아 발견된 첫 번째 가사를 반환합니다. 베스트 매치: 활성화된 모든 가사 소스를 검색하여 자동으로 가장 적합한 가사를 선택합니다
+
+
+ 가사 검색 전략
+
반 대담한
@@ -1168,6 +1192,9 @@
재생 소스
+
+ 재생 소스 ID
+
"soundcloud.com"에서 "Fut to the Feeling"을 재생하십시오.
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
index bb4ddc8..1d0da53 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
@@ -237,6 +237,9 @@
歌词窗口管理快捷设置
+
+ 匹配百分比
+
播放源快捷设置
@@ -270,9 +273,15 @@
艺术家
+
+ 时长
+
* 保存更改立即生效,此后将以映射信息和目标歌词源检索该曲目歌词;标记为纯音乐将直接返回纯音乐占位歌词。重置以按原始数据检索。
+
+ 搜索时忽略缓存
+
映射为
@@ -907,6 +916,9 @@
浅色
+
+ 链接的本地文件
+
启用对新播放源的监听
@@ -1039,9 +1051,21 @@
靠右
+
+ 最佳匹配
+
配置歌词源
+
+ 按顺序
+
+
+ 按顺序:依照下方列表的优先级依次查找,返回第一个找到的歌词; 最佳匹配:在所有已启用的歌词源中搜索,并自动选择匹配度最高的结果
+
+
+ 歌词搜索策略
+
次粗
@@ -1168,6 +1192,9 @@
播放源
+
+ 播放源 ID
+
在 “soundcloud.com” 上播放 “Cut to the Feeling”
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
index 1b53652..b5a698d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
@@ -237,6 +237,9 @@
歌詞視窗管理快捷設定
+
+ 匹配百分比
+
播放源快捷設置
@@ -270,9 +273,15 @@
藝術家
+
+ 時長
+
* 保存更改立即生效,此後將以映射信息和目標歌詞源檢索該曲目歌詞;標記為純音樂將直接返回純音樂佔位歌詞。重置以按原始數據檢索。
+
+ 搜尋時忽略快取
+
映射爲
@@ -907,6 +916,9 @@
淺色
+
+ 連結的本機檔案
+
啟用對新播放來源的監聽
@@ -1039,9 +1051,21 @@
靠右
+
+ 最佳匹配
+
配置歌詞源
+
+ 按順序
+
+
+ 依序:依照下方清單的優先順序依序查找,傳回第一個找到的歌詞;最佳符合:在所有已啟用的歌詞來源中搜尋,並自動選擇符合度最高的結果
+
+
+ 歌詞搜尋策略
+
次粗
@@ -1168,6 +1192,9 @@
播放源
+
+ 播放源 ID
+
在 “soundcloud.com” 上播放 “Cut to the Feeling”
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
index 8aac300..5eee60d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/AboutControlViewModel.cs
@@ -93,11 +93,6 @@ namespace BetterLyrics.WinUI3.ViewModels
DirectoryHelper.DeleteAllFiles(PathHelper.NeteaseLyricsCacheDirectory);
DirectoryHelper.DeleteAllFiles(PathHelper.QQLyricsCacheDirectory);
- DirectoryHelper.DeleteAllFiles(PathHelper.TranslationCacheDirectory);
- DirectoryHelper.DeleteAllFiles(PathHelper.KugouTranslationCacheDirectory);
- DirectoryHelper.DeleteAllFiles(PathHelper.NeteaseTranslationCacheDirectory);
- DirectoryHelper.DeleteAllFiles(PathHelper.QQTranslationCacheDirectory);
-
DirectoryHelper.DeleteAllFiles(PathHelper.iTunesAlbumArtCacheDirectory);
DevWinUI.Growl.Success(_resourceService.GetLocalizedString("ActionCompleted"));
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs
index 802445a..26fd57d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsSearchControlViewModel.cs
@@ -113,11 +113,14 @@ namespace BetterLyrics.WinUI3.ViewModels
{
LyricsSearchResults = [..await Task.Run(async () =>
{
- return await _lyricsSearchService.SearchAllAsync(
+ var result = await _lyricsSearchService.SearchAllAsync(
((SongInfo?)_mediaSessionsService.CurrentSongInfo?.Clone() ?? new())
.WithTitle(MappedSongSearchQuery.MappedTitle)
.WithArtist(MappedSongSearchQuery.MappedArtist.SplitByCommonSplitter())
- .WithAlbum(MappedSongSearchQuery.MappedAlbum), token);
+ .WithAlbum(MappedSongSearchQuery.MappedAlbum),
+ !_settingsService.AppSettings.GeneralSettings.IgnoreCacheWhenSearching,
+ token);
+ return result;
}, token)];
IsSearching = false;
});
@@ -176,10 +179,7 @@ namespace BetterLyrics.WinUI3.ViewModels
if (value?.Raw != null)
{
var lyricsParser = new LyricsParser();
- lyricsParser.Parse(
- [MappedSongSearchQuery ?? new()],
- _mediaSessionsService.CurrentSongInfo,
- value?.Raw, value?.Provider);
+ lyricsParser.Parse(_mediaSessionsService.CurrentSongInfo, value);
LyricsDataArr = [.. lyricsParser.LyricsDataArr];
}
else