From de3d6f16957766afe3f58ab2eb59df35a1462cbe Mon Sep 17 00:00:00 2001 From: Zhe Fang Date: Wed, 23 Jul 2025 13:54:30 -0400 Subject: [PATCH] fix --- .../Package.appxmanifest | 2 +- .../BetterLyrics.WinUI3/App.xaml.cs | 2 + ...entArgs.cs => TimelineChangedEventArgs.cs} | 3 +- .../Helper/LyricsParser.cs | 7 +- .../Services/IPlaybackService.cs | 2 +- .../Services/PlaybackService.cs | 91 ++++++++++++------- .../ViewModels/LyricsPageViewModel.cs | 6 ++ .../LyricsRendererViewModel.Ctor.cs | 2 +- .../ViewModels/LyricsRendererViewModel.cs | 2 +- 9 files changed, 78 insertions(+), 39 deletions(-) rename BetterLyrics.WinUI3/BetterLyrics.WinUI3/Events/{PositionChangedEventArgs.cs => TimelineChangedEventArgs.cs} (53%) 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) {