diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
index 1321fa2..bf1313e 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3 (Package)/Package.appxmanifest
@@ -12,7 +12,7 @@
+ Version="1.0.28.0" />
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
index ab84ce7..529d2bf 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/App.xaml.cs
@@ -10,10 +10,12 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.ApplicationModel.Resources;
using Serilog;
using ShadowViewer.Controls;
using System;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/PositionChangedEventArgs.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/TimelineChangedEventArgs.cs
similarity index 53%
rename from BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/PositionChangedEventArgs.cs
rename to BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/TimelineChangedEventArgs.cs
index c563a77..5b64c5d 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/PositionChangedEventArgs.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/TimelineChangedEventArgs.cs
@@ -4,8 +4,9 @@ using System;
namespace BetterLyrics.WinUI3.Events
{
- public class PositionChangedEventArgs(TimeSpan position) : EventArgs()
+ public class TimelineChangedEventArgs(TimeSpan position, TimeSpan end) : EventArgs()
{
public TimeSpan Position { get; set; } = position;
+ public TimeSpan End { get; set; } = end;
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
index cec9601..e1dde67 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs
@@ -109,7 +109,12 @@ namespace BetterLyrics.WinUI3.Helper
// 按时间分组
var grouped = lrcLines.GroupBy(l => l.time).OrderBy(g => g.Key).ToList();
- int languageCount = grouped.Max(g => g.Count());
+ int languageCount = 0;
+ if (grouped != null && grouped.Count > 0)
+ {
+ // 计算最大语言数量
+ languageCount = grouped.Max(g => g.Count());
+ }
// 初始化每种语言的歌词列表
_lyricsDataArr.Clear();
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs
index 4631e23..bd718dd 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IPlaybackService.cs
@@ -10,7 +10,7 @@ namespace BetterLyrics.WinUI3.Services
public interface IPlaybackService
{
event EventHandler? IsPlayingChanged;
- event EventHandler? PositionChanged;
+ event EventHandler? TimelineChanged;
event EventHandler? SongInfoChanged;
event EventHandler? AlbumArtChangedChanged;
event EventHandler? MediaSourceProvidersInfoChanged;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
index d765853..d4b7648 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs
@@ -37,13 +37,14 @@ namespace BetterLyrics.WinUI3.Services
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 EventSourceReader? _sse = null;
private readonly MediaManager _mediaManager = new();
- private MediaManager.MediaSession? _focusedSession = null;
private readonly LatestOnlyTaskRunner _albumArtRefreshRunner = new();
private readonly LatestOnlyTaskRunner _onAnyMediaPropertyChangedRunner = new();
@@ -53,7 +54,7 @@ namespace BetterLyrics.WinUI3.Services
private byte[]? _SMTCAlbumArtBytes = null;
public event EventHandler? IsPlayingChanged;
- public event EventHandler? PositionChanged;
+ public event EventHandler? TimelineChanged;
public event EventHandler? SongInfoChanged;
public event EventHandler? AlbumArtChangedChanged;
public event EventHandler? MediaSourceProvidersInfoChanged;
@@ -95,34 +96,33 @@ namespace BetterLyrics.WinUI3.Services
{
if (!_mediaManager.IsStarted) return;
- _focusedSession = mediaSession ?? _mediaManager.GetFocusedSession();
-
- if (_focusedSession == null || !IsMediaSourceEnabled(_focusedSession.Id))
- {
- SendNullMessages();
- }
- else
- {
- SendFocusedMessagesAsync().ConfigureAwait(false);
- }
+ SendFocusedMessagesAsync().ConfigureAwait(false);
}
private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties)
{
if (!_mediaManager.IsStarted) return;
- if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != _focusedSession) return;
+ if (mediaSession == null) return;
+
+ var focusedSession = _mediaManager.GetFocusedSession();
+
+ if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != focusedSession) return;
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
{
- PositionChanged?.Invoke(this, new PositionChangedEventArgs(timelineProperties.Position));
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(timelineProperties.Position, timelineProperties.EndTime));
});
}
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo)
{
if (!_mediaManager.IsStarted) return;
+ if (mediaSession == null) return;
+
+ var focusedSession = _mediaManager.GetFocusedSession();
+
RecordMediaSourceProviderInfo(mediaSession);
- if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != _focusedSession) return;
+ if (!IsMediaSourceEnabled(mediaSession.Id) || mediaSession != focusedSession) return;
_cachedIsPlaying = playbackInfo.PlaybackStatus switch
{
@@ -139,10 +139,14 @@ namespace BetterLyrics.WinUI3.Services
private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties)
{
if (!_mediaManager.IsStarted) return;
+ if (mediaSession == null) return;
+
string id = mediaSession.Id;
+ var focusedSession = _mediaManager.GetFocusedSession();
+
RecordMediaSourceProviderInfo(mediaSession);
- if (!IsMediaSourceEnabled(id) || mediaSession != _focusedSession) return;
+ if (!IsMediaSourceEnabled(id) || mediaSession != focusedSession) return;
_cachedSongInfo = new SongInfo
{
@@ -196,6 +200,8 @@ namespace BetterLyrics.WinUI3.Services
private void MediaManager_OnAnySessionClosed(MediaManager.MediaSession mediaSession)
{
if (!_mediaManager.IsStarted) return;
+ if (mediaSession == null) return;
+
if (_mediaManager.CurrentMediaSessions.Count == 0)
{
SendNullMessages();
@@ -205,14 +211,17 @@ namespace BetterLyrics.WinUI3.Services
private void MediaManager_OnAnySessionOpened(MediaManager.MediaSession mediaSession)
{
if (!_mediaManager.IsStarted) return;
+ if (mediaSession == null) return;
+
RecordMediaSourceProviderInfo(mediaSession);
- _focusedSession = _mediaManager.GetFocusedSession();
SendFocusedMessagesAsync().ConfigureAwait(false);
}
private void RecordMediaSourceProviderInfo(MediaManager.MediaSession mediaSession)
{
if (!_mediaManager.IsStarted) return;
+ if (mediaSession == null) return;
+
var id = mediaSession?.Id;
if (string.IsNullOrEmpty(id)) return;
@@ -236,18 +245,19 @@ namespace BetterLyrics.WinUI3.Services
_cachedIsPlaying = false;
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
IsPlayingChanged?.Invoke(this, new IsPlayingChangedEventArgs(_cachedIsPlaying));
- PositionChanged?.Invoke(this, new PositionChangedEventArgs(TimeSpan.Zero));
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.Zero, TimeSpan.Zero));
});
}
private async Task SendFocusedMessagesAsync()
{
- if (_focusedSession == null) return;
+ var focusedSession = _mediaManager.GetFocusedSession();
+ if (focusedSession == null || focusedSession.ControlSession == null) return;
- var mediaProps = await _focusedSession.ControlSession.TryGetMediaPropertiesAsync();
- MediaManager_OnAnyMediaPropertyChanged(_focusedSession, mediaProps);
- MediaManager_OnAnyPlaybackStateChanged(_focusedSession, _focusedSession.ControlSession.GetPlaybackInfo());
- MediaManager_OnAnyTimelinePropertyChanged(_focusedSession, _focusedSession.ControlSession.GetTimelineProperties());
+ var mediaProps = await focusedSession.ControlSession.TryGetMediaPropertiesAsync();
+ MediaManager_OnAnyMediaPropertyChanged(focusedSession, mediaProps);
+ MediaManager_OnAnyPlaybackStateChanged(focusedSession, focusedSession.ControlSession.GetPlaybackInfo());
+ MediaManager_OnAnyTimelinePropertyChanged(focusedSession, focusedSession.ControlSession.GetTimelineProperties());
}
private async Task UpdateAlbumArtRelated(CancellationToken token)
@@ -296,7 +306,7 @@ namespace BetterLyrics.WinUI3.Services
{
try
{
- _sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}/subscribe-player-status?filter=progress")).Start();
+ _sse = new EventSourceReader(new Uri($"{_settingsService.LXMusicServer}/subscribe-player-status?filter=progress,duration")).Start();
_sse.MessageReceived += Sse_MessageReceived;
_sse.Disconnected += Sse_Disconnected;
}
@@ -334,39 +344,54 @@ namespace BetterLyrics.WinUI3.Services
private void Sse_MessageReceived(object sender, EventSourceMessageEventArgs e)
{
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
-
- if (data.TryGetDouble(out double positionSeconds))
+ if (data.TryGetDouble(out double seconds))
{
if (_cachedSongInfo?.SourceAppUserModelId == _lxMusicId)
{
- PositionChanged?.Invoke(this, new PositionChangedEventArgs(TimeSpan.FromSeconds(positionSeconds)));
+ if (e.Event == "progress")
+ {
+ _lxMusicPositionSeconds = seconds;
+ }
+ else if (e.Event == "duration")
+ {
+ _lxMusicDurationSeconds = seconds;
+ }
+ _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
+ {
+ TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
+ });
}
}
}
public async Task PlayAsync()
{
- await _focusedSession?.ControlSession.TryPlayAsync();
+ var focusedSession = _mediaManager.GetFocusedSession();
+ await focusedSession?.ControlSession.TryPlayAsync();
}
public async Task PauseAsync()
{
- await _focusedSession?.ControlSession.TryPauseAsync();
+ var focusedSession = _mediaManager.GetFocusedSession();
+ await focusedSession?.ControlSession.TryPauseAsync();
}
public async Task PreviousAsync()
{
- await _focusedSession?.ControlSession.TrySkipPreviousAsync();
+ var focusedSession = _mediaManager.GetFocusedSession();
+ await focusedSession?.ControlSession.TrySkipPreviousAsync();
}
public async Task NextAsync()
{
- await _focusedSession?.ControlSession.TrySkipNextAsync();
+ var focusedSession = _mediaManager.GetFocusedSession();
+ await focusedSession?.ControlSession.TrySkipNextAsync();
}
public async Task ChangePosition(double seconds)
{
- await _focusedSession?.ControlSession.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
+ var focusedSession = _mediaManager.GetFocusedSession();
+ await focusedSession?.ControlSession.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks);
}
public void Receive(PropertyChangedMessage> message)
@@ -377,7 +402,7 @@ namespace BetterLyrics.WinUI3.Services
{
_mediaSourceProvidersInfo = [.. message.NewValue];
_settingsService.MediaSourceProvidersInfo = _mediaSourceProvidersInfo;
- MediaManager_OnFocusedSessionChanged(_mediaManager.GetFocusedSession());
+ MediaManager_OnFocusedSessionChanged(null);
}
}
}
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
index d5bc7b5..938d7f6 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsPageViewModel.cs
@@ -48,10 +48,16 @@ namespace BetterLyrics.WinUI3.ViewModels
_playbackService = playbackService;
_playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
_playbackService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
+ _playbackService.TimelineChanged += PlaybackService_TimelineChanged;
IsSongPlaying = _playbackService.IsPlaying;
}
+ private void PlaybackService_TimelineChanged(object? sender, Events.TimelineChangedEventArgs e)
+ {
+ SongDurationSeconds = (int)e.End.TotalSeconds;
+ }
+
//private void SystemVolumeHelper_VolumeChanged(int volume)
//{
// Volume = volume;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs
index fb6d9da..6de1b17 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.Ctor.cs
@@ -65,7 +65,7 @@ namespace BetterLyrics.WinUI3.ViewModels
_playbackService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
_playbackService.SongInfoChanged += PlaybackService_SongInfoChanged;
_playbackService.AlbumArtChangedChanged += PlaybackService_AlbumArtChangedChanged;
- _playbackService.PositionChanged += PlaybackService_PositionChanged;
+ _playbackService.TimelineChanged += PlaybackService_TimelineChanged;
_isPlaying = _playbackService.IsPlaying;
diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs
index 9e82202..1ddf9d4 100644
--- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs
+++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs
@@ -335,7 +335,7 @@ namespace BetterLyrics.WinUI3.ViewModels
_isPlaying = e.IsPlaying;
}
- private void PlaybackService_PositionChanged(object? sender, PositionChangedEventArgs e)
+ private void PlaybackService_TimelineChanged(object? sender, TimelineChangedEventArgs e)
{
if (Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds) >= _timelineSyncThreshold)
{