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