diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
index 5e5a7db..a3954a6 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="1.0.45.0" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
index 45c5045..0e44b3f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml
@@ -51,6 +51,8 @@
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
index 4a77ff9..92c1a19 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
@@ -3,7 +3,16 @@
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.LyricsSearchService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
+using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.ViewModels;
+using BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel;
+using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
@@ -64,7 +73,7 @@ namespace BetterLyrics.WinUI3
private void EnsureSingleInstance()
{
bool createdNew;
- _instanceMutex = new Mutex(true, MetadataHelper.AppName, out createdNew);
+ _instanceMutex = new Mutex(true, Constants.App.AppName, out createdNew);
if (!createdNew)
{
@@ -102,11 +111,12 @@ namespace BetterLyrics.WinUI3
})
// Services
.AddSingleton()
- .AddSingleton()
+ .AddSingleton()
.AddSingleton()
.AddSingleton()
.AddSingleton()
.AddSingleton()
+ .AddSingleton()
// ViewModels
.AddSingleton()
.AddSingleton()
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/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/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/LastFM.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/LastFM.png
new file mode 100644
index 0000000..938c17d
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/LastFM.png differ
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Leaf.png b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Leaf.png
new file mode 100644
index 0000000..699cd55
Binary files /dev/null and b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Leaf.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/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/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/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 0f1ebb1..b04ef3b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj
@@ -53,8 +53,8 @@
-
-
+
+
@@ -65,8 +65,8 @@
-
-
+
+
@@ -78,6 +78,11 @@
+
+
+ ..\..\..\Last.fm\src\Hqub.Lastfm\bin\Release\netstandard2.0\Hqub.Lastfm.dll
+
+
MSBuild:Compile
@@ -93,27 +98,78 @@
+
+ Always
+
+
+ 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/AmllTTmlDB.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/AmllTTmlDB.cs
new file mode 100644
index 0000000..a20ff9b
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/AmllTTmlDB.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class AmllTTmlDB
+ {
+ private const string BaseUrl = "https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/";
+ public const string QueryPrefix = $"{BaseUrl}raw-lyrics/";
+ public const string Index = $"{BaseUrl}metadata/raw-lyrics-index.jsonl";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/App.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/App.cs
new file mode 100644
index 0000000..0a9110a
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/App.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class App
+ {
+ public const string AppAuthor = "Zhe Fang";
+ public const string AppName = "BetterLyrics";
+
+ public const string AutoStartupTaskId = "AutoStartup";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LXMusic.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LXMusic.cs
new file mode 100644
index 0000000..d16ddee
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LXMusic.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class LXMusic
+ {
+ public const string QuerySuffix = "/subscribe-player-status?filter=progress,duration";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LastFMTemplate b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LastFMTemplate
new file mode 100644
index 0000000..fffc31e
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/LastFMTemplate
@@ -0,0 +1,9 @@
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class LastFM
+ {
+ public const string ApiKey = "Your api key here";
+ public const string SharedSecret = "Your shared secret here";
+ public const string UnAuthUrl = "https://www.last.fm/settings/applications";
+ }
+}
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Link.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Link.cs
new file mode 100644
index 0000000..f121b36
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Link.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class Link
+ {
+ public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics";
+ public const string QQGroupUrl = "https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info";
+ public const string DiscordUrl = "https://discord.gg/5yAQPnyCKv";
+ public const string TelegramUrl = "https://t.me/+svhSLZ7awPsxNGY1";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs
new file mode 100644
index 0000000..82e6347
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerID.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.ApplicationModel;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class PlayerID
+ {
+ public const string LXMusic = "cn.toside.music.desktop";
+ 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 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";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs
new file mode 100644
index 0000000..35a3960
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/PlayerName.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public class PlayerName
+ {
+ public const string LXMusic = "LX Music";
+ 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 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)";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Time.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Time.cs
new file mode 100644
index 0000000..1d5ad53
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/Time.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class Time
+ {
+ public static readonly TimeSpan DebounceTimeout = TimeSpan.FromMilliseconds(300);
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/iTunes.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/iTunes.cs
new file mode 100644
index 0000000..dd61c97
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Constants/iTunes.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Constants
+{
+ public static class iTunes
+ {
+ public const string QueryPrefix = "https://itunes.apple.com/search?";
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/LyricsSearchProviderToDisplayNameConverter.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/LyricsSearchProviderToDisplayNameConverter.cs
index cadcebf..54b671d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/LyricsSearchProviderToDisplayNameConverter.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/LyricsSearchProviderToDisplayNameConverter.cs
@@ -15,9 +15,9 @@ namespace BetterLyrics.WinUI3.Converter
return provider switch
{
LyricsSearchProvider.LrcLib => "LrcLib",
- LyricsSearchProvider.QQ => "QQ",
- LyricsSearchProvider.Netease => "Netease",
- LyricsSearchProvider.Kugou => "Kugou",
+ LyricsSearchProvider.QQ => "QQ 音乐",
+ LyricsSearchProvider.Netease => "网易云音乐",
+ LyricsSearchProvider.Kugou => "酷狗音乐",
LyricsSearchProvider.AmllTtmlDb => "amll-ttml-db",
LyricsSearchProvider.LocalLrcFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalLrcFile"),
LyricsSearchProvider.LocalMusicFile => App.ResourceLoader!.GetString("LyricsSearchProviderLocalMusicFile"),
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToDisplayedNameConverter.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToDisplayedNameConverter.cs
new file mode 100644
index 0000000..ebb3fbc
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToDisplayedNameConverter.cs
@@ -0,0 +1,47 @@
+using BetterLyrics.WinUI3.Constants;
+using BetterLyrics.WinUI3.Helper;
+using Microsoft.UI.Xaml.Data;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Converter
+{
+ public class MediaSourceProviderToDisplayedNameConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value is string provider)
+ {
+ return provider 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.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,
+ _ => provider,
+ };
+ }
+ return value?.ToString() ?? "";
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToLogoUriConverter.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToLogoUriConverter.cs
new file mode 100644
index 0000000..4f424fc
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Converter/MediaSourceProviderToLogoUriConverter.cs
@@ -0,0 +1,47 @@
+using BetterLyrics.WinUI3.Constants;
+using BetterLyrics.WinUI3.Helper;
+using Microsoft.UI.Xaml.Data;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Converter
+{
+ public class MediaSourceProviderToLogoUriConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, string language)
+ {
+ if (value is string provider)
+ {
+ return provider switch
+ {
+ PlayerID.Spotify => PathHelper.SpotifyLogoPath,
+ PlayerID.AppleMusic => PathHelper.AppleMusicLogoPath,
+ PlayerID.iTunes => PathHelper.iTunesLogoPath,
+ PlayerID.KugouMusic => PathHelper.KugouMusicLogoPath,
+ PlayerID.NetEaseCloudMusic => PathHelper.NetEaseCloudMusicLogoPath,
+ PlayerID.QQMusic => PathHelper.QQMusicLogoPath,
+ PlayerID.LXMusic => 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,
+ _ => PathHelper.UnknownPlayerLogoPath,
+ };
+ }
+ return PathHelper.UnknownPlayerLogoPath;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, string language)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/AlbumArtChangedEventArgs.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/AlbumArtChangedEventArgs.cs
index 5c2403e..f19b09f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/AlbumArtChangedEventArgs.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/AlbumArtChangedEventArgs.cs
@@ -8,8 +8,9 @@ using Windows.UI;
namespace BetterLyrics.WinUI3.Events
{
- public class AlbumArtChangedEventArgs(SoftwareBitmap? albumArtSwBitmap, Color? albumArtLightAccentColor, Color? albumArtDarkAccentColor) : EventArgs
+ public class AlbumArtChangedEventArgs(byte[]? bytes, SoftwareBitmap? albumArtSwBitmap, Color? albumArtLightAccentColor, Color? albumArtDarkAccentColor) : EventArgs
{
+ public byte[]? Bytes { get; set; } = bytes;
public SoftwareBitmap? AlbumArtSwBitmap { get; set; } = albumArtSwBitmap;
public Color? AlbumArtLightAccentColor { get; set; } = albumArtLightAccentColor;
public Color? AlbumArtDarkAccentColor { get; set; } = albumArtDarkAccentColor;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMIsAuthenticatedChangedEventArgs.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMIsAuthenticatedChangedEventArgs.cs
new file mode 100644
index 0000000..175a8b5
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMIsAuthenticatedChangedEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Events
+{
+ public class LastFMIsAuthenticatedChangedEventArgs : EventArgs
+ {
+ public bool IsAuthenticated { get; set; }
+ public LastFMIsAuthenticatedChangedEventArgs(bool isAuthenticated)
+ {
+ IsAuthenticated = isAuthenticated;
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMUserChangedEventArgs.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMUserChangedEventArgs.cs
new file mode 100644
index 0000000..d838ba9
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/LastFMUserChangedEventArgs.cs
@@ -0,0 +1,18 @@
+using Hqub.Lastfm.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Events
+{
+ public class LastFMUserChangedEventArgs : EventArgs
+ {
+ public User? User { get; set; }
+ public LastFMUserChangedEventArgs(User? user)
+ {
+ User = user;
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs
index 916ca3c..41c61c3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DesktopModeHelper.cs
@@ -1,5 +1,5 @@
using BetterLyrics.WinUI3.Enums;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DockModeHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DockModeHelper.cs
index f1899b8..07b999b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DockModeHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/DockModeHelper.cs
@@ -1,5 +1,5 @@
using BetterLyrics.WinUI3.Enums;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.WinUI;
using Microsoft.UI.Xaml;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FontHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FontHelper.cs
index ae52cc2..abeea6f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FontHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/FontHelper.cs
@@ -1,4 +1,4 @@
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.Graphics.Canvas.Text;
using System;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
index d9941b0..58c5463 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ImageHelper.cs
@@ -6,6 +6,7 @@ using Microsoft.Graphics.Canvas.Text;
using Microsoft.UI;
using Microsoft.UI.Xaml.Media.Imaging;
using SixLabors.ImageSharp;
+using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@@ -168,34 +169,55 @@ namespace BetterLyrics.WinUI3.Helper
var themeColor = Rgba32.ParseHex(GetAccentColorsFromByte(imageBytes, 1).FirstOrDefault().ToHex());
- // 新建正方形画布
using var square = new Image(size, size, themeColor);
- // 计算居中位置
int offsetX = (size - image.Width) / 2;
int offsetY = (size - image.Height) / 2;
- // 绘制原图到正方形画布
square.Mutate(ctx => ctx.DrawImage(image, new Point(offsetX, offsetY), 1f));
- // 保存为 PNG 字节流
using var ms = new MemoryStream();
- square.Save(ms, new PngEncoder());
+ square.Save(ms, new JpegEncoder());
return ms.ToArray();
}
public static byte[] Resize(byte[] imageBytes, int size)
{
- using Image image = Image.Load(imageBytes);
- var factor = Math.Max((float)size / image.Width, (float)size / image.Height);
+ using (Image image = Image.Load(imageBytes))
+ {
+ var factor = Math.Max((float)size / image.Width, (float)size / image.Height);
- int width = (int)(image.Width * factor);
- int height = (int)(image.Height * factor);
- image.Mutate(x => x.Resize(width, height, KnownResamplers.Welch));
+ int width = (int)(image.Width * factor);
+ int height = (int)(image.Height * factor);
- using var ms = new MemoryStream();
- image.Save(ms, new PngEncoder());
- return ms.ToArray();
+ if (factor > 1)
+ {
+ image.Mutate(x => x.Resize(width, height, KnownResamplers.Welch));
+ }
+ else
+ {
+ image.Mutate(x => x.Resize(width, height, KnownResamplers.NearestNeighbor));
+ }
+
+ using var ms = new MemoryStream();
+ image.Save(ms, new JpegEncoder());
+ return ms.ToArray();
+ }
+ }
+
+ public static byte[] GenerateNoiseBGRA(int width, int height)
+ {
+ var random = new Random();
+ var pixelData = new byte[width * height * 4];
+ for (int i = 0; i < width * height; i++)
+ {
+ byte gray = (byte)random.Next(0, 256);
+ pixelData[i * 4 + 0] = gray; // B
+ pixelData[i * 4 + 1] = gray; // G
+ pixelData[i * 4 + 2] = gray; // R
+ pixelData[i * 4 + 3] = 255; // A
+ }
+ return pixelData;
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
index fd16dc2..c1bd26f 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LanguageHelper.cs
@@ -1,4 +1,5 @@
using BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Lyricify.Lyrics.Helpers.General;
using NTextCat;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs
index d3ab08b..57f9db3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/MetadataHelper.cs
@@ -14,9 +14,6 @@ namespace BetterLyrics.WinUI3.Helper
public static class MetadataHelper
{
- public const string AppAuthor = "Zhe Fang";
- public const string AppDisplayName = "Better Lyrics";
- public const string AppName = "BetterLyrics";
public static string AppVersion
{
get
@@ -25,24 +22,5 @@ namespace BetterLyrics.WinUI3.Helper
return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
}
}
-
- public const string GithubUrl = "https://github.com/jayfunc/BetterLyrics";
- public const string QQGroupUrl = "https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info";
- public const string DiscordUrl = "https://discord.gg/5yAQPnyCKv";
- public const string TelegramUrl = "https://t.me/+svhSLZ7awPsxNGY1";
-
- public static async Task GetBuildDate()
- {
- var assembly = Assembly.GetExecutingAssembly();
- var filePath = assembly.Location;
- if (!File.Exists(filePath))
- return DateTime.MinValue;
-
- StorageFile file = await StorageFile.GetFileFromPathAsync(filePath);
- // 获取文件基本属性
- BasicProperties props = await file.GetBasicPropertiesAsync();
- // 返回修改日期
- return props.DateModified.DateTime;
- }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NoiseGenerationHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NoiseGenerationHelper.cs
deleted file mode 100644
index 02b7a41..0000000
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/NoiseGenerationHelper.cs
+++ /dev/null
@@ -1,331 +0,0 @@
-using System;
-using System.Buffers;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Text.RegularExpressions;
-using System.Threading.Tasks;
-using Windows.Storage;
-using static BetterLyrics.WinUI3.Helper.NoiseOverlayHelper.BitmapFileCreator;
-
-namespace BetterLyrics.WinUI3.Helper
-{
- internal static class NoiseOverlayHelper
- {
-
- const string NoiseOverlayFileName = "noise_overlay.bmp";
-
- static readonly string NoiseOverlayFilePath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "Assets", NoiseOverlayFileName);
-
- ///
- /// 生成 BGRA 格式的灰阶噪声像素数据
- ///
- public static byte[] GenerateNoiseBitmapBGRA(int width, int height)
- {
- var random = new Random();
- var pixelData = new byte[width * height * 4];
- for (int i = 0; i < width * height; i++)
- {
- byte gray = (byte)random.Next(0, 256);
- pixelData[i * 4 + 0] = gray; // B
- pixelData[i * 4 + 1] = gray; // G
- pixelData[i * 4 + 2] = gray; // R
- pixelData[i * 4 + 3] = 255; // A
- }
- return pixelData;
- }
-
- ///
- /// 生成单色灰阶随机噪声
- ///
- /// 输出文件路径
- /// 图片宽度
- /// 图片高度
- public static BitmapFile GenerateNoiseBitmap(int width, int height)
- {
- const uint NumOfGrayscale = 16;
- uint bitCount = NextPowerOfTwo((uint)Math.Round(Math.Sqrt(NumOfGrayscale)));
-
- var palette = BitmapFileCreator.CreateGrayscalePalette(16);
- var pixelData = GenerateRandomNoise(width, height, bitCount);
-
- var fileHeader = BitmapFileCreator.CreateFileHeader(palette, pixelData);
- var infoHeader = BitmapFileCreator.CreateInfoHeader(width, height, bitCount);
-
- return new BitmapFile(fileHeader, infoHeader, palette, pixelData);
- }
-
- ///
- /// 读取噪声图片的位头信息
- ///
- public static BitmapFileCreator.WINBMPINFOHEADER ReadBitmapInfoHeaders(string? FilePath)
- {
- var _filePath = FilePath ?? NoiseOverlayFilePath;
- using var fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
- using var br = new BinaryReader(fs);
-
- // 跳过文件头
- fs.Seek(Marshal.SizeOf(), SeekOrigin.Begin);
-
- // 读取信息头
- byte[] infoHeaderBytes = br.ReadBytes(Marshal.SizeOf());
- return MemoryMarshal.Read(infoHeaderBytes);
- }
-
- public static BitmapFileCreator.WINBMPINFOHEADER ReadBitmapInfoHeaders(byte[] FileBytes)
- {
- // 跳过文件头
- var offset = Marshal.SizeOf();
-
- // 读取信息头
- var infoHeaderLength = Marshal.SizeOf();
- Span infoHeaderBytes = new(FileBytes, offset, infoHeaderLength);
- return MemoryMarshal.Read(infoHeaderBytes);
- }
-
- ///
- /// safe 的写入 struct 到流
- ///
- /// 值 strcut
- /// 要写入的字节流
- /// 要被写入的结构
- public static void WriteStruct(Stream stream, in T structure) where T : struct
- {
- int size = Unsafe.SizeOf();
- byte[] buffer = ArrayPool.Shared.Rent(size);
- try
- {
- MemoryMarshal.Write(buffer, in structure);
- stream.Write(buffer, 0, size);
- }
- finally
- {
- ArrayPool.Shared.Return(buffer);
- }
- }
-
- ///
- /// 随机填充位图内容
- ///
- /// 填充宽度
- /// 填充高度
- /// 单个调色盘索引所占比特位数
- /// 字节数据
- private static byte[] GenerateRandomNoise(int width, int height, uint bitCount)
- {
- // 创建位图行字节数,4K 对齐
- int rowSize = ((width * (int)bitCount + 31) >> 5) << 2;
-
- // 创建随机位图数据
- Random rnd = new();
- return Enumerable.Range(0, rowSize * height)
- .Select(i => (byte)rnd.Next(0x00, 0xFF))
- .ToArray();
- }
-
- private static uint NextPowerOfTwo(uint value)
- {
- value--;
- value |= value >> 1;
- value |= value >> 2;
- value |= value >> 4;
- value |= value >> 8;
- value |= value >> 16;
- return value + 1;
- }
- public static class BitmapFileCreator
- {
-
- ///
- /// 创建BMP文件头
- ///
- /// 调色盘数据
- /// 像素数据
- /// 文件头结构
- public static BITMAPFILEHEADER CreateFileHeader(byte[] palette, byte[] pixelData)
- {
- return new BITMAPFILEHEADER
- {
- bfType = 0x4D42,
- bfSize = (uint)(Marshal.SizeOf() +
- Marshal.SizeOf() +
- palette.Length +
- pixelData.Length),
- bfReserved1 = 0,
- bfReserved2 = 0,
- bfOffBits = (uint)(Marshal.SizeOf() +
- Marshal.SizeOf() +
- palette.Length)
- };
- }
-
- ///
- /// 将指定值填充到为最接近的2的幂数
- ///
- ///
- /// 生成灰阶调色盘
- ///
- /// 灰阶数量
- /// 调色盘byte数组
- public static byte[] CreateGrayscalePalette(int colors)
- {
- return Enumerable.Range(0, colors)
- .SelectMany(i => Enumerable.Repeat((byte)(i * 0x10), 4))
- .ToArray();
- }
-
- ///
- /// 创建BMP信息头
- ///
- /// 宽度
- /// 高度
- /// 单个像素(调色盘索引)位数
- /// BMP信息头结构
- public static WINBMPINFOHEADER CreateInfoHeader(int width, int height, uint bitCount)
- {
- return new WINBMPINFOHEADER
- {
- biSize = (uint)Marshal.SizeOf(),
- biWidth = (uint)width,
- biHeight = (uint)height,
- biPlanes = 1,
- biBitCount = (ushort)bitCount,
- biCompression = 0,
- biSizeImage = 0,
- biXPelsPerMeter = 0,
- biYPelsPerMeter = 0,
- biClrUsed = 0,
- biClrImportant = 0
- };
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- ///
- /// BMP 位图文件头
- ///
- public struct BITMAPFILEHEADER
- {
- ///
- /// 文件类型标识,用于指定文件格式
- ///
- public ushort bfType;
- ///
- /// 文件大小,以字节为单位
- ///
- public uint bfSize;
- ///
- /// 保留字段,未使用
- ///
- public ushort bfReserved1;
- ///
- /// 保留字段,未使用
- ///
- public ushort bfReserved2;
- ///
- /// 像素数据的起始位置,以字节为单位,从文件头开始计算
- ///
- public uint bfOffBits;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- ///
- /// BMP 位图信息头
- ///
- public struct WINBMPINFOHEADER
- {
- ///
- /// 指定此结构体的字节大小。
- ///
- public uint biSize;
-
- ///
- /// 以像素为单位的位图宽度。
- ///
- public uint biWidth;
-
- ///
- /// 以像素为单位的位图高度。
- ///
- public uint biHeight;
-
- ///
- /// 目标设备的平面数,通常为1。
- ///
- public ushort biPlanes;
-
- ///
- /// 每个像素的位数,表示颜色深度,如1、4、8、16、24、32等。
- ///
- public ushort biBitCount;
-
- ///
- /// 压缩类型,0表示不压缩。
- ///
- public uint biCompression;
-
- ///
- /// 位图图像数据的大小(以字节为单位),若图像未压缩,该值可设为0。
- ///
- public uint biSizeImage;
-
- ///
- /// 每米X轴方向的像素数(水平分辨率),通常设为0。
- ///
- public uint biXPelsPerMeter;
-
- ///
- /// 每米Y轴方向的像素数(垂直分辨率),通常设为0。
- ///
- public uint biYPelsPerMeter;
-
- ///
- /// 实际使用的颜色索引数,若为0,则使用位图中实际出现的颜色数。
- ///
- public uint biClrUsed;
-
- ///
- /// 重要颜色索引数,0表示所有颜色都重要。
- ///
- public uint biClrImportant;
- }
- }
-
- public class BitmapFile(BitmapFileCreator.BITMAPFILEHEADER fileHeader, BitmapFileCreator.WINBMPINFOHEADER infoHeader, byte[] palette, byte[] pixelData)
- {
- public BITMAPFILEHEADER FileHeader = fileHeader;
- public WINBMPINFOHEADER InfoHeader = infoHeader;
- public byte[] Palette = palette;
- public byte[] PixelData = pixelData;
-
- ///
- /// 转换为byte[]
- ///
- ///
- public static explicit operator byte[](BitmapFile bf)
- {
- var result = new byte[bf.FileHeader.bfSize];
- var ms = new MemoryStream(result);
- bf.WriteToStream(ms);
- return result;
- }
-
- public byte[] ToByteArray() => (byte[])this;
-
- public Task ToByteArrayAsync() { return Task.FromResult(ToByteArray());}
-
- ///
- /// 写入此结构到流中
- ///
- public void WriteToStream(Stream stream)
- {
- NoiseOverlayHelper.WriteStruct(stream, FileHeader);
- NoiseOverlayHelper.WriteStruct(stream, InfoHeader);
- stream.Write(Palette);
- stream.Write(PixelData);
- stream.Flush();
- }
- }
- }
-}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ObjectHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ObjectHelper.cs
index d646c6c..c0f0b1c 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ObjectHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/ObjectHelper.cs
@@ -32,6 +32,10 @@ namespace BetterLyrics.WinUI3.Helper
if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
+ // Windows.Graphics.Imaging.SoftwareBitmap
+ isDisposedField = objType.GetField("_objRef_global__System_IDisposable", BindingFlags.NonPublic | BindingFlags.Instance);
+ if (isDisposedField != null) { return !Convert.ToBoolean(isDisposedField.GetValue(obj)); }
+
// System.IO.FileStream
var strategyField = objType.GetField("_strategy", BindingFlags.NonPublic | BindingFlags.Instance);
if (strategyField != null)
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
index 81d93af..e80ff14 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/PathHelper.cs
@@ -18,6 +18,21 @@ namespace BetterLyrics.WinUI3.Helper
//public static string LanguageProfilePath => Path.Combine(AssetsFolder, "Core14.profile.xml");
public static string LanguageProfilePath => Path.Combine(AssetsFolder, "Wiki82.profile.xml");
public static string LogoPath => Path.Combine(AssetsFolder, "Logo.ico");
+ 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 UnknownPlayerLogoPath => Path.Combine(AssetsFolder, "Question.png");
public static string LogDirectory => Path.Combine(CacheFolder, "logs");
public static string LogFilePattern => Path.Combine(LogDirectory, "log-.txt");
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs
index 9ec6a7f..1d8d2cb 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/LyricsData.cs
@@ -26,7 +26,7 @@ namespace BetterLyrics.WinUI3.Models
LyricsLines = lyricsLines;
}
- public void SetDisplayedTextAlongWith(LyricsData translationData, int toleranceMs = 0)
+ public void SetDisplayedTextAlongWith(LyricsData translationData, string separator, int toleranceMs = 0)
{
foreach (var line in LyricsLines)
{
@@ -47,11 +47,11 @@ namespace BetterLyrics.WinUI3.Models
{
tmp = ChineseConverter.ConvertToSimplifiedChinese(transLine.OriginalText);
}
- line.DisplayedText = $"{line.OriginalText}\n{tmp}";
+ line.DisplayedText = $"{line.OriginalText}{separator}{tmp}";
}
else
{
- line.DisplayedText = $"{line.OriginalText}\n{transLine.OriginalText}";
+ line.DisplayedText = $"{line.OriginalText}{separator}{transLine.OriginalText}";
}
}
else
@@ -62,7 +62,7 @@ namespace BetterLyrics.WinUI3.Models
}
}
- public void SetDisplayedTextAlongWith(string translation)
+ public void SetDisplayedTextAlongWith(string translation, string separator)
{
List translationArr = translation.Split(StringHelper.NewLine).ToList();
int i = 0;
@@ -74,7 +74,7 @@ namespace BetterLyrics.WinUI3.Models
}
else
{
- line.DisplayedText = $"{line.OriginalText}{StringHelper.NewLine}{translationArr[i]}";
+ line.DisplayedText = $"{line.OriginalText}{separator}{translationArr[i]}";
}
i++;
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
index 410890d..3d6d8ef 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Models/MediaSourceProviderInfo.cs
@@ -2,6 +2,10 @@
using BetterLyrics.WinUI3.Enums;
using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
namespace BetterLyrics.WinUI3.Models
{
@@ -13,12 +17,39 @@ namespace BetterLyrics.WinUI3.Models
[ObservableProperty]
public partial string Provider { get; set; }
+ [ObservableProperty]
+ public partial bool IsLastFMTrackEnabled { get; set; }
+
+ [ObservableProperty]
+ public partial int TimelineSyncThreshold { get; set; }
+
+ [ObservableProperty]
+ public partial int PositionOffset { get; set; }
+
+ [ObservableProperty]
+ public partial bool ResetPositionOffsetOnSongChanged { get; set; }
+
+ [ObservableProperty]
+ public partial ObservableCollection LyricsSearchProvidersInfo { get; set; }
+
public MediaSourceProviderInfo() { }
- public MediaSourceProviderInfo(string provider, bool isEnabled)
+ public MediaSourceProviderInfo(string provider)
{
Provider = provider;
- IsEnabled = isEnabled;
+ IsEnabled = true;
+ IsLastFMTrackEnabled = false;
+ if (provider == Constants.PlayerID.AppleMusic)
+ {
+ TimelineSyncThreshold = PositionOffset = 1000;
+ }
+ else
+ {
+ TimelineSyncThreshold = 0;
+ PositionOffset = 0;
+ }
+ ResetPositionOffsetOnSongChanged = false;
+ LyricsSearchProvidersInfo = [.. Enum.GetValues().Select(p => new LyricsSearchProviderInfo(p, true))];
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/LyricsRenderer.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/LyricsRenderer.xaml.cs
index 2797f7f..5b60e47 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/LyricsRenderer.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Renderer/LyricsRenderer.xaml.cs
@@ -1,9 +1,8 @@
// 2025/6/23 by Zhe Fang
-using BetterLyrics.WinUI3.ViewModels;
+using BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Media.Animation;
namespace BetterLyrics.WinUI3.Renderer
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
similarity index 94%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
index 2516dc1..c45bc40 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/AlbumArtSearchService.cs
@@ -1,6 +1,7 @@
using ATL;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
@@ -14,7 +15,7 @@ using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
{
public class AlbumArtSearchService : IAlbumArtSearchService
{
@@ -102,7 +103,7 @@ namespace BetterLyrics.WinUI3.Services
}
// Build the iTunes API URL
- string url = $"https://itunes.apple.com/search?term=" + WebUtility.UrlEncode($"{artist} {album}").Replace("%20", "+") + "&country=" + countryCode + "&entity=album&media=music&limit=1";
+ string url = $"{Constants.iTunes.QueryPrefix}term=" + WebUtility.UrlEncode($"{artist} {album}").Replace("%20", "+") + "&country=" + countryCode + "&entity=album&media=music&limit=1";
// Make a request to the API
using HttpResponseMessage response = await _iTunesHttpClinet.GetAsync(url);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IAlbumArtSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
similarity index 82%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IAlbumArtSearchService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
index ef6267b..7295126 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IAlbumArtSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/AlbumArtSearchService/IAlbumArtSearchService.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.AlbumArtSearchService
{
public interface IAlbumArtSearchService
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/ILastFMService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/ILastFMService.cs
new file mode 100644
index 0000000..3e29844
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/ILastFMService.cs
@@ -0,0 +1,27 @@
+using BetterLyrics.WinUI3.Events;
+using BetterLyrics.WinUI3.Models;
+using Hqub.Lastfm.Entities;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BetterLyrics.WinUI3.Services.LastFMService
+{
+ public interface ILastFMService
+ {
+ User User { get; }
+ bool IsAuthenticated { get; }
+
+ event EventHandler? UserChanged;
+ event EventHandler? IsAuthenticatedChanged;
+
+ Task AuthAsync();
+ Task ConfirmAuth();
+ Task UnAuthAsync();
+ Task ConfirmUnAuthAsync();
+ Task TrackAsync(SongInfo songInfo);
+ Task RefreshAsync();
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/LastFMService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/LastFMService.cs
new file mode 100644
index 0000000..668e0f8
--- /dev/null
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LastFMService/LastFMService.cs
@@ -0,0 +1,154 @@
+using BetterLyrics.WinUI3.Events;
+using BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Services.SettingsService;
+using BetterLyrics.WinUI3.ViewModels;
+using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
+using BetterLyrics.WinUI3.Views;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.Mvvm.Messaging;
+using CommunityToolkit.Mvvm.Messaging.Messages;
+using Hqub.Lastfm;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.System;
+
+namespace BetterLyrics.WinUI3.Services.LastFMService
+{
+ public partial class LastFMService : ILastFMService
+ {
+ private readonly ISettingsService _settingsService;
+ private readonly LastfmClient _client;
+
+ public event EventHandler? UserChanged;
+ public event EventHandler? IsAuthenticatedChanged;
+
+ public Hqub.Lastfm.Entities.User? User { get; private set; }
+
+ public bool IsAuthenticated { get; private set; }
+
+ public LastFMService(ISettingsService settingsService)
+ {
+ _settingsService = settingsService;
+
+ _client = new LastfmClient(Constants.LastFM.ApiKey, Constants.LastFM.SharedSecret);
+ _client.Session.SessionKey = _settingsService.LastFMSessionKey;
+ UpdateAuthStatusAsync();
+ }
+
+ public async Task ConfirmAuth()
+ {
+ try
+ {
+ await _client.AuthenticateViaWebAsync();
+ _settingsService.LastFMSessionKey = _client.Session.SessionKey;
+ await UpdateAuthStatusAsync();
+ }
+ catch (Exception)
+ {
+ App.Current.SettingsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("LastFMAuthFailed") ?? "", InfoBarSeverity.Error);
+ }
+ }
+
+ public async Task ConfirmUnAuthAsync()
+ {
+ _client.Session.SessionKey = "";
+ _settingsService.LastFMSessionKey = "";
+ await UpdateAuthStatusAsync();
+ }
+
+ public async Task AuthAsync()
+ {
+ var dialogXamlRoot = WindowHelper.GetWindowByWindowType()?.Content.XamlRoot;
+ if (dialogXamlRoot == null)
+ {
+ return;
+ }
+
+ var dialog = new ContentDialog
+ {
+ Title = App.ResourceLoader?.GetString("LastFMRequestAuthTitle") ?? "",
+ Content = App.ResourceLoader?.GetString("LastFMRequestAuthDesc") ?? "",
+ PrimaryButtonText = App.ResourceLoader?.GetString("LastFMRequestAuthConfirm") ?? "",
+ CloseButtonText = App.ResourceLoader?.GetString("Cancel") ?? "",
+ DefaultButton = ContentDialogButton.Close,
+ XamlRoot = dialogXamlRoot,
+ };
+ dialog.PrimaryButtonClick += async (s, args) =>
+ {
+ await ConfirmAuth();
+ };
+
+ string url = await _client.GetWebAuthenticationUrlAsync();
+ await Launcher.LaunchUriAsync(new Uri(url));
+ await dialog.ShowAsync();
+ }
+
+ public async Task UnAuthAsync()
+ {
+ var dialogXamlRoot = WindowHelper.GetWindowByWindowType()?.Content.XamlRoot;
+ if (dialogXamlRoot == null)
+ {
+ return;
+ }
+
+ var dialog = new ContentDialog
+ {
+ Title = App.ResourceLoader?.GetString("LastFMRequestUnAuthTitle") ?? "",
+ Content = App.ResourceLoader?.GetString("LastFMRequestUnAuthDesc") ?? "",
+ PrimaryButtonText = App.ResourceLoader?.GetString("LastFMRequestUnAuthConfirm") ?? "",
+ CloseButtonText = App.ResourceLoader?.GetString("Cancel") ?? "",
+ DefaultButton = ContentDialogButton.Close,
+ XamlRoot = dialogXamlRoot,
+ };
+ dialog.PrimaryButtonClick += async (s, args) =>
+ {
+ await ConfirmUnAuthAsync();
+ };
+
+ await Launcher.LaunchUriAsync(new Uri(Constants.LastFM.UnAuthUrl));
+ await dialog.ShowAsync();
+ }
+
+ private async Task UpdateAuthStatusAsync()
+ {
+ IsAuthenticated = _client.Session.Authenticated;
+ IsAuthenticatedChanged?.Invoke(this, new LastFMIsAuthenticatedChangedEventArgs(IsAuthenticated));
+ if (IsAuthenticated)
+ {
+ User = await _client.User.GetInfoAsync();
+ }
+ else
+ {
+ User = null;
+ }
+ UserChanged?.Invoke(this, new LastFMUserChangedEventArgs(User));
+ }
+
+ public async Task TrackAsync(SongInfo songInfo)
+ {
+ if (IsAuthenticated)
+ {
+ await _client.Track.ScrobbleAsync(new Hqub.Lastfm.Entities.Scrobble
+ {
+ Track = songInfo.Title,
+ Artist = songInfo.Artist,
+ Date = DateTime.Now,
+ });
+ }
+ }
+
+ public async Task RefreshAsync()
+ {
+ await UpdateAuthStatusAsync();
+ }
+ }
+}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILibWatcherService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/ILibWatcherService.cs
similarity index 87%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILibWatcherService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/ILibWatcherService.cs
index c307f0a..4829741 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILibWatcherService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/ILibWatcherService.cs
@@ -8,7 +8,7 @@ using System.Threading.Tasks;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Models;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.LibWatcherService
{
public interface ILibWatcherService
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/LibWatcherService.cs
similarity index 95%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/LibWatcherService.cs
index ffd1d84..bc23de0 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LibWatcherService/LibWatcherService.cs
@@ -6,10 +6,11 @@ using System.IO;
using System.Linq;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
using Microsoft.UI.Dispatching;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.LibWatcherService
{
public class LibWatcherService : BaseViewModel, IDisposable, ILibWatcherService
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
similarity index 62%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILyricsSearchService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
index 197c512..107b5ac 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ILyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/ILyricsSearchService.cs
@@ -5,10 +5,10 @@ using System.Threading;
using System.Threading.Tasks;
using BetterLyrics.WinUI3.Enums;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
public interface ILyricsSearchService
{
- Task<(string?, LyricsSearchProvider?)> SearchAsync(string title, string artist, string album, double durationMs, CancellationToken token);
+ Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
similarity index 95%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
index db9e480..e2ebdea 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/LyricsSearchService/LyricsSearchService.cs
@@ -3,6 +3,7 @@
using ATL;
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Lyricify.Lyrics.Providers.Web.Kugou;
using Lyricify.Lyrics.Searchers;
@@ -18,7 +19,7 @@ using System.Threading;
using System.Threading.Tasks;
using Windows.Storage;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.LyricsSearchService
{
public class LyricsSearchService : ILyricsSearchService
{
@@ -36,7 +37,7 @@ namespace BetterLyrics.WinUI3.Services
_lrcLibHttpClient = new();
_lrcLibHttpClient.DefaultRequestHeaders.Add(
"User-Agent",
- $"{MetadataHelper.AppName} {MetadataHelper.AppVersion} ({MetadataHelper.GithubUrl})"
+ $"{Constants.App.AppName} {MetadataHelper.AppVersion} ({Constants.Link.GithubUrl})"
);
_amllTtmlDbHttpClient = new();
}
@@ -60,10 +61,9 @@ namespace BetterLyrics.WinUI3.Services
public async Task DownloadAmllTtmlDbIndexAsync()
{
- const string url = "https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/metadata/raw-lyrics-index.jsonl";
try
{
- using var response = await _amllTtmlDbHttpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
+ using var response = await _amllTtmlDbHttpClient.GetAsync(Constants.AmllTTmlDB.Index, HttpCompletionOption.ResponseHeadersRead);
if (!response.IsSuccessStatusCode) return false;
await using var stream = await response.Content.ReadAsStreamAsync();
@@ -86,13 +86,13 @@ namespace BetterLyrics.WinUI3.Services
}
}
- public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string title, string artist, string album, double durationMs, CancellationToken token)
+ public async Task<(string?, LyricsSearchProvider?)> SearchAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
{
_logger.LogInformation("Searching img for: {Title} - {Artist} (Album: {Album}, Duration: {DurationMs}ms)", title, artist, album, durationMs);
try
{
- foreach (var provider in _settingsService.LyricsSearchProvidersInfo)
+ foreach (var provider in _settingsService.MediaSourceProvidersInfo.Where(x => x.Provider == mediaSessionId).FirstOrDefault()?.LyricsSearchProvidersInfo ?? [])
{
if (!provider.IsEnabled)
{
@@ -268,7 +268,7 @@ namespace BetterLyrics.WinUI3.Services
return null;
// 下载歌词内容
- var url = $"https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/refs/heads/main/raw-lyrics/{rawLyricFile}";
+ var url = $"{Constants.AmllTTmlDB.QueryPrefix}{rawLyricFile}";
try
{
using var response = await _amllTtmlDbHttpClient.GetAsync(url);
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/IMediaSessionsService.cs
similarity index 84%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/IMediaSessionsService.cs
index bd718dd..d103e5b 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/IMediaSessionsService.cs
@@ -5,9 +5,9 @@ using System.Threading.Tasks;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Models;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{
- public interface IPlaybackService
+ public interface IMediaSessionsService
{
event EventHandler? IsPlayingChanged;
event EventHandler? TimelineChanged;
@@ -23,5 +23,6 @@ namespace BetterLyrics.WinUI3.Services
bool IsPlaying { get; }
SongInfo? SongInfo { get; }
+ TimeSpan Position { get; }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
similarity index 73%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
index 6c2822c..fb3ae85 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MediaSessionsService/MediaSessionsService.cs
@@ -1,17 +1,20 @@
// 2025/6/23 by Zhe Fang
+using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Services.AlbumArtSearchService;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
+using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using EvtSource;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
-using Microsoft.UI.Xaml;
-using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System;
using System.Collections.Generic;
@@ -25,24 +28,22 @@ using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media.Control;
using Windows.Storage.Streams;
-using Windows.UI.Shell;
using WindowsMediaController;
-using static WindowsMediaController.MediaManager;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.MediaSessionsService
{
- public partial class PlaybackService : BaseViewModel, IPlaybackService,
+ public partial class MediaSessionsService : BaseViewModel, IMediaSessionsService,
IRecipient>>,
IRecipient>>
{
private readonly IAlbumArtSearchService _albumArtSearchService;
- private readonly ILogger _logger;
+ private readonly ILogger _logger;
- private readonly string _lxMusicId = "cn.toside.music.desktop";
private double _lxMusicPositionSeconds = 0;
private double _lxMusicDurationSeconds = 0;
private bool _cachedIsPlaying = false;
+ private TimeSpan _cachedPosition = TimeSpan.Zero;
private EventSourceReader? _sse = null;
@@ -62,10 +63,10 @@ namespace BetterLyrics.WinUI3.Services
public event EventHandler? AlbumArtChangedChanged;
public event EventHandler? MediaSourceProvidersInfoChanged;
- public PlaybackService(ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService) : base(settingsService)
+ public MediaSessionsService(ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService) : base(settingsService)
{
_albumArtSearchService = albumArtSearchService;
- _logger = Ioc.Default.GetRequiredService>();
+ _logger = Ioc.Default.GetRequiredService>();
_mediaSourceProvidersInfo = _settingsService.MediaSourceProvidersInfo;
InitMediaManager();
@@ -73,6 +74,7 @@ namespace BetterLyrics.WinUI3.Services
public bool IsPlaying => _cachedIsPlaying;
public SongInfo? SongInfo => _cachedSongInfo;
+ public TimeSpan Position => _cachedPosition;
private bool IsMediaSourceEnabled(string id)
{
@@ -109,12 +111,24 @@ namespace BetterLyrics.WinUI3.Services
var focusedSession = _mediaManager.GetFocusedSession();
- if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != focusedSession) return;
+ if (mediaSession != focusedSession) return;
- _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ if (!IsMediaSourceEnabled(mediaSession.Id))
{
- TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(timelineProperties.Position, timelineProperties.EndTime));
- });
+ _cachedPosition = TimeSpan.Zero;
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, TimeSpan.Zero));
+ });
+ }
+ else
+ {
+ _cachedPosition = timelineProperties.Position;
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties.EndTime));
+ });
+ }
}
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
@@ -125,13 +139,20 @@ namespace BetterLyrics.WinUI3.Services
var focusedSession = _mediaManager.GetFocusedSession();
RecordMediaSourceProviderInfo(mediaSession);
- if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != focusedSession) return;
+ if (mediaSession != focusedSession) return;
- _cachedIsPlaying = playbackInfo.PlaybackStatus switch
+ if (!IsMediaSourceEnabled(mediaSession.Id))
{
- GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true,
- _ => false,
- };
+ _cachedIsPlaying = false;
+ }
+ else
+ {
+ _cachedIsPlaying = playbackInfo.PlaybackStatus switch
+ {
+ GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true,
+ _ => false,
+ };
+ }
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
@@ -149,55 +170,88 @@ namespace BetterLyrics.WinUI3.Services
var focusedSession = _mediaManager.GetFocusedSession();
RecordMediaSourceProviderInfo(mediaSession);
- if (!IsMediaSourceEnabled(id) || mediaSession != focusedSession) return;
+ if (mediaSession != focusedSession) return;
- _cachedSongInfo = new SongInfo
+ if (!IsMediaSourceEnabled(id))
{
- Title = mediaProperties.Title,
- Artist = mediaProperties.Artist,
- Album = mediaProperties.AlbumTitle,
- DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
- SourceAppUserModelId = id,
- };
+ _cachedSongInfo = null;
- _cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
+ _onAnyMediaPropertyChangedRunner.RunAsync(async token =>
+ {
+ _logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
+ mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
- _onAnyMediaPropertyChangedRunner.RunAsync(async token =>
- {
- _logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
- mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
-
- if (id == _lxMusicId)
- {
- StartSSE();
- }
- else
- {
- StopSSE();
- }
-
- if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
- {
- _SMTCAlbumArtBytes = await ImageHelper.ToByteArrayAsync(streamReference);
- }
- else
- {
- _SMTCAlbumArtBytes = null;
- }
-
- await _albumArtRefreshRunner.RunAsync(async tokne =>
- {
- await UpdateAlbumArtRelated(tokne);
- });
-
- if (!token.IsCancellationRequested)
- {
- _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ if (id == Constants.PlayerID.LXMusic)
{
- SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
+ StopSSE();
+ }
+
+ _SMTCAlbumArtBytes = null;
+
+ await _albumArtRefreshRunner.RunAsync(async tokne =>
+ {
+ await UpdateAlbumArtRelated(tokne);
});
- }
- }).ConfigureAwait(false);
+
+ if (!token.IsCancellationRequested)
+ {
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
+ });
+ }
+ }).ConfigureAwait(false);
+ }
+ else
+ {
+ _cachedSongInfo = new SongInfo
+ {
+ Title = mediaProperties.Title,
+ Artist = mediaProperties.Artist,
+ Album = mediaProperties.AlbumTitle,
+ DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
+ SourceAppUserModelId = id,
+ };
+
+ _cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
+
+ _onAnyMediaPropertyChangedRunner.RunAsync(async token =>
+ {
+ _logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
+ mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
+
+ if (id == Constants.PlayerID.LXMusic)
+ {
+ StartSSE();
+ }
+ else
+ {
+ StopSSE();
+ }
+
+ if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference)
+ {
+ _SMTCAlbumArtBytes = await ImageHelper.ToByteArrayAsync(streamReference);
+ }
+ else
+ {
+ _SMTCAlbumArtBytes = null;
+ }
+
+ await _albumArtRefreshRunner.RunAsync(async tokne =>
+ {
+ await UpdateAlbumArtRelated(tokne);
+ });
+
+ if (!token.IsCancellationRequested)
+ {
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
+ });
+ }
+ }).ConfigureAwait(false);
+ }
}
private void MediaManager_OnAnySessionClosed(MediaManager.MediaSession mediaSession)
@@ -231,7 +285,9 @@ namespace BetterLyrics.WinUI3.Services
var found = _mediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == id);
if (found == null)
{
- _mediaSourceProvidersInfo.Add(new MediaSourceProviderInfo(id, true));
+ _mediaSourceProvidersInfo.Add(new MediaSourceProviderInfo(id));
+ // 在这里就写进设置
+ // 因为 SettingsPageViewModel 可能还没有初始化
_settingsService.MediaSourceProvidersInfo = _mediaSourceProvidersInfo;
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
@@ -258,9 +314,9 @@ namespace BetterLyrics.WinUI3.Services
if (focusedSession == null || focusedSession.ControlSession == null) return;
var mediaProps = await focusedSession.ControlSession.TryGetMediaPropertiesAsync();
+ MediaManager_OnAnyTimelinePropertyChanged(focusedSession, focusedSession.ControlSession.GetTimelineProperties());
MediaManager_OnAnyMediaPropertyChanged(focusedSession, mediaProps);
MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
- MediaManager_OnAnyTimelinePropertyChanged(focusedSession, focusedSession.ControlSession.GetTimelineProperties());
}
private async Task UpdateAlbumArtRelated(CancellationToken token)
@@ -285,8 +341,8 @@ namespace BetterLyrics.WinUI3.Services
token.ThrowIfCancellationRequested();
}
- bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
bytes = ImageHelper.Resize(bytes, _targetAlbumArtSize);
+ bytes = ImageHelper.MakeSquareWithThemeColor(bytes);
using var stream = new InMemoryRandomAccessStream();
await stream.WriteAsync(bytes.AsBuffer());
@@ -303,7 +359,7 @@ namespace BetterLyrics.WinUI3.Services
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
- AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
+ AlbumArtChangedChanged?.Invoke(this, new AlbumArtChangedEventArgs(null, albumArtSwBitmap, albumArtLightAccentColor, albumArtDarkAccentColor));
});
}
@@ -311,7 +367,7 @@ namespace BetterLyrics.WinUI3.Services
{
try
{
- _sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}/subscribe-player-status?filter=progress,duration")).Start();
+ _sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}{Constants.LXMusic.QuerySuffix}")).Start();
_sse.MessageReceived += Sse_MessageReceived;
_sse.Disconnected += Sse_Disconnected;
}
@@ -348,7 +404,7 @@ namespace BetterLyrics.WinUI3.Services
private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
{
- if (_cachedSongInfo?.SourceAppUserModelId == _lxMusicId)
+ if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
{
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
if (data.ValueKind == JsonValueKind.Number)
@@ -421,7 +477,6 @@ namespace BetterLyrics.WinUI3.Services
if (message.PropertyName == nameof(SettingsPageViewModel.MediaSourceProvidersInfo))
{
_mediaSourceProvidersInfo = [.. message.NewValue];
- _settingsService.MediaSourceProvidersInfo = _mediaSourceProvidersInfo;
MediaManager_OnFocusedSessionChanged(null);
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/ISettingsService.cs
similarity index 94%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/ISettingsService.cs
index cdcb0d8..ffcb93c 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ISettingsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/ISettingsService.cs
@@ -6,7 +6,7 @@ using BetterLyrics.WinUI3.Models;
using Microsoft.UI.Xaml;
using Windows.UI;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.SettingsService
{
public interface ISettingsService
{
@@ -38,7 +38,6 @@ namespace BetterLyrics.WinUI3.Services
string LibreTranslateServer { get; set; }
int SelectedTargetLanguageIndex { get; set; }
- bool ResetPositionOffsetOnSongChanged { get; set; }
int PositionOffset { get; set; }
// Lyrics lib
@@ -78,7 +77,6 @@ namespace BetterLyrics.WinUI3.Services
float LyricsLineSpacingFactor { get; set; }
- List LyricsSearchProvidersInfo { get; set; }
List AlbumArtSearchProvidersInfo { get; set; }
List MediaSourceProvidersInfo { get; set; }
@@ -94,7 +92,6 @@ namespace BetterLyrics.WinUI3.Services
LyricsDisplayType DisplayType { get; set; }
- int TimelineSyncThreshold { get; set; }
int LockHotKeyIndex { get; set; }
bool IsImmersiveMode { get; set; }
string LXMusicServer { get; set; }
@@ -107,5 +104,10 @@ namespace BetterLyrics.WinUI3.Services
PlaybackOrder PlaybackOrder { get; set; }
bool IsLibreTranslateEnabled { get; set; }
string DockMonitorDeviceName { get; set; }
+
+ // LastFM
+ string LastFMSessionKey { get; set; }
+
+ string LyricsTranslationSeparator { get; set; }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
similarity index 90%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
index 549235f..c37f580 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/SettingsService/SettingsService.cs
@@ -10,10 +10,11 @@ using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
using System.Linq;
+using Windows.Media.Core;
using Windows.Storage;
using Windows.UI;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.SettingsService
{
public class SettingsService : ISettingsService
{
@@ -51,7 +52,7 @@ namespace BetterLyrics.WinUI3.Services
private const string IsLyricsGlowEffectEnabledKey = "IsLyricsGlowEffectEnabled";
private const string LanguageKey = "Language";
- private const string LocalLyricsFoldersKey = "LocalLyricsFolders";
+ private const string LocalMediaFoldersKey = "LocalLyricsFolders";
private const string LyricsAlignmentTypeKey = "TextAlignmentType";
private const string SongInfoAlignmentTypeKey = "SongInfoAlignmentType";
private const string LyricsBlurAmountKey = "LyricsBlurAmount";
@@ -71,7 +72,6 @@ namespace BetterLyrics.WinUI3.Services
private const string LyricsGlowEffectScopeKey = "LyricsGlowEffectScope";
private const string LyricsHighlightSopeKey = "LyricsHighlightSope";
private const string LyricsLineSpacingFactorKey = "LyricsLineSpacingFactor";
- private const string LyricsSearchProvidersInfoKey = "LyricsSearchProvidersInfo";
private const string AlbumArtSearchProvidersInfoKey = "AlbumArtSearchProvidersInfo";
private const string LyricsVerticalEdgeOpacityKey = "LyricsVerticalEdgeOpacity";
@@ -94,11 +94,8 @@ namespace BetterLyrics.WinUI3.Services
private const string LyricsScrollEasingTypeKey = "LyricsScrollEasingType";
private const string LyricsScrollDurationKey = "LyricsScrollDuration";
- public const string TimelineSyncThresholdKey = "TimelineSyncThreshold";
-
private const string IsLyricsFloatAnimationEnabledKey = "IsLyricsFloatAnimationEnabled";
- private const string ResetPositionOffsetOnSongChangedKey = "ResetPositionOffsetOnSongChanged";
private const string PlaybackOrderKey = "PlaybackOrder";
private const string PositionOffsetKey = "PositionOffset";
@@ -115,6 +112,11 @@ namespace BetterLyrics.WinUI3.Services
private const string DockMonitorDeviceNameKey = "DockMonitorDeviceName";
+ // LastFM
+ private const string LastFMSessionKeyKey = "LastFMSessionKey";
+
+ private const string LyricsTranslationSeparatorKey = "LyricsTranslationSeparator";
+
private readonly ApplicationDataContainer _localSettings;
public SettingsService()
@@ -123,29 +125,7 @@ namespace BetterLyrics.WinUI3.Services
SetDefault(IsFirstRunKey, true);
// Lyrics lib
- SetDefault(LocalLyricsFoldersKey, "[]");
- SetDefault(
- LyricsSearchProvidersInfoKey,
- System.Text.Json.JsonSerializer.Serialize(
- Enum.GetValues()
- .Select(p => new LyricsSearchProviderInfo(p, true))
- .ToList(),
- SourceGenerationContext.Default.ListLyricsSearchProviderInfo
- )
- );
- if (LyricsSearchProvidersInfo.Count != Enum.GetValues().Length)
- {
- LyricsSearchProvidersInfo = Enum.GetValues()
- .Select(p => new LyricsSearchProviderInfo(
- p,
- LyricsSearchProvidersInfo
- .Where(x => x.Provider == p)
- .FirstOrDefault()
- ?.IsEnabled ?? true
- ))
- .ToList();
- }
-
+ SetDefault(LocalMediaFoldersKey, "[]");
SetDefault(
AlbumArtSearchProvidersInfoKey,
System.Text.Json.JsonSerializer.Serialize(
@@ -169,6 +149,23 @@ namespace BetterLyrics.WinUI3.Services
}
SetDefault(MediaSourceProvidersInfoKey, "[]");
+ var tmp = MediaSourceProvidersInfo;
+ for (int i = 0; i < tmp.Count; i++)
+ {
+ var mediaSource = tmp[i];
+ if (mediaSource.LyricsSearchProvidersInfo == null || mediaSource.LyricsSearchProvidersInfo.Count != Enum.GetValues().Length)
+ {
+ mediaSource.LyricsSearchProvidersInfo = [..Enum.GetValues()
+ .Select(p => new LyricsSearchProviderInfo(
+ p,
+ mediaSource.LyricsSearchProvidersInfo?
+ .Where(x => x.Provider == p)
+ .FirstOrDefault()
+ ?.IsEnabled ?? true
+ ))];
+ }
+ }
+ MediaSourceProvidersInfo = tmp;
// App appearance
SetDefault(LanguageKey, (int)Language.FollowSystem);
@@ -235,11 +232,9 @@ namespace BetterLyrics.WinUI3.Services
SetDefault(LyricsScrollEasingTypeKey, (int)EasingType.EaseInOutSine);
SetDefault(LyricsScrollDurationKey, 500); // 500ms
- SetDefault(TimelineSyncThresholdKey, 0); // 0ms
SetDefault(IsLyricsFloatAnimationEnabledKey, true);
- SetDefault(ResetPositionOffsetOnSongChangedKey, false);
SetDefault(PositionOffsetKey, 0);
SetDefault(LockHotKeyIndexKey, 'U' - 'A');
SetDefault(DockPlacementKey, (int)DockPlacement.Top);
@@ -250,6 +245,10 @@ namespace BetterLyrics.WinUI3.Services
SetDefault(LyricsFontFamilyKey, FontHelper.SystemFontFamilies.ElementAtOrDefault(0));
SetDefault(IsDragEverywhereEnabledKey, false);
SetDefault(DockMonitorDeviceNameKey, MonitorHelper.GetPrimaryMonitorDeviceName());
+
+ SetDefault(LastFMSessionKeyKey, "");
+
+ SetDefault(LyricsTranslationSeparatorKey, StringHelper.NewLine);
}
public bool IsDragEverywhereEnabled
@@ -448,12 +447,12 @@ namespace BetterLyrics.WinUI3.Services
{
get =>
System.Text.Json.JsonSerializer.Deserialize(
- GetValue(LocalLyricsFoldersKey) ?? "[]",
+ GetValue(LocalMediaFoldersKey) ?? "[]",
SourceGenerationContext.Default.ListLocalMediaFolder
)!;
set =>
SetValue(
- LocalLyricsFoldersKey,
+ LocalMediaFoldersKey,
System.Text.Json.JsonSerializer.Serialize(
value,
SourceGenerationContext.Default.ListLocalMediaFolder
@@ -563,23 +562,6 @@ namespace BetterLyrics.WinUI3.Services
set => SetValue(LyricsLineSpacingFactorKey, value);
}
- public List LyricsSearchProvidersInfo
- {
- get =>
- System.Text.Json.JsonSerializer.Deserialize(
- GetValue(LyricsSearchProvidersInfoKey) ?? "[]",
- SourceGenerationContext.Default.ListLyricsSearchProviderInfo
- )!;
- set =>
- SetValue(
- LyricsSearchProvidersInfoKey,
- System.Text.Json.JsonSerializer.Serialize(
- value,
- SourceGenerationContext.Default.ListLyricsSearchProviderInfo
- )
- );
- }
-
public List AlbumArtSearchProvidersInfo
{
get =>
@@ -656,24 +638,12 @@ namespace BetterLyrics.WinUI3.Services
set => SetValue(IgnoreFullscreenWindowKey, value);
}
- public int TimelineSyncThreshold
- {
- get => GetValue(TimelineSyncThresholdKey);
- set => SetValue(TimelineSyncThresholdKey, value);
- }
-
public bool IsLyricsFloatAnimationEnabled
{
get => GetValue(IsLyricsFloatAnimationEnabledKey);
set => SetValue(IsLyricsFloatAnimationEnabledKey, value);
}
- public bool ResetPositionOffsetOnSongChanged
- {
- get => GetValue(ResetPositionOffsetOnSongChangedKey);
- set => SetValue(ResetPositionOffsetOnSongChangedKey, value);
- }
-
public PlaybackOrder PlaybackOrder
{
get => (PlaybackOrder)GetValue(PlaybackOrderKey);
@@ -698,6 +668,22 @@ namespace BetterLyrics.WinUI3.Services
set => SetValue(DockMonitorDeviceNameKey, value);
}
+ // LastFM
+
+ public string LastFMSessionKey
+ {
+ get => GetValue(LastFMSessionKeyKey)!;
+ set => SetValue(LastFMSessionKeyKey, value);
+ }
+
+ public string LyricsTranslationSeparator
+ {
+ get => GetValue(LyricsTranslationSeparatorKey)!;
+ set => SetValue(LyricsTranslationSeparatorKey, value);
+ }
+
+ // Common methods
+
private T? GetValue(string key)
{
if (_localSettings.Values.TryGetValue(key, out object? value))
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/ITranslateService.cs
similarity index 88%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/ITranslateService.cs
index 25a6282..47f1c0d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/ITranslateService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/ITranslateService.cs
@@ -6,7 +6,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.TranslateService
{
public interface ITranslateService
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/TranslateService.cs
similarity index 96%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/TranslateService.cs
index b867ff0..fdda2f8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/TranslateService/TranslateService.cs
@@ -1,6 +1,7 @@
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Serialization;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
using Lyricify.Lyrics.Helpers.General;
using Microsoft.UI.Dispatching;
@@ -13,7 +14,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
-namespace BetterLyrics.WinUI3.Services
+namespace BetterLyrics.WinUI3.Services.TranslateService
{
public class TranslateService : BaseViewModel, ITranslateService
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
index 1454d75..96f05a9 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/en-US/Resources.resw
@@ -285,9 +285,6 @@
About
-
- Lyrics library
-
App appearance
@@ -566,13 +563,10 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Easing animation type
- Playback sources
+ Playback and lyrics sources
- Playback sources
-
-
- Enable or disable lyrics display for a specified media source
+ Monitor this playback source
Log record
@@ -643,7 +637,7 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
Translate server is not set, please configure it in settings first
-
+
Reset to 0 when switching songs
@@ -919,4 +913,67 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
This setting will not affect the dock mode and the dock mode will always remain centered.
+
+ Last.fm
+
+
+ Last.fm
+
+
+ Authorize
+
+
+ Revoke authorization
+
+
+ Track listening history via Last.fm
+
+
+ Username
+
+
+ Total playing count
+
+
+ Registration date
+
+
+ Source and translation separator
+
+
+ Immersive mode
+
+
+ Play all
+
+
+ No playback source captured
+
+
+ Refresh
+
+
+ Authorization failed, please try again
+
+
+ Grant BetterLyrics permission to access your Last.fm account
+
+
+ Please complete the authorization in your browser
+
+
+ I have completed the authorization
+
+
+ Cancel
+
+
+ Revoke BetterLyrics' permission to access your Last.fm account
+
+
+ Please complete the cancellation operation in your browser
+
+
+ I have canceled my authorization
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
index a087abb..91c3066 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ja-JP/Resources.resw
@@ -285,9 +285,6 @@
について
-
- 歌詞
-
アプリの外観
@@ -566,13 +563,10 @@
アニメーションタイプを緩和します
- 再生ソース
+ プレイと歌詞
- 再生ソース
-
-
- 指定されたメディアソースの歌詞ディスプレイを有効または無効にする
+ この再生ソースを監視します
ログレコード
@@ -643,7 +637,7 @@
翻訳サーバーは設定されていません。最初に設定で構成してください
-
+
曲を切り替えるときに0にリセットします
@@ -919,4 +913,67 @@
この設定はドックモードには影響しません。ドックモードは常に中心のままです。
+
+ Last.fm
+
+
+ Last.fm
+
+
+ 許可
+
+
+ 承認を取り消します
+
+
+ last.fm 経由でリスニング履歴を追跡します
+
+
+ ユーザー名
+
+
+ 合計プレイカウント
+
+
+ 登録日
+
+
+ ソースおよび翻訳セパレーター
+
+
+ 没入モード
+
+
+ すべてを再生します
+
+
+ キャプチャされた再生ソースはありません
+
+
+ リフレッシュします
+
+
+ 承認が失敗しました、もう一度やり直してください
+
+
+ BetterLyricsにLast.fmアカウントへのアクセスを許可してください!
+
+
+ ブラウザの承認を完了してください
+
+
+ 私は承認を完了しました
+
+
+ キャンセル
+
+
+ Last.fmアカウントへのBetterLyricsアクセスを取り消します!
+
+
+ ブラウザでキャンセル操作を完了してください
+
+
+ 認可をキャンセルしました
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
index 5995e3b..527a6ea 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/ko-KR/Resources.resw
@@ -285,9 +285,6 @@
에 대한
-
- 가사
-
앱 모양
@@ -566,13 +563,10 @@
애니메이션 유형 완화
- 재생 소스
+ 연극과 가사
- 재생 소스
-
-
- 지정된 미디어 소스의 가사 디스플레이 활성화 또는 비활성화
+ 이 재생 소스를 모니터링하십시오
로그 레코드
@@ -643,7 +637,7 @@
번역 서버가 설정되지 않았습니다. 먼저 설정으로 구성하십시오.
-
+
노래를 전환 할 때 0 으로 재설정하십시오
@@ -919,4 +913,67 @@
이 설정은 도크 모드에 영향을 미치지 않으며 도크 모드는 항상 중앙에 유지됩니다.
+
+ Last.fm
+
+
+ Last.fm
+
+
+ 승인
+
+
+ 취소 승인
+
+
+ Last.fm 을 통해 청취 기록을 추적합니다
+
+
+ 사용자 이름
+
+
+ 총 플레이 카운트
+
+
+ 등록일
+
+
+ 소스 및 번역 분리기
+
+
+ 몰입 형 모드
+
+
+ 모두 재생하십시오
+
+
+ 재생 소스가 캡처되지 않았습니다
+
+
+ 새로 고치다
+
+
+ 승인이 실패했습니다. 다시 시도하십시오
+
+
+ Last.fm 계정에 BetterLyrics 액세스 권한을 부여하세요!
+
+
+ 브라우저에서 승인을 완료하십시오
+
+
+ 나는 승인을 완료했다
+
+
+ 취소
+
+
+ Last.fm 계정에 대한 BetterLyrics 액세스를 취소하십시오!
+
+
+ 브라우저에서 취소 작업을 완료하십시오
+
+
+ 내 승인을 취소했습니다
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
index 64cf5b6..e70e07e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-CN/Resources.resw
@@ -285,9 +285,6 @@
关于
-
- 歌词源
-
应用外观
@@ -566,13 +563,10 @@
缓动动画类型
- 播放源
+ 播放与歌词源
- 播放源
-
-
- 为指定媒体源启用或禁用歌词显示
+ 监听此播放源
日志记录
@@ -643,7 +637,7 @@
未设置Translate服务器,请先在设置中进行配置
-
+
切换歌曲时重置为 0
@@ -919,4 +913,67 @@
此设置不会影响停靠模式,停靠模式将始终保持居中。
+
+ Last.fm
+
+
+ Last.fm
+
+
+ 授权
+
+
+ 撤销授权
+
+
+ 通过 Last.fm 跟踪听歌历史记录
+
+
+ 用户名
+
+
+ 听歌总数量
+
+
+ 注册日期
+
+
+ 原文译文分隔符
+
+
+ 沉浸模式
+
+
+ 播放全部
+
+
+ 没有捕获的播放源
+
+
+ 刷新
+
+
+ 授权失败,请重试
+
+
+ 授予 BetterLyrics 访问您 Last.fm 账户的权限
+
+
+ 请在浏览器中完成授权
+
+
+ 我已经完成了授权
+
+
+ 取消
+
+
+ 撤销 BetterLyrics 访问您 Last.fm 账户的权限
+
+
+ 请在浏览器中完成取消操作
+
+
+ 我已经取消了我的授权
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
index 4608ae5..be81055 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Strings/zh-TW/Resources.resw
@@ -285,9 +285,6 @@
關於
-
- 歌詞源
-
應用外觀
@@ -566,13 +563,10 @@
緩動動畫類型
- 播放來源
+ 播放與歌詞源
- 播放來源
-
-
- 為指定媒體源啟用或禁用歌詞顯示
+ 監聽此播放來源
日誌記錄
@@ -643,7 +637,7 @@
未設定翻譯伺服器,請先在設定中進行配置
-
+
切換歌曲時重置為 0
@@ -919,4 +913,67 @@
此設定不會影響停靠模式,停靠模式將始終保持居中。
+
+ Last.fm
+
+
+ Last.fm
+
+
+ 授權
+
+
+ 撤銷授權
+
+
+ 透過 Last.fm 追蹤聽歌歷史記錄
+
+
+ 使用者名稱
+
+
+ 聽歌總數量
+
+
+ 註冊日期
+
+
+ 原文譯文分隔符
+
+
+ 沉浸模式
+
+
+ 播放全部
+
+
+ 沒有捕獲的播放源
+
+
+ 重新整理
+
+
+ 授權失敗,請重試
+
+
+ 授予 BetterLyrics 訪問您 Last.fm 賬戶的權限
+
+
+ 請在瀏覽器中完成授權
+
+
+ 我已經完成了授權
+
+
+ 取消
+
+
+ 撤銷 BetterLyrics 訪問您 Last.fm 賬戶的權限
+
+
+ 請在瀏覽器中完成取消操作
+
+
+ 我已經取消了我的授權
+
\ No newline at end of file
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseViewModel.cs
index 9510752..9ab0484 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseViewModel.cs
@@ -1,6 +1,6 @@
// 2025/6/23 by Zhe Fang
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Dispatching;
using System;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs
index 6b86c24..82f2ce0 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/BaseWindowViewModel.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
index f774321..05353e2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
@@ -3,7 +3,8 @@
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -27,7 +28,7 @@ namespace BetterLyrics.WinUI3.ViewModels
IRecipient>,
IRecipient>
{
- private readonly IPlaybackService _playbackService;
+ private readonly IMediaSessionsService _mediaSessionsService;
private readonly ThrottleHelper _timelineThrottle = new(TimeSpan.FromSeconds(1));
private bool _isDockMode = false;
@@ -37,12 +38,11 @@ namespace BetterLyrics.WinUI3.ViewModels
private int _lyricsDockFontSize = 8;
private int _lyricsDesktopFontSize = 8;
- public LyricsPageViewModel(ISettingsService settingsService, IPlaybackService playbackService) : base(settingsService)
+ public LyricsPageViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService) : base(settingsService)
{
IsFirstRun = _settingsService.IsFirstRun;
IsTranslationEnabled = _settingsService.IsTranslationEnabled;
DisplayType = _settingsService.DisplayType;
- ResetPositionOffsetOnSongChanged = _settingsService.ResetPositionOffsetOnSongChanged;
PositionOffset = _settingsService.PositionOffset;
IsImmersiveMode = _settingsService.IsImmersiveMode;
ShowTranslationOnly = _settingsService.ShowTranslationOnly;
@@ -56,12 +56,12 @@ namespace BetterLyrics.WinUI3.ViewModels
//Volume = SystemVolumeHelper.GetMasterVolume();
//SystemVolumeHelper.VolumeChanged += SystemVolumeHelper_VolumeChanged;
- _playbackService = playbackService;
- _playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
- _playbackService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
- _playbackService.TimelineChanged += PlaybackService_TimelineChanged;
+ _mediaSessionsService = mediaSessionsService;
+ _mediaSessionsService.SongInfoChanged += PlaybackService_SongInfoChanged;
+ _mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
+ _mediaSessionsService.TimelineChanged += PlaybackService_TimelineChanged;
- IsSongPlaying = _playbackService.IsPlaying;
+ IsSongPlaying = _mediaSessionsService.IsPlaying;
}
private void PlaybackService_TimelineChanged(object? sender, Events.TimelineChangedEventArgs e)
@@ -83,10 +83,6 @@ namespace BetterLyrics.WinUI3.ViewModels
{
SongInfo = e.SongInfo;
SongDurationSeconds = SongInfo?.Duration ?? 0;
- if (ResetPositionOffsetOnSongChanged)
- {
- PositionOffset = 0;
- }
}
[ObservableProperty]
@@ -138,10 +134,6 @@ namespace BetterLyrics.WinUI3.ViewModels
[NotifyPropertyChangedRecipients]
public partial bool ShowTranslationOnly { get; set; }
- [ObservableProperty]
- [NotifyPropertyChangedRecipients]
- public partial bool ResetPositionOffsetOnSongChanged { get; set; }
-
[ObservableProperty]
public partial bool IsSongPlaying { get; set; }
@@ -213,25 +205,25 @@ namespace BetterLyrics.WinUI3.ViewModels
[RelayCommand]
private async Task PlaySongAsync()
{
- await _playbackService.PlayAsync();
+ await _mediaSessionsService.PlayAsync();
}
[RelayCommand]
private async Task PauseSongAsync()
{
- await _playbackService.PauseAsync();
+ await _mediaSessionsService.PauseAsync();
}
[RelayCommand]
private async Task PreviousSongAsync()
{
- await _playbackService.PreviousAsync();
+ await _mediaSessionsService.PreviousAsync();
}
[RelayCommand]
private async Task NextSongAsync()
{
- await _playbackService.NextAsync();
+ await _mediaSessionsService.NextAsync();
}
partial void OnIsFirstRunChanged(bool value)
@@ -271,17 +263,17 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsStandardFontSize))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsStandardFontSize))
{
UpdateHintMessageFontSize();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsDockFontSize))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsDockFontSize))
{
UpdateHintMessageFontSize();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsDesktopFontSize))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsDesktopFontSize))
{
UpdateHintMessageFontSize();
}
@@ -290,9 +282,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontFamily))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsFontFamily))
{
LyricsFontFamily = message.NewValue;
}
@@ -306,9 +298,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is LyricsRendererViewModel)
+ if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
{
- if (message.PropertyName == nameof(LyricsRendererViewModel.TotalTime))
+ if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsRendererViewModel.TotalTime))
{
if (_timelineThrottle.CanTrigger())
{
@@ -323,9 +315,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is LyricsRendererViewModel)
+ if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
{
- if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsSearchProvider))
+ if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsRendererViewModel.LyricsSearchProvider))
{
LyricsSearchProvider = message.NewValue;
}
@@ -334,9 +326,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is LyricsRendererViewModel)
+ if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
{
- if (message.PropertyName == nameof(LyricsRendererViewModel.TranslationSearchProvider))
+ if (message.PropertyName == nameof(LyricsRendererViewModel.LyricsRendererViewModel.TranslationSearchProvider))
{
TranslationSearchProvider = message.NewValue;
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Ctor.cs
similarity index 69%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Ctor.cs
index acc2240..7e3e48d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Ctor.cs
@@ -1,20 +1,37 @@
using BetterLyrics.WinUI3.Enums;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.LyricsSearchService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
+using BetterLyrics.WinUI3.Services.TranslateService;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
+using System.Diagnostics;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
{
- public LyricsRendererViewModel(ISettingsService settingsService, IPlaybackService playbackService, ILyricsSearchService musicSearchService, ILibWatcherService libWatcherService, ITranslateService libreTranslateService) : base(settingsService)
+ public LyricsRendererViewModel(
+ ISettingsService settingsService,
+ IMediaSessionsService mediaSessionsService,
+ ILyricsSearchService musicSearchService,
+ ILibWatcherService libWatcherService,
+ ITranslateService libreTranslateService,
+ ILastFMService lastFMService
+ ) : base(settingsService)
{
_lyrcsSearchService = musicSearchService;
- _playbackService = playbackService;
+ _mediaSessionsService = mediaSessionsService;
_libWatcherService = libWatcherService;
_translateService = libreTranslateService;
+ _lastFMService = lastFMService;
+
+ _mediaSourceProvidersInfo = _settingsService.MediaSourceProvidersInfo;
+
_logger = Ioc.Default.GetRequiredService>();
_albumArtCornerRadius = _settingsService.CoverImageRadius;
@@ -59,9 +76,13 @@ namespace BetterLyrics.WinUI3.ViewModels
_showTranslationOnly = _settingsService.ShowTranslationOnly;
_isLibreTranslateEnabled = _settingsService.IsLibreTranslateEnabled;
_targetLanguageIndex = _settingsService.SelectedTargetLanguageIndex;
+ _lyricsTranslationSeparator = _settingsService.LyricsTranslationSeparator;
+
+ _dockPlacement = _settingsService.DockPlacement;
+
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment = _settingsService.SongInfoAlignmentType.ToCanvasHorizontalAlignment();
- _timelineSyncThreshold = _settingsService.TimelineSyncThreshold;
+ _timelineSyncThreshold = 0;
_canvasYScrollTransition.SetDuration(_settingsService.LyricsScrollDuration / 1000f);
_canvasYScrollTransition.SetEasingType(_settingsService.LyricsScrollEasingType);
@@ -73,12 +94,12 @@ namespace BetterLyrics.WinUI3.ViewModels
_libWatcherService.MusicLibraryFilesChanged +=
LibWatcherService_MusicLibraryFilesChanged;
- _playbackService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
- _playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
- _playbackService.AlbumArtChangedChanged += PlaybackService_AlbumArtChangedChanged;
- _playbackService.TimelineChanged += PlaybackService_TimelineChanged;
+ _mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
+ _mediaSessionsService.SongInfoChanged += PlaybackService_SongInfoChanged;
+ _mediaSessionsService.AlbumArtChangedChanged += PlaybackService_AlbumArtChangedChanged;
+ _mediaSessionsService.TimelineChanged += PlaybackService_TimelineChanged;
- _isPlaying = _playbackService.IsPlaying;
+ _isPlaying = _mediaSessionsService.IsPlaying;
UpdateColorConfig();
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Draw.cs
similarity index 86%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Draw.cs
index 4688211..55c0020 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Draw.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Draw.cs
@@ -17,7 +17,7 @@ using Windows.Foundation;
using Windows.Graphics.Effects;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
{
@@ -35,15 +35,15 @@ namespace BetterLyrics.WinUI3.ViewModels
if (_isDockMode)
{
- FillBackgroundColor(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
+ FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value * _albumArtBgOpacity / 100f);
}
else if (_isDesktopMode)
{
- FillBackgroundColor(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value);
+ FillBackground(control, combinedDs, _immersiveBgColorTransition.Value, 0f, _immersiveBgOpacityTransition.Value * _albumArtBgOpacity / 100f);
}
else
{
- FillBackgroundColor(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _albumArtBgOpacity / 100f);
+ FillBackground(control, combinedDs, _albumArtAccentColorTransition.Value, 0f, _albumArtBgOpacity / 100f);
DrawAlbumArtBackground(control, combinedDs);
}
@@ -83,7 +83,7 @@ namespace BetterLyrics.WinUI3.ViewModels
$"Total line count: {GetMaxLyricsLineIndexBoundaries().Item2 + 1}\n" +
$"Cur time: {TotalTime + _positionOffset}\n" +
$"Lang size: {_lyricsDataArr.Count}\n" +
- $"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}\n" +
+ $"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}\n" +
$"Y offset: {_canvasYScrollTransition.Value}",
new Vector2(10, 40),
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White,
@@ -259,7 +259,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
);
- if (line.HighlightOpacityTransition.Value !=0)
+ if (line.HighlightOpacityTransition.Value != 0)
{
// 再叠加高亮行歌词层(前景歌词层)
using var mask = new CanvasCommandList(control.Device);
@@ -324,13 +324,13 @@ namespace BetterLyrics.WinUI3.ViewModels
);
// Brushes
- using var fadeInBrush = GetHorizontalFillBrush(
+ using var fadeInBrush = CreateHorizontalFillBrush(
control,
[(0f, 0f), (1f, 1f)],
(float)highlightRect.Right - fadingWidth,
fadingWidth
);
- using var fadeOutBrush = GetHorizontalFillBrush(
+ using var fadeOutBrush = CreateHorizontalFillBrush(
control,
[(0f, 1f), (1f, 0f)],
(float)highlightRect.Right,
@@ -345,22 +345,34 @@ namespace BetterLyrics.WinUI3.ViewModels
}
else
{
- float height = 0f;
+ //float height = 0f;
var regions = textLayout.GetCharacterRegions(0, line.OriginalText.Length);
if (regions.Length > 0)
{
- height = (float)regions[^1].LayoutBounds.Bottom - (float)regions[0].LayoutBounds.Top;
+ //height = (float)regions[^1].LayoutBounds.Bottom - (float)regions[0].LayoutBounds.Top;
+
+ for (int j = 0; j < regions.Length; j++)
+ {
+ var region = regions[j];
+ var rect = new Rect(
+ region.LayoutBounds.X,
+ region.LayoutBounds.Y + line.Position.Y,
+ region.LayoutBounds.Width,
+ region.LayoutBounds.Height
+ );
+ maskDs.FillRectangle(rect, Colors.White);
+ }
}
- maskDs.FillRectangle(
- new Rect(
- textLayout.LayoutBounds.X,
- line.Position.Y,
- textLayout.LayoutBounds.Width,
- height
- ),
- Colors.White
- );
+ //maskDs.FillRectangle(
+ // new Rect(
+ // textLayout.LayoutBounds.X,
+ // line.Position.Y,
+ // textLayout.LayoutBounds.Width,
+ // height
+ // ),
+ // Colors.White
+ //);
}
using var opacityEffect = new OpacityEffect
@@ -438,7 +450,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
}
- private void FillBackgroundColor(ICanvasAnimatedControl control, CanvasDrawingSession ds, Color color, float radius, float opacity)
+ private void FillBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds, Color color, float radius, float opacity)
{
ds.FillRoundedRectangle(
new Rect(0, 0, _canvasWidth, _canvasHeight),
@@ -448,7 +460,17 @@ namespace BetterLyrics.WinUI3.ViewModels
);
}
- private CanvasLinearGradientBrush GetHorizontalFillBrush(
+ private void FillBackground(ICanvasAnimatedControl control, CanvasDrawingSession ds, CanvasLinearGradientBrush brush, float radius, float opacity)
+ {
+ ds.FillRoundedRectangle(
+ new Rect(0, 0, _canvasWidth, _canvasHeight),
+ radius,
+ radius,
+ brush
+ );
+ }
+
+ private CanvasLinearGradientBrush CreateHorizontalFillBrush(
ICanvasAnimatedControl control,
List<(float position, float opacity)> stops,
float startX,
@@ -465,5 +487,23 @@ namespace BetterLyrics.WinUI3.ViewModels
EndPoint = new Vector2(startX + width, 0),
};
}
+
+ private CanvasLinearGradientBrush CreateVerticalFillBrush(
+ ICanvasAnimatedControl control,
+ List<(float position, Color color)> stops,
+ float startY,
+ float height
+ )
+ {
+ return new CanvasLinearGradientBrush(control, stops.Select(x => new CanvasGradientStop
+ {
+ Position = x.position,
+ Color = x.color,
+ }).ToArray())
+ {
+ StartPoint = new Vector2(0, startY),
+ EndPoint = new Vector2(0, startY + height),
+ };
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Effects.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Effects.cs
similarity index 99%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Effects.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Effects.cs
index b700107..04967fe 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Effects.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Effects.cs
@@ -7,7 +7,7 @@ using System;
using System.Numerics;
using Windows.Foundation;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Messages.cs
similarity index 75%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Messages.cs
index b45c4af..f6a42f3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Messages.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Messages.cs
@@ -6,10 +6,11 @@ using Microsoft.Extensions.Logging;
using Microsoft.UI.Xaml;
using System;
using System.Collections.ObjectModel;
+using System.Linq;
using System.Threading.Tasks;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
: IRecipient>,
@@ -24,14 +25,15 @@ namespace BetterLyrics.WinUI3.ViewModels
IRecipient>,
IRecipient>,
IRecipient>,
- IRecipient>>,
+ IRecipient>,
+ IRecipient>>,
IRecipient>>
{
public void Receive(PropertyChangedMessage> message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LocalMediaFolders))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LocalMediaFolders))
{
// Music lib changed, re-fetch lyrics
_logger.LogInformation("Local lyrics folders changed, refreshing lyrics.");
@@ -43,13 +45,19 @@ namespace BetterLyrics.WinUI3.ViewModels
}
}
- public void Receive(PropertyChangedMessage> message)
+ public void Receive(PropertyChangedMessage> message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsSearchProvidersInfo))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.MediaSourceProvidersInfo))
{
- // Lyrics search providers info changed, re-fetch lyrics
+ _mediaSourceProvidersInfo = message.NewValue.ToList();
+
+ UpdateTimelineSyncThreshold();
+ UpdatePositionOffset();
+ UpdateIsLastFMTrackEnabled();
+
+ // Media source providers info changed (maybe include lyrics search providers info changed), re-fetch lyrics
_logger.LogInformation("Lyrics search providers info changed, refreshing lyrics.");
_ = _refreshLyricsRunner.RunAsync(async token =>
{
@@ -61,31 +69,31 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.IsDynamicCoverOverlayEnabled))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsDynamicCoverOverlayEnabled))
{
_isDynamicCoverOverlayEnabled = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.IsDebugOverlayEnabled))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsDebugOverlayEnabled))
{
_isDebugOverlayEnabled = message.NewValue;
_isDebugOverlayEnabledChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.IsLyricsGlowEffectEnabled))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsLyricsGlowEffectEnabled))
{
_isLyricsGlowEffectEnabled = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.IsFanLyricsEnabled))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsFanLyricsEnabled))
{
_isFanLyricsEnabled = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.IsLyricsFloatAnimationEnabled))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsLyricsFloatAnimationEnabled))
{
_isLyricsFloatAnimationEnabled = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.IsLibreTranslateEnabled))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.IsLibreTranslateEnabled))
{
_isLibreTranslateEnabled = message.NewValue;
UpdateTranslations();
@@ -145,19 +153,19 @@ namespace BetterLyrics.WinUI3.ViewModels
UpdateColorConfig();
}
}
- else if (message.Sender is SettingsPageViewModel)
+ else if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomBgFontColor))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsCustomBgFontColor))
{
_customBgFontColor = message.NewValue;
UpdateColorConfig();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomFgFontColor))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsCustomFgFontColor))
{
_customFgFontColor = message.NewValue;
UpdateColorConfig();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsCustomStrokeFontColor))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsCustomStrokeFontColor))
{
_customStrokeFontColor = message.NewValue;
UpdateColorConfig();
@@ -167,9 +175,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsLineSpacingFactor))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsLineSpacingFactor))
{
_lyricsLineSpacingFactor = message.NewValue;
_isLayoutChanged = true;
@@ -179,94 +187,83 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.CoverImageRadius))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.CoverImageRadius))
{
_albumArtCornerRadius = message.NewValue;
_isAlbumArtCornerRadiusChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.CoverOverlayOpacity))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.CoverOverlayOpacity))
{
_albumArtBgOpacity = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.CoverOverlayBlurAmount))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.CoverOverlayBlurAmount))
{
_albumArtBgBlurAmount = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.CoverAcrylicEffectAmount))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.CoverAcrylicEffectAmount))
{
_coverAcrylicEffectAmount = message.NewValue;
_isCoverAcrylicEffectAmountChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsVerticalEdgeOpacity))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsVerticalEdgeOpacity))
{
_lyricsVerticalEdgeOpacity = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBlurAmount))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsBlurAmount))
{
_lyricsBlurAmount = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsStandardFontSize))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsStandardFontSize))
{
_lyricsStandardFontSize = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsDockFontSize))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsDockFontSize))
{
_lyricsDockFontSize = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsDesktopFontSize))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsDesktopFontSize))
{
_lyricsDesktopFontSize = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.SelectedTargetLanguageIndex))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.SelectedTargetLanguageIndex))
{
_targetLanguageIndex = message.NewValue;
_logger.LogInformation("Target language index changed: {Index}", _targetLanguageIndex);
UpdateTranslations();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontStrokeWidth))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsFontStrokeWidth))
{
_lyricsFontStrokeWidth = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsScrollDuration))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsScrollDuration))
{
_canvasYScrollTransition.SetDuration(message.NewValue / 1000f);
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.TimelineSyncThreshold))
- {
- _timelineSyncThreshold = message.NewValue;
- }
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBgFontOpacity))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsBgFontOpacity))
{
_defaultOpacity = message.NewValue / 100f;
_isLayoutChanged = true;
}
}
- else if (message.Sender is LyricsPageViewModel)
- {
- if (message.PropertyName == nameof(LyricsPageViewModel.PositionOffset))
- {
- _positionOffset = TimeSpan.FromMilliseconds(message.NewValue);
- }
- }
}
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsGlowEffectScope))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsGlowEffectScope))
{
_lyricsGlowEffectScope = message.NewValue;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsHighlightScope))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsHighlightScope))
{
_lyricsHighlightScope = message.NewValue;
}
@@ -275,14 +272,14 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsAlignmentType))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsAlignmentType))
{
_lyricsAlignmentType = message.NewValue;
_isLayoutChanged = true;
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.SongInfoAlignmentType))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.SongInfoAlignmentType))
{
_titleTextFormat.HorizontalAlignment = _artistTextFormat.HorizontalAlignment =
message.NewValue.ToCanvasHorizontalAlignment();
@@ -297,19 +294,19 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBgFontColorType))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsBgFontColorType))
{
_lyricsBgFontColorType = message.NewValue;
UpdateColorConfig();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFgFontColorType))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsFgFontColorType))
{
_lyricsFgFontColorType = message.NewValue;
UpdateColorConfig();
}
- else if (message.PropertyName == nameof(SettingsPageViewModel.LyricsStrokeFontColorType))
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsStrokeFontColorType))
{
_lyricsStrokeFontColorType = message.NewValue;
UpdateColorConfig();
@@ -319,9 +316,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontWeight))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsFontWeight))
{
_lyricsTextFormat.FontWeight = message.NewValue.ToFontWeight();
_isLayoutChanged = true;
@@ -331,9 +328,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsBackgroundTheme))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsBackgroundTheme))
{
_lyricsBgTheme = message.NewValue;
UpdateColorConfig();
@@ -343,9 +340,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsScrollEasingType))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsScrollEasingType))
{
_canvasYScrollTransition.SetEasingType(message.NewValue);
}
@@ -354,13 +351,29 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LyricsFontFamily))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsFontFamily))
{
_lyricsTextFormat.FontFamily = _artistTextFormat.FontFamily = _titleTextFormat.FontFamily = message.NewValue;
_isLayoutChanged = true;
}
+ else if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LyricsTranslationSeparator))
+ {
+ _lyricsTranslationSeparator = message.NewValue;
+ UpdateTranslations();
+ }
+ }
+ }
+
+ public void Receive(PropertyChangedMessage message)
+ {
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
+ {
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.DockPlacement))
+ {
+ _dockPlacement = message.NewValue;
+ }
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Transition.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Transition.cs
similarity index 98%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Transition.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Transition.cs
index 88ea245..c5545fe 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Transition.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Transition.cs
@@ -8,7 +8,7 @@ using System.Text;
using System.Threading.Tasks;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
similarity index 94%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
index b8ab560..5262fac 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Update.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.Update.cs
@@ -7,6 +7,7 @@ using Microsoft.Graphics.Canvas.UI.Xaml;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
+using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
@@ -16,7 +17,7 @@ using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel
{
@@ -43,6 +44,12 @@ namespace BetterLyrics.WinUI3.ViewModels
if (_isPlaying)
{
TotalTime += _elapsedTime;
+ _totalPlayingTime += _elapsedTime;
+ if (_isLastFMTrackEnabled && !_isLastFMTracked && SongInfo?.Duration != null && SongInfo.Duration > 0 && _totalPlayingTime.TotalSeconds >= SongInfo.Duration * 0.5)
+ {
+ _isLastFMTracked = true;
+ _lastFMService.TrackAsync(SongInfo);
+ }
}
var playingLineIndex = GetCurrentPlayingLineIndex();
@@ -292,7 +299,7 @@ namespace BetterLyrics.WinUI3.ViewModels
line.Position = new Vector2(0, y);
line.UpdateTextLayout(control, _lyricsTextFormat, _maxLyricsWidth, _canvasHeight, _isDockMode ? TextAlignmentType.Center : _lyricsAlignmentType);
line.UpdateCenterPosition(_maxLyricsWidth, _isDockMode ? TextAlignmentType.Center : _lyricsAlignmentType);
-
+
//line.UpdateTextGeometry();
//line.UpdateFontEffect(control, _isDesktopMode, _strokeFontColor, _lyricsFontStrokeWidth, _bgFontColor);
@@ -579,7 +586,7 @@ namespace BetterLyrics.WinUI3.ViewModels
{
if (_coverAcrylicEffectAmount > 0)
{
- var ret = NoiseOverlayHelper.GenerateNoiseBitmapBGRA((int)_canvasWidth, (int)_canvasHeight);
+ var ret = ImageHelper.GenerateNoiseBGRA((int)_canvasWidth, (int)_canvasHeight);
_coverAcrylicNoiseCanvasBitmap?.Dispose();
_coverAcrylicNoiseCanvasBitmap = null;
_coverAcrylicNoiseCanvasBitmap = CanvasBitmap.CreateFromBytes(
@@ -591,5 +598,27 @@ namespace BetterLyrics.WinUI3.ViewModels
);
}
}
+
+ private MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
+ {
+ return _mediaSourceProvidersInfo.Where(x => x.Provider == SongInfo?.SourceAppUserModelId)?.FirstOrDefault();
+ }
+
+ private void UpdateTimelineSyncThreshold()
+ {
+ _timelineSyncThreshold = GetCurrentMediaSourceProviderInfo()?.TimelineSyncThreshold ?? 0;
+ }
+
+ private void UpdatePositionOffset()
+ {
+ var current = GetCurrentMediaSourceProviderInfo();
+ _positionOffset = TimeSpan.FromMilliseconds(current?.PositionOffset ?? 0);
+ }
+
+ private void UpdateIsLastFMTrackEnabled()
+ {
+ var current = GetCurrentMediaSourceProviderInfo();
+ _isLastFMTrackEnabled = current?.IsLastFMTrackEnabled ?? false;
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.cs
similarity index 93%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.cs
index ab2c08e..e681cc2 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel/LyricsRendererViewModel.cs
@@ -5,7 +5,13 @@ using BetterLyrics.WinUI3.Events;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.LyricsSearchService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.TranslateService;
using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.WinUI;
using Microsoft.Extensions.Logging;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Text;
@@ -21,10 +27,14 @@ using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
{
public partial class LyricsRendererViewModel : BaseViewModel
{
+ private bool _isLastFMTrackEnabled = false;
+ private bool _isLastFMTracked = false;
+ private TimeSpan _totalPlayingTime = TimeSpan.Zero;
+
private TimeSpan _elapsedTime = TimeSpan.Zero;
[ObservableProperty]
@@ -100,8 +110,9 @@ namespace BetterLyrics.WinUI3.ViewModels
private readonly ILyricsSearchService _lyrcsSearchService;
private readonly ILibWatcherService _libWatcherService;
- private readonly IPlaybackService _playbackService;
+ private readonly IMediaSessionsService _mediaSessionsService;
private readonly ITranslateService _translateService;
+ private readonly ILastFMService _lastFMService;
private readonly ILogger _logger;
private readonly float _leftMargin = 36f;
@@ -110,6 +121,8 @@ namespace BetterLyrics.WinUI3.ViewModels
private readonly float _topMargin = 36f;
private readonly float _bottomMargin = 36f;
+ private DockPlacement _dockPlacement;
+
private Color _adaptiveGrayedFontColor = Colors.Transparent;
private Color? _adaptiveColoredFontColor = null;
@@ -157,8 +170,10 @@ namespace BetterLyrics.WinUI3.ViewModels
private bool _showTranslationOnly;
private int _targetLanguageIndex;
private bool _isLibreTranslateEnabled;
+ private string _lyricsTranslationSeparator;
- private int _timelineSyncThreshold;
+ private List _mediaSourceProvidersInfo;
+ private int _timelineSyncThreshold = 0;
private CanvasTextFormat _lyricsTextFormat = new()
{
@@ -357,6 +372,11 @@ namespace BetterLyrics.WinUI3.ViewModels
if (Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds) >= _timelineSyncThreshold)
{
TotalTime = e.Position;
+ if (TotalTime.TotalSeconds <= 1)
+ {
+ _totalPlayingTime = TimeSpan.Zero;
+ _isLastFMTracked = false;
+ }
}
}
@@ -364,6 +384,10 @@ namespace BetterLyrics.WinUI3.ViewModels
{
SongInfo = e.SongInfo;
+ UpdateTimelineSyncThreshold();
+ UpdatePositionOffset();
+ UpdateIsLastFMTrackEnabled();
+
if (SongInfo?.Title != _songTitle || SongInfo?.Artist != _songArtist)
{
_lastSongTitle = _songTitle;
@@ -383,6 +407,10 @@ namespace BetterLyrics.WinUI3.ViewModels
await RefreshLyricsAsync(token);
});
TotalTime = TimeSpan.Zero;
+
+ // 处理 Last.fm 追踪
+ _totalPlayingTime = TimeSpan.Zero;
+ _isLastFMTracked = false;
}
}
@@ -459,7 +487,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
else
{
- _lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], 50);
+ _lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _lyricsTranslationSeparator, 50);
_langIndex = 0;
}
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
@@ -480,7 +508,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
else
{
- _lyricsDataArr[0].SetDisplayedTextAlongWith(translated);
+ _lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _lyricsTranslationSeparator);
_langIndex = 0;
}
TranslationSearchProvider = Enums.TranslationSearchProvider.LibreTranslate;
@@ -508,6 +536,7 @@ namespace BetterLyrics.WinUI3.ViewModels
if (SongInfo != null)
{
(lyricsRaw, lyricsSearchProvider) = await _lyrcsSearchService.SearchAsync(
+ SongInfo.SourceAppUserModelId ?? "",
SongInfo.Title,
SongInfo.Artist,
SongInfo.Album ?? "",
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
index 484970a..3ab5078 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsWindowViewModel.cs
@@ -3,8 +3,11 @@
using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
+using BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel;
+using BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
@@ -17,6 +20,7 @@ using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using System;
using System.Diagnostics;
+using System.Linq;
using System.Threading.Tasks;
using Vanara.PInvoke;
using Windows.System;
@@ -34,7 +38,7 @@ namespace BetterLyrics.WinUI3
IRecipient>,
IRecipient>
{
- private readonly IPlaybackService _playbackService = Ioc.Default.GetRequiredService();
+ private readonly IMediaSessionsService _mediaSessionsService = Ioc.Default.GetRequiredService();
private ForegroundWindowWatcher? _windowWatcher = null;
private bool _ignoreFullscreenWindow;
private bool _hideWindowWhenNotPlaying;
@@ -53,7 +57,7 @@ namespace BetterLyrics.WinUI3
_dockWindowHeight = _settingsService.DockWindowHeight;
OnIsImmersiveModeChanged(_settingsService.IsImmersiveMode);
- _playbackService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
+ _mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
}
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
@@ -106,7 +110,7 @@ namespace BetterLyrics.WinUI3
if (IsDockMode || IsDesktopMode)
{
- if (_hideWindowWhenNotPlaying && !_playbackService.IsPlaying)
+ if (_hideWindowWhenNotPlaying && !_mediaSessionsService.IsPlaying)
{
if (IsDockMode)
{
@@ -222,16 +226,16 @@ namespace BetterLyrics.WinUI3
var hwnd = WindowNative.GetWindowHandle(window);
_windowWatcher = new ForegroundWindowWatcher(
hwnd,
- onWindowChanged =>
+ fgHwnd =>
{
_dispatcherQueueTimer.Debounce(() =>
{
- if (_ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
+ if ((IsDockMode || IsDesktopMode) && _ignoreFullscreenWindow && window.AppWindow.Presenter is OverlappedPresenter presenter)
{
presenter.IsAlwaysOnTop = true;
}
UpdateAccentColor(hwnd);
- }, TimeSpan.FromMilliseconds(300));
+ }, Constants.Time.DebounceTimeout);
}
);
_windowWatcher.Start();
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs
index 1676642..332352d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/MusicGalleryViewModel.cs
@@ -3,6 +3,8 @@ using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.SettingsService;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
@@ -408,9 +410,9 @@ namespace BetterLyrics.WinUI3.ViewModels
public void Receive(PropertyChangedMessage> message)
{
- if (message.Sender is SettingsPageViewModel)
+ if (message.Sender is SettingsPageViewModel.SettingsPageViewModel)
{
- if (message.PropertyName == nameof(SettingsPageViewModel.LocalMediaFolders))
+ if (message.PropertyName == nameof(SettingsPageViewModel.SettingsPageViewModel.LocalMediaFolders))
{
RefreshSongs();
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Ctor.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Ctor.cs
similarity index 65%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Ctor.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Ctor.cs
index 8216dfc..9ff29f8 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Ctor.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Ctor.cs
@@ -1,27 +1,43 @@
using BetterLyrics.WinUI3.Helper;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Models;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
+using BetterLyrics.WinUI3.Services.TranslateService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel
{
public partial class SettingsPageViewModel
{
- public SettingsPageViewModel(ISettingsService settingsService, ILibWatcherService libWatcherService, IPlaybackService playbackService, ITranslateService libreTranslateService) : base(settingsService)
+ public SettingsPageViewModel(
+ ISettingsService settingsService,
+ ILibWatcherService libWatcherService,
+ IMediaSessionsService mediaSessionsService,
+ ITranslateService libreTranslateService,
+ ILastFMService lastFMService) : base(settingsService)
{
_libWatcherService = libWatcherService;
- _playbackService = playbackService;
+ _mediaSessionsService = mediaSessionsService;
_libreTranslateService = libreTranslateService;
+ // LastFM
+ _lastFMService = lastFMService;
+ _lastFMService.UserChanged += LastFMService_UserChanged;
+ _lastFMService.IsAuthenticatedChanged += LastFMService_IsAuthenticatedChanged;
+ IsLastFMAuthenticated = _lastFMService.IsAuthenticated;
+ LastFMUser = _lastFMService.User;
+
IsLibreTranslateEnabled = _settingsService.IsLibreTranslateEnabled;
LibreTranslateServer = _settingsService.LibreTranslateServer;
SelectedTargetLanguageIndex = _settingsService.SelectedTargetLanguageIndex;
LocalMediaFolders = [.. _settingsService.LocalMediaFolders];
- LyricsSearchProvidersInfo = [.. _settingsService.LyricsSearchProvidersInfo];
AlbumArtSearchProvidersInfo = [.. _settingsService.AlbumArtSearchProvidersInfo];
Language = _settingsService.Language;
@@ -64,14 +80,14 @@ namespace BetterLyrics.WinUI3.ViewModels
LyricsFontStrokeWidth = _settingsService.LyricsFontStrokeWidth;
LyricsBackgroundTheme = _settingsService.LyricsBackgroundTheme;
MediaSourceProvidersInfo = [.. _settingsService.MediaSourceProvidersInfo];
+ SelectedMediaSourceProvider = MediaSourceProvidersInfo.FirstOrDefault();
+
IgnoreFullscreenWindow = _settingsService.IgnoreFullscreenWindow;
LyricsScrollEasingType = _settingsService.LyricsScrollEasingType;
LyricsScrollDuration = _settingsService.LyricsScrollDuration;
- TimelineSyncThreshold = _settingsService.TimelineSyncThreshold;
IsLyricsFloatAnimationEnabled = _settingsService.IsLyricsFloatAnimationEnabled;
- ResetPositionOffsetOnSongChanged = _settingsService.ResetPositionOffsetOnSongChanged;
LockHotKeyIndex = _settingsService.LockHotKeyIndex;
LXMusicServer = _settingsService.LXMusicServer;
@@ -88,7 +104,29 @@ namespace BetterLyrics.WinUI3.ViewModels
MonitorDeviceNames = [.. MonitorHelper.GetAllMonitorDeviceNames()];
SelectedDockMonitorDeviceName = _settingsService.DockMonitorDeviceName;
- _playbackService.MediaSourceProvidersInfoChanged += PlaybackService_SessionIdsChanged;
+ LyricsTranslationSeparator = _settingsService.LyricsTranslationSeparator;
+
+ _mediaSessionsService.MediaSourceProvidersInfoChanged += MediaSessionsService_SessionIdsChanged;
+ _mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
+ }
+
+ private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
+ {
+ var current = MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.SourceAppUserModelId)?.FirstOrDefault();
+ if (_mediaSessionsService.Position.TotalSeconds <= 1 && current?.ResetPositionOffsetOnSongChanged == true)
+ {
+ current.PositionOffset = 0;
+ }
+ }
+
+ private void LastFMService_IsAuthenticatedChanged(object? sender, Events.LastFMIsAuthenticatedChangedEventArgs e)
+ {
+ IsLastFMAuthenticated = e.IsAuthenticated;
+ }
+
+ private void LastFMService_UserChanged(object? sender, Events.LastFMUserChangedEventArgs e)
+ {
+ LastFMUser = e.User;
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.OnPropsChanged.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.OnPropsChanged.cs
similarity index 96%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.OnPropsChanged.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.OnPropsChanged.cs
index 557fc63..d8399aa 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.OnPropsChanged.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.OnPropsChanged.cs
@@ -5,7 +5,7 @@ using Microsoft.UI.Xaml;
using Windows.Globalization;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel
{
public partial class SettingsPageViewModel
{
@@ -176,18 +176,10 @@ namespace BetterLyrics.WinUI3.ViewModels
{
_settingsService.LyricsVerticalEdgeOpacity = value;
}
- partial void OnTimelineSyncThresholdChanged(int value)
- {
- _settingsService.TimelineSyncThreshold = value;
- }
partial void OnIsLyricsFloatAnimationEnabledChanged(bool value)
{
_settingsService.IsLyricsFloatAnimationEnabled = value;
}
- partial void OnResetPositionOffsetOnSongChangedChanged(bool value)
- {
- _settingsService.ResetPositionOffsetOnSongChanged = value;
- }
partial void OnLyricsBgFontOpacityChanged(int value)
{
_settingsService.LyricsBgFontOpacity = value;
@@ -227,5 +219,9 @@ namespace BetterLyrics.WinUI3.ViewModels
{
_settingsService.DockMonitorDeviceName = value;
}
+ partial void OnLyricsTranslationSeparatorChanged(string value)
+ {
+ _settingsService.LyricsTranslationSeparator = value;
+ }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Props.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Props.cs
similarity index 94%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Props.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Props.cs
index 4ffc74f..e64feb4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.Props.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.Props.cs
@@ -2,6 +2,7 @@
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using CommunityToolkit.Mvvm.ComponentModel;
+using Hqub.Lastfm.Entities;
using Microsoft.UI.Xaml;
using System;
using System.Collections.Generic;
@@ -11,7 +12,7 @@ using System.Text;
using System.Threading.Tasks;
using Windows.UI;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel
{
public partial class SettingsPageViewModel
{
@@ -87,10 +88,6 @@ namespace BetterLyrics.WinUI3.ViewModels
[ObservableProperty]
public partial ObservableCollection LocalMediaFolders { get; set; }
- [ObservableProperty]
- [NotifyPropertyChangedRecipients]
- public partial ObservableCollection LyricsSearchProvidersInfo { get; set; }
-
[ObservableProperty]
[NotifyPropertyChangedRecipients]
public partial ObservableCollection AlbumArtSearchProvidersInfo { get; set; }
@@ -98,6 +95,9 @@ namespace BetterLyrics.WinUI3.ViewModels
[ObservableProperty]
public partial ObservableCollection MediaSourceProvidersInfo { get; set; }
+ [ObservableProperty]
+ public partial MediaSourceProviderInfo? SelectedMediaSourceProvider { get; set; }
+
[ObservableProperty]
[NotifyPropertyChangedRecipients]
public partial bool IsFanLyricsEnabled { get; set; }
@@ -181,10 +181,6 @@ namespace BetterLyrics.WinUI3.ViewModels
[ObservableProperty]
public partial object NavViewSelectedItemTag { get; set; } = "App";
- [ObservableProperty]
- [NotifyPropertyChangedRecipients]
- public partial bool ResetPositionOffsetOnSongChanged { get; set; }
-
[ObservableProperty]
[NotifyPropertyChangedRecipients]
public partial bool IsLyricsFloatAnimationEnabled { get; set; }
@@ -215,10 +211,6 @@ namespace BetterLyrics.WinUI3.ViewModels
[NotifyPropertyChangedRecipients]
public partial int LyricsScrollDuration { get; set; }
- [ObservableProperty]
- [NotifyPropertyChangedRecipients]
- public partial int TimelineSyncThreshold { get; set; }
-
[ObservableProperty]
public partial bool IsLXMusicServerTesting { get; set; } = false;
@@ -234,11 +226,23 @@ namespace BetterLyrics.WinUI3.ViewModels
[NotifyPropertyChangedRecipients]
public partial int DockWindowHeight { get; set; }
+ // Dock Monitor
[ObservableProperty]
[NotifyPropertyChangedRecipients]
public partial string SelectedDockMonitorDeviceName { get; set; }
[ObservableProperty]
public partial ObservableCollection MonitorDeviceNames { get; set; }
+
+ // LastFM
+ [ObservableProperty]
+ public partial bool IsLastFMAuthenticated { get; set; }
+
+ [ObservableProperty]
+ public partial User? LastFMUser { get; set; }
+
+ [ObservableProperty]
+ [NotifyPropertyChangedRecipients]
+ public partial string LyricsTranslationSeparator { get; set; }
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.cs
similarity index 84%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.cs
index 4ff714a..7b8dbb6 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsPageViewModel/SettingsPageViewModel.cs
@@ -4,45 +4,45 @@ using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.LastFMService;
+using BetterLyrics.WinUI3.Services.LibWatcherService;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.TranslateService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.WinUI;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
-using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel;
-using Windows.Globalization;
-using Windows.UI;
using WinRT.Interop;
-using MetadataHelper = BetterLyrics.WinUI3.Helper.MetadataHelper;
-namespace BetterLyrics.WinUI3.ViewModels
+namespace BetterLyrics.WinUI3.ViewModels.SettingsPageViewModel
{
public partial class SettingsPageViewModel : BaseViewModel
{
private readonly ILibWatcherService _libWatcherService;
- private readonly IPlaybackService _playbackService;
+ private readonly IMediaSessionsService _mediaSessionsService;
private readonly ITranslateService _libreTranslateService;
+ private readonly ILastFMService _lastFMService;
- private readonly string _autoStartupTaskId = "AutoStartup";
-
- private void PlaybackService_SessionIdsChanged(object? sender, Events.MediaSourceProvidersInfoEventArgs e)
+ private void MediaSessionsService_SessionIdsChanged(object? sender, Events.MediaSourceProvidersInfoEventArgs e)
{
MediaSourceProvidersInfo = [.. e.MediaSourceProviersInfo];
}
public void OnLyricsSearchProvidersReordered()
{
- _settingsService.LyricsSearchProvidersInfo = [.. LyricsSearchProvidersInfo];
+ _settingsService.MediaSourceProvidersInfo = [.. MediaSourceProvidersInfo];
Broadcast(
- LyricsSearchProvidersInfo,
- LyricsSearchProvidersInfo,
- nameof(LyricsSearchProvidersInfo)
+ MediaSourceProvidersInfo,
+ MediaSourceProvidersInfo,
+ nameof(MediaSourceProvidersInfo)
);
}
@@ -70,16 +70,6 @@ namespace BetterLyrics.WinUI3.ViewModels
Broadcast(LocalMediaFolders, LocalMediaFolders, nameof(LocalMediaFolders));
}
- public void ToggleLyricsSearchProvider()
- {
- _settingsService.LyricsSearchProvidersInfo = [.. LyricsSearchProvidersInfo];
- Broadcast(
- LyricsSearchProvidersInfo,
- LyricsSearchProvidersInfo,
- nameof(LyricsSearchProvidersInfo)
- );
- }
-
public void ToggleAlbumArtSearchProvider(AlbumArtSearchProviderInfo providerInfo)
{
_settingsService.AlbumArtSearchProvidersInfo = [.. AlbumArtSearchProvidersInfo];
@@ -90,13 +80,17 @@ namespace BetterLyrics.WinUI3.ViewModels
);
}
- public void ToggleMediaSourceProvider(MediaSourceProviderInfo providerInfo)
+ public void BroadcastMediaSourceProvidersInfoChanged()
{
- Broadcast(
- MediaSourceProvidersInfo,
- MediaSourceProvidersInfo,
- nameof(MediaSourceProvidersInfo)
- );
+ _dispatcherQueueTimer.Debounce(() =>
+ {
+ _settingsService.MediaSourceProvidersInfo = [.. MediaSourceProvidersInfo];
+ Broadcast(
+ MediaSourceProvidersInfo,
+ MediaSourceProvidersInfo,
+ nameof(MediaSourceProvidersInfo)
+ );
+ }, TimeSpan.FromMilliseconds(100));
}
private void AddFolderAsync(string path)
@@ -130,7 +124,7 @@ namespace BetterLyrics.WinUI3.ViewModels
[RelayCommand]
private async Task LaunchProjectGitHubPageAsync()
{
- await Windows.System.Launcher.LaunchUriAsync(new Uri(MetadataHelper.GithubUrl));
+ await Windows.System.Launcher.LaunchUriAsync(new Uri(Constants.Link.GithubUrl));
}
[RelayCommand]
@@ -223,9 +217,27 @@ namespace BetterLyrics.WinUI3.ViewModels
SelectedDockMonitorDeviceName = MonitorHelper.GetPrimaryMonitorDeviceName();
}
+ [RelayCommand]
+ private async Task LastFMAuthAsync()
+ {
+ await _lastFMService.AuthAsync();
+ }
+
+ [RelayCommand]
+ private async Task LastFMUnAuthAsync()
+ {
+ await _lastFMService.UnAuthAsync();
+ }
+
+ [RelayCommand]
+ private async Task LastFMRefreshAsync()
+ {
+ await _lastFMService.RefreshAsync();
+ }
+
public async Task ToggleAutoStartupAsync(bool target)
{
- StartupTask startupTask = await StartupTask.GetAsync(_autoStartupTaskId);
+ StartupTask startupTask = await StartupTask.GetAsync(Constants.App.AutoStartupTaskId);
if (target)
{
await startupTask.RequestEnableAsync();
@@ -240,7 +252,7 @@ namespace BetterLyrics.WinUI3.ViewModels
public async Task DetectIsAutoStartupEnabledAsync()
{
bool result = false;
- var startupTask = await StartupTask.GetAsync(_autoStartupTaskId);
+ var startupTask = await StartupTask.GetAsync(Constants.App.AutoStartupTaskId);
switch (startupTask.State)
{
case StartupTaskState.Disabled:
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs
index d79b4d9..d19b0bf 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SettingsWindowViewModel.cs
@@ -1,4 +1,4 @@
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
namespace BetterLyrics.WinUI3.ViewModels
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs
index ee129f6..89512e3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/SystemTrayViewModel.cs
@@ -1,5 +1,5 @@
using BetterLyrics.WinUI3.Helper;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -18,7 +18,7 @@ namespace BetterLyrics.WinUI3.ViewModels
public partial bool IsLyricsWindowLocked { get; set; } = false;
[ObservableProperty]
- public partial string ToolTipText { get; set; } = MetadataHelper.AppName;
+ public partial string ToolTipText { get; set; } = Constants.App.AppName;
public void Receive(PropertyChangedMessage message)
{
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
index b9d2880..3181b32 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml
@@ -79,52 +79,6 @@
-
-
-
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
index b7e1fa6..86ce8a3 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsPage.xaml.cs
@@ -1,7 +1,8 @@
// 2025/6/23 by Zhe Fang
using BetterLyrics.WinUI3.Enums;
-using BetterLyrics.WinUI3.Services;
+using BetterLyrics.WinUI3.Services.MediaSessionsService;
+using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
using CommunityToolkit.Mvvm.DependencyInjection;
using Microsoft.UI.Xaml;
@@ -16,7 +17,7 @@ namespace BetterLyrics.WinUI3.Views
public sealed partial class LyricsPage : Page
{
private readonly ISettingsService _settingsService = Ioc.Default.GetRequiredService();
- private readonly IPlaybackService _playbackService = Ioc.Default.GetRequiredService();
+ private readonly IMediaSessionsService _mediaSessionsService = Ioc.Default.GetRequiredService();
public LyricsPageViewModel ViewModel => (LyricsPageViewModel)DataContext;
@@ -50,11 +51,6 @@ namespace BetterLyrics.WinUI3.Views
_settingsService.DisplayType = ViewModel.DisplayType;
}
- private void PositionOffsetResetButton_Click(object sender, RoutedEventArgs e)
- {
- ViewModel.PositionOffset = 0;
- }
-
private void BottomCommandGrid_PointerEntered(object sender, Microsoft.UI.Xaml.Input.PointerRoutedEventArgs e)
{
if (ViewModel.IsImmersiveMode && BottomCommandGrid.Children.Count != 0)
@@ -78,11 +74,6 @@ namespace BetterLyrics.WinUI3.Views
DisplayTypeSwitchFlyout.ShowAt(BottomRightCommandStackPanel);
}
- private void TimelineOffsetButton_Click(object sender, RoutedEventArgs e)
- {
- TimelineOffsetFlyout.ShowAt(BottomLeftCommandStackPanel);
- }
-
private void TranslationButton_Click(object sender, RoutedEventArgs e)
{
TranslationFlyout.ShowAt(BottomRightCommandStackPanel);
@@ -142,7 +133,7 @@ namespace BetterLyrics.WinUI3.Views
private void TimelineSliderOverlay_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e)
{
- _playbackService.ChangePosition(TimelineSlider.Value);
+ _mediaSessionsService.ChangePosition(TimelineSlider.Value);
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
index 95b8de4..98d8fee 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/LyricsWindow.xaml
@@ -123,6 +123,9 @@
Command="{x:Bind ViewModel.ImmersiveToggleButtonEnabledChangedCommand}"
IsChecked="{x:Bind ViewModel.IsImmersiveMode, Mode=TwoWay}"
Style="{StaticResource TitleBarToggleButtonStyle}">
+
+
+
+
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
index ab57eae..7329877 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Views/MusicGalleryPage.xaml.cs
@@ -167,5 +167,15 @@ namespace BetterLyrics.WinUI3.Views
ViewModel.SelectedSongsTabInfoIndex = 0;
ViewModel.ApplyPlaylist();
}
+
+ private void PlayAllButton_Click(object sender, RoutedEventArgs e)
+ {
+ ViewModel.TrackPlayingQueue.Clear();
+ ViewModel.PlayingSongIndex = -1;
+
+ ViewModel.TrackPlayingQueue.InsertRange(ViewModel.PlayingSongIndex + 1, SongListView.Items.Cast