diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/SongInfoExtensions.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/SongInfoExtensions.cs index f060eea..7190e46 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/SongInfoExtensions.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Extensions/SongInfoExtensions.cs @@ -5,7 +5,7 @@ namespace BetterLyrics.WinUI3.Extensions { public static class SongInfoExtensions { - public static SongInfo Placeholder => new SongInfo + public static SongInfo Placeholder => new() { Title = "N/A", Album = "N/A", diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.AlbumArtUpdater.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.AlbumArtUpdater.cs index e451ceb..1de5159 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.AlbumArtUpdater.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.AlbumArtUpdater.cs @@ -42,15 +42,13 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService { _logger.LogInformation("RefreshArtAlbum"); - if (CurrentSongInfo == null) + IBuffer? buffer = null; + if (CurrentSongInfo != SongInfoExtensions.Placeholder) { - _logger.LogWarning("CurrentSongInfo == null"); - return; + buffer = await Task.Run(async () => await _albumArtSearchService.SearchAsync(CurrentSongInfo, _SMTCAlbumArtBuffer, token), token); + if (token.IsCancellationRequested) return; } - IBuffer? buffer = await Task.Run(async () => await _albumArtSearchService.SearchAsync(CurrentSongInfo, _SMTCAlbumArtBuffer, token), token); - if (token.IsCancellationRequested) return; - if (buffer == null) { using var placeHolderStream = await ImageHelper.GetAlbumArtPlaceholderAsync(); diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.LyricsUpdater.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.LyricsUpdater.cs index 25101d1..2f9cad4 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.LyricsUpdater.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.LyricsUpdater.cs @@ -24,7 +24,7 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService CurrentLyricsSearchResult = null; CurrentLyricsData = LyricsData.GetLoadingPlaceholder(); - if (CurrentSongInfo != null) + if (CurrentSongInfo != SongInfoExtensions.Placeholder) { CurrentLyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync( CurrentSongInfo, @@ -48,6 +48,11 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService token); } } + + if (CurrentLyricsSearchResult == null) + { + CurrentLyricsData = LyricsData.GetNotfoundPlaceholder(); + } } public async void UpdateLyrics() diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.cs index 79f0945..31f41bd 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/GSMTCService.cs @@ -26,6 +26,7 @@ using CommunityToolkit.WinUI; using EvtSource; using Microsoft.Extensions.Logging; using Microsoft.UI.Dispatching; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using System; using System.Diagnostics; @@ -50,6 +51,10 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private readonly MediaManager _mediaManager = new(); private IBuffer? _SMTCAlbumArtBuffer = null; + private MediaManager.MediaSession? _currentDesiredSession = null; + + private readonly StatsDashboardControlViewModel _statsDashboardControlViewModel; + private readonly IAlbumArtSearchService _albumArtSearchService; private readonly ILyricsSearchService _lyrcsSearchService; private readonly ITranslationService _translationService; @@ -64,16 +69,20 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private byte[]? _lxMusicAlbumArtBytes = null; private readonly DispatcherQueueTimer? _onMediaPropsChangedTimer; + private readonly DispatcherTimer _scrobbleTimer; - private readonly Stopwatch _scrobbleStopwatch = new(); + [ObservableProperty] public partial bool IsScrobbled { get; set; } = false; + [ObservableProperty] public partial TimeSpan ScrobbledDuration { get; set; } = TimeSpan.Zero; + [ObservableProperty] public partial TimeSpan TargetScrobbledDuration { get; set; } = TimeSpan.Zero; [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool CurrentIsPlaying { get; private set; } = false; [ObservableProperty][NotifyPropertyChangedRecipients] public partial TimeSpan CurrentPosition { get; private set; } = TimeSpan.Zero; - [ObservableProperty][NotifyPropertyChangedRecipients] public partial SongInfo? CurrentSongInfo { get; private set; } = SongInfoExtensions.Placeholder; + [ObservableProperty][NotifyPropertyChangedRecipients] public partial SongInfo CurrentSongInfo { get; private set; } = SongInfoExtensions.Placeholder; [ObservableProperty] public partial MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; set; } public GSMTCService( + StatsDashboardControlViewModel statsDashboardControlViewModel, ISettingsService settingsService, IAlbumArtSearchService albumArtSearchService, ILyricsSearchService lyricsSearchService, @@ -84,6 +93,8 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService ILastFMService lastFMService, ILogger logger) { + _statsDashboardControlViewModel = statsDashboardControlViewModel; + _settingsService = settingsService; _albumArtSearchService = albumArtSearchService; _lyrcsSearchService = lyricsSearchService; @@ -94,6 +105,10 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService _lastFMService = lastFMService; _logger = logger; + _scrobbleTimer = new(); + _scrobbleTimer.Interval = TimeSpan.FromSeconds(1); + _scrobbleTimer.Tick += ScrobbleTimer_Tick; + _onMediaPropsChangedTimer = _dispatcherQueue.CreateTimer(); _settingsService.AppSettings.MediaSourceProvidersInfo.ItemPropertyChanged += MediaSourceProvidersInfo_ItemPropertyChanged; @@ -106,6 +121,45 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService InitMediaManager(); } + private void ScrobbleTimer_Tick(object? sender, object e) + { + if (!IsScrobbled) + { + if (!string.IsNullOrWhiteSpace(CurrentSongInfo.Title) && CurrentSongInfo.Title != "N/A") + { + ScrobbledDuration += _scrobbleTimer.Interval; + if (ScrobbledDuration >= TargetScrobbledDuration) + { + // 写入本地播放记录 + var playHistoryItem = CurrentSongInfo.ToPlayHistoryItem(ScrobbledDuration.TotalMilliseconds); + if (playHistoryItem != null) + { + // 后台 + _ = Task.Run(async () => + { + await _playHistoryService.AddLogAsync(playHistoryItem); + _dispatcherQueue.TryEnqueue(() => + { + _statsDashboardControlViewModel.RefreshData(); + }); + }); + _logger.LogInformation("ScrobbleTimer_Tick: {} scrobbled", CurrentSongInfo.Title); + } + // 写入 Last.fm 播放记录 + var isLastFMEnabled = CurrentMediaSourceProviderInfo?.IsLastFMTrackEnabled ?? false; + if (isLastFMEnabled) + { + // 后台 + _ = Task.Run(() => _lastFMService.TrackAsync(CurrentSongInfo)); + } + + IsScrobbled = true; + ScrobbledDuration = TimeSpan.Zero; + } + } + } + } + private void MappedSongSearchQueries_ItemPropertyChanged(object? sender, ItemPropertyChangedEventArgs e) { UpdateLyrics(); @@ -143,10 +197,9 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService } } - private MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo() + private MediaSourceProviderInfo? GetCurrentDesiredMediaSourceProviderInfo() { - var desiredSession = GetCurrentSession(); - return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == desiredSession?.Id); + return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == _currentDesiredSession?.Id); } private bool IsMediaSourceEnabled(string id) @@ -176,6 +229,8 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private void InitMediaManager() { + _mediaManager.Start(); + _mediaManager.OnAnySessionOpened += MediaManager_OnAnySessionOpened; _mediaManager.OnAnySessionClosed += MediaManager_OnAnySessionClosed; _mediaManager.OnFocusedSessionChanged += MediaManager_OnFocusedSessionChanged; @@ -183,221 +238,150 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService _mediaManager.OnAnyPlaybackStateChanged += MediaManager_OnAnyPlaybackStateChanged; _mediaManager.OnAnyTimelinePropertyChanged += MediaManager_OnAnyTimelinePropertyChanged; - _mediaManager.Start(); - - MediaManager_OnFocusedSessionChanged(null); _mediaManager.CurrentMediaSessions.ToList().ForEach(x => RecordMediaSourceProviderInfo(x.Value)); + OnDesiredSessionChanged(true); } - private async void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession? mediaSession) + private void OnDesiredSessionChanged(bool firstTime = false) { - if (!_mediaManager.IsStarted) return; - - await SendFocusedMessagesAsync(); - } - - private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties? timelineProperties) - { - _dispatcherQueue.TryEnqueue(() => + var desiredSession = GetCurrentDesiredSession(); + if (firstTime || desiredSession != _currentDesiredSession) { - if (!_mediaManager.IsStarted) return; - if (mediaSession == null) + _currentDesiredSession = desiredSession; + if (_currentDesiredSession == null) { - _scrobbleStopwatch.Reset(); - CurrentPosition = TimeSpan.Zero; - return; - } - - var desiredSession = GetCurrentSession(); - - if (mediaSession != desiredSession) return; - - if (!IsMediaSourceEnabled(mediaSession.Id)) - { - _scrobbleStopwatch.Reset(); - CurrentPosition = TimeSpan.Zero; + SendNullMessages(); } else { - if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id)) - { - CurrentPosition = timelineProperties?.Position ?? TimeSpan.Zero; - CurrentSongInfo?.DurationMs = timelineProperties?.EndTime.TotalMilliseconds ?? 0; - } + _ = SendFocusedMessagesAsync(); + } + } + } + + private void MediaManager_OnFocusedSessionChanged(MediaManager.MediaSession? mediaSession) + { + OnDesiredSessionChanged(); + } + + private void MediaManager_OnAnyTimelinePropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionTimelineProperties timelineProperties) + { + _dispatcherQueue.TryEnqueue(() => + { + if (mediaSession != _currentDesiredSession) return; + + CurrentPosition = timelineProperties.Position; + CurrentSongInfo.DurationMs = timelineProperties.EndTime.TotalMilliseconds; + UpdateTargetScrobbledDuration(); + }); + } + + private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo) + { + _dispatcherQueue.TryEnqueue(() => + { + if (mediaSession != _currentDesiredSession) return; + + CurrentIsPlaying = playbackInfo.PlaybackStatus switch + { + GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true, + _ => false, + }; + + if (CurrentIsPlaying) + { + _scrobbleTimer.Start(); + } + else + { + _scrobbleTimer.Stop(); } }); } - private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo) - { - _dispatcherQueue.TryEnqueue(() => - { - if (!_mediaManager.IsStarted) return; - if (mediaSession == null) - { - CurrentIsPlaying = false; - return; - } - - var desiredSession = GetCurrentSession(); - - if (mediaSession != desiredSession) return; - - if (!IsMediaSourceEnabled(mediaSession.Id)) - { - CurrentIsPlaying = false; - } - else - { - CurrentIsPlaying = playbackInfo?.PlaybackStatus switch - { - GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true, - _ => false, - }; - - if (CurrentIsPlaying) - { - _scrobbleStopwatch.Start(); - } - else - { - _scrobbleStopwatch.Stop(); - } - } - }); - } - - private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties? mediaProperties) + private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties mediaProperties) { _onMediaPropsChangedTimer?.Debounce(() => { _dispatcherQueue.TryEnqueue(async () => { - if (!_mediaManager.IsStarted) return; - if (mediaSession == null) + if (mediaSession != _currentDesiredSession) return; + + string sessionId = mediaSession.Id; + + var currentMediaSourceProviderInfo = GetCurrentDesiredMediaSourceProviderInfo(); + if (currentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true) { - CurrentSongInfo = SongInfoExtensions.Placeholder; + currentMediaSourceProviderInfo?.PositionOffset = 0; } - string? sessionId = mediaSession?.Id; + string fixedArtist = mediaProperties.Artist; + string fixedAlbum = mediaProperties.AlbumTitle; + string? songId = null; - var desiredSession = GetCurrentSession(); - - if (mediaSession != desiredSession) return; - - if (sessionId != null && !IsMediaSourceEnabled(sessionId)) + if (PlayerIdHelper.IsAppleMusic(sessionId)) { - CurrentSongInfo = SongInfoExtensions.Placeholder; + fixedArtist = mediaProperties.Artist.Split(" — ").First(); + fixedAlbum = mediaProperties.Artist.Split(" — ").Last(); + fixedAlbum = fixedAlbum.Replace(" - Single", ""); + fixedAlbum = fixedAlbum.Replace(" - EP", ""); + } + else if (PlayerIdHelper.IsNeteaseFamily(sessionId)) + { + songId = mediaProperties.Genres + .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.NetEaseCloudMusicTrackID))? + .Replace(ExtendedGenreFiled.NetEaseCloudMusicTrackID, ""); + } + else if (sessionId == PlayerId.QQMusic) + { + songId = mediaProperties.Genres + .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.QQMusicTrackID))? + .Replace(ExtendedGenreFiled.QQMusicTrackID, ""); + } - if (PlayerIdHelper.IsLXMusic(sessionId)) - { - StopSSE(); - } + var linkedFileName = mediaProperties.Genres + .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.FileName))? + .Replace(ExtendedGenreFiled.FileName, ""); - _SMTCAlbumArtBuffer = null; + CurrentSongInfo.Title = mediaProperties.Title; + CurrentSongInfo.Artists = fixedArtist.SplitByCommonSplitter(); + CurrentSongInfo.Album = fixedAlbum; + CurrentSongInfo.DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds; + CurrentSongInfo.PlayerId = sessionId; + CurrentSongInfo.SongId = songId; + CurrentSongInfo.LinkedFileName = linkedFileName; + + _scrobbleTimer.Stop(); + IsScrobbled = false; + ScrobbledDuration = TimeSpan.Zero; + UpdateTargetScrobbledDuration(); + _scrobbleTimer.Start(); + + if (PlayerIdHelper.IsLXMusic(sessionId)) + { + StartSSE(); } else { - var currentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo(); - if (currentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true) - { - currentMediaSourceProviderInfo?.PositionOffset = 0; - } + StopSSE(); + } - string? fixedArtist = mediaProperties?.Artist; - string? fixedAlbum = mediaProperties?.AlbumTitle; - string? songId = null; - - if (PlayerIdHelper.IsAppleMusic(sessionId)) - { - fixedArtist = mediaProperties?.Artist.Split(" — ").FirstOrDefault(); - fixedAlbum = mediaProperties?.Artist.Split(" — ").LastOrDefault(); - fixedAlbum = fixedAlbum?.Replace(" - Single", ""); - fixedAlbum = fixedAlbum?.Replace(" - EP", ""); - } - else if (PlayerIdHelper.IsNeteaseFamily(sessionId)) - { - songId = mediaProperties?.Genres - .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.NetEaseCloudMusicTrackID))? - .Replace(ExtendedGenreFiled.NetEaseCloudMusicTrackID, ""); - } - else if (sessionId == PlayerId.QQMusic) - { - songId = mediaProperties?.Genres - .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.QQMusicTrackID))? - .Replace(ExtendedGenreFiled.QQMusicTrackID, ""); - } - - var linkedFileName = mediaProperties?.Genres - .FirstOrDefault(x => x.StartsWith(ExtendedGenreFiled.FileName))? - .Replace(ExtendedGenreFiled.FileName, ""); - - // 写入播放记录 - if (CurrentSongInfo != null && !string.IsNullOrWhiteSpace(CurrentSongInfo.Title) && CurrentSongInfo.Title != "N/A") - { - // 必须捕获一个副本给异步任务,因为 CurrentSongInfo 马上就要变了 - var lastSong = CurrentSongInfo; - - // 当前秒表时间 >= 上一首总时长 / 2 - if (lastSong.DurationMs > 0 && - _scrobbleStopwatch.Elapsed.TotalMilliseconds >= (lastSong.DurationMs / 2)) - { - // 写入本地播放记录 - var playHistoryItem = lastSong.ToPlayHistoryItem(_scrobbleStopwatch.Elapsed.TotalMilliseconds); - if (playHistoryItem != null) - { - // 后台 - _ = Task.Run(() => _playHistoryService.AddLogAsync(playHistoryItem)); - _logger.LogInformation($"[Scrobble] 结算成功: {lastSong.Title}"); - } - // 写入 Last.fm 播放记录 - var isLastFMEnabled = CurrentMediaSourceProviderInfo?.IsLastFMTrackEnabled ?? false; - if (isLastFMEnabled) - { - // 后台 - _ = Task.Run(() => _lastFMService.TrackAsync(lastSong)); - } - } - } - _scrobbleStopwatch.Restart(); - - CurrentSongInfo = new SongInfo - { - Title = mediaProperties?.Title ?? "N/A", - Artists = fixedArtist?.SplitByCommonSplitter() ?? ["N/A"], - Album = fixedAlbum ?? "N/A", - DurationMs = mediaSession?.ControlSession?.GetTimelineProperties().EndTime.TotalMilliseconds ?? 0, - PlayerId = sessionId, - SongId = songId, - LinkedFileName = linkedFileName - }; - - if (PlayerIdHelper.IsLXMusic(sessionId)) - { - StartSSE(); - } - else - { - StopSSE(); - } - - if (PlayerIdHelper.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null) - { - _SMTCAlbumArtBuffer = _lxMusicAlbumArtBytes.AsBuffer(); - } - else if (mediaProperties?.Thumbnail is IRandomAccessStreamReference streamReference) - { - _SMTCAlbumArtBuffer = await ImageHelper.ToBufferAsync(streamReference); - } - else - { - _SMTCAlbumArtBuffer = null; - } + if (PlayerIdHelper.IsLXMusic(sessionId) && _lxMusicAlbumArtBytes != null) + { + _SMTCAlbumArtBuffer = _lxMusicAlbumArtBytes.AsBuffer(); + } + else if (mediaProperties.Thumbnail is IRandomAccessStreamReference streamReference) + { + _SMTCAlbumArtBuffer = await ImageHelper.ToBufferAsync(streamReference); + } + else + { + _SMTCAlbumArtBuffer = null; } _logger.LogInformation("MediaManager_OnAnyMediaPropertyChanged {SongInfo}", CurrentSongInfo); - CurrentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo(); + CurrentMediaSourceProviderInfo = GetCurrentDesiredMediaSourceProviderInfo(); UpdateAlbumArt(); UpdateLyrics(); @@ -410,25 +394,20 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private void MediaManager_OnAnySessionClosed(MediaManager.MediaSession mediaSession) { - if (!_mediaManager.IsStarted) return; if (mediaSession == null) return; - if (_mediaManager.CurrentMediaSessions.Count == 0) - { - SendNullMessages(); - } + OnDesiredSessionChanged(); } - private async void MediaManager_OnAnySessionOpened(MediaManager.MediaSession mediaSession) + private void MediaManager_OnAnySessionOpened(MediaManager.MediaSession mediaSession) { - if (!_mediaManager.IsStarted) return; if (mediaSession == null) return; RecordMediaSourceProviderInfo(mediaSession); - await SendFocusedMessagesAsync(); + OnDesiredSessionChanged(); } - private MediaManager.MediaSession? GetCurrentSession() + private MediaManager.MediaSession? GetCurrentDesiredSession() { var focusedSession = _mediaManager.GetFocusedSession(); if (focusedSession == null) @@ -454,7 +433,6 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private void RecordMediaSourceProviderInfo(MediaManager.MediaSession mediaSession) { - if (!_mediaManager.IsStarted) return; if (mediaSession == null) return; var id = mediaSession?.Id; @@ -472,19 +450,18 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService private void SendNullMessages() { - _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, (() => + _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () => { CurrentSongInfo = SongInfoExtensions.Placeholder; CurrentIsPlaying = false; - - CurrentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo(); - - _scrobbleStopwatch.Reset(); CurrentPosition = TimeSpan.Zero; + UpdateAlbumArt(); + UpdateLyrics(); + + _scrobbleTimer.Stop(); _discordService.Disable(); - UpdateCurrentMediaSourceProviderInfoPositionOffset(); - })); + }); } private void UpdateCurrentMediaSourceProviderInfoPositionOffset() @@ -508,21 +485,39 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService } } + private void UpdateTargetScrobbledDuration() + { + TargetScrobbledDuration = TimeSpan.FromSeconds(CurrentSongInfo.Duration == 0 ? 30 : CurrentSongInfo.Duration / 2); + } + private async Task SendFocusedMessagesAsync() { - GlobalSystemMediaTransportControlsSessionMediaProperties? mediaProps = null; - - var desiredSession = GetCurrentSession(); + if (_currentDesiredSession == null) + { + SendNullMessages(); + return; + } try { - mediaProps = await desiredSession?.ControlSession?.TryGetMediaPropertiesAsync(); - } - catch (Exception) { } + var mediaProps = await _currentDesiredSession.ControlSession?.TryGetMediaPropertiesAsync(); + var timelineProps = _currentDesiredSession.ControlSession?.GetTimelineProperties(); + var playbackInfo = _currentDesiredSession.ControlSession?.GetPlaybackInfo(); - MediaManager_OnAnyTimelinePropertyChanged(desiredSession, desiredSession?.ControlSession?.GetTimelineProperties()); - MediaManager_OnAnyMediaPropertyChanged(desiredSession, mediaProps); - MediaManager_OnAnyPlaybackStateChanged(desiredSession, desiredSession?.ControlSession?.GetPlaybackInfo()); + if (mediaProps == null || timelineProps == null || playbackInfo == null) + { + SendNullMessages(); + return; + } + + MediaManager_OnAnyTimelinePropertyChanged(_currentDesiredSession, timelineProps); + MediaManager_OnAnyMediaPropertyChanged(_currentDesiredSession, mediaProps); + MediaManager_OnAnyPlaybackStateChanged(_currentDesiredSession, playbackInfo); + } + catch (Exception) + { + SendNullMessages(); + } } private void StartSSE() @@ -573,7 +568,7 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService { _dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () => { - if (PlayerIdHelper.IsLXMusic(CurrentSongInfo?.PlayerId)) + if (PlayerIdHelper.IsLXMusic(CurrentSongInfo.PlayerId)) { var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement); if (data.ValueKind == JsonValueKind.Number) @@ -584,11 +579,11 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService } else if (e.Event == "duration") { - CurrentSongInfo?.DurationMs = data.GetDouble() * 1000; + CurrentSongInfo.DurationMs = data.GetDouble() * 1000; UpdateDiscordPresence(); } - if (IsMediaSourceTimelineSyncEnabled(CurrentSongInfo?.PlayerId)) + if (IsMediaSourceTimelineSyncEnabled(CurrentSongInfo.PlayerId)) { CurrentPosition = TimeSpan.FromSeconds(_lxMusicPositionSeconds); } @@ -620,47 +615,27 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService public async Task PlayAsync() { - var desiredSession = GetCurrentSession(); - if (desiredSession != null) - { - await desiredSession.ControlSession?.TryPlayAsync(); - } + await _currentDesiredSession?.ControlSession?.TryPlayAsync(); } public async Task PauseAsync() { - var desiredSession = GetCurrentSession(); - if (desiredSession != null) - { - await desiredSession.ControlSession?.TryPauseAsync(); - } + await _currentDesiredSession?.ControlSession?.TryPauseAsync(); } public async Task PreviousAsync() { - var desiredSession = GetCurrentSession(); - if (desiredSession != null) - { - await desiredSession.ControlSession?.TrySkipPreviousAsync(); - } + await _currentDesiredSession?.ControlSession?.TrySkipPreviousAsync(); } public async Task NextAsync() { - var desiredSession = GetCurrentSession(); - if (desiredSession != null) - { - await desiredSession.ControlSession?.TrySkipNextAsync(); - } + await _currentDesiredSession?.ControlSession?.TrySkipNextAsync(); } public async Task ChangePosition(double seconds) { - var desiredSession = GetCurrentSession(); - if (desiredSession != null) - { - await desiredSession.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks); - } + await _currentDesiredSession?.ControlSession?.TryChangePlaybackPositionAsync(TimeSpan.FromSeconds(seconds).Ticks); } public async Task ChangeLyricsLine(int index) @@ -693,7 +668,7 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService { if (message.PropertyName == nameof(MediaSourceProviderInfo.IsEnabled)) { - MediaManager_OnFocusedSessionChanged(null); + OnDesiredSessionChanged(); } } else if (message.Sender is TranslationSettings) @@ -723,7 +698,7 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService { if (message.PropertyName == nameof(MusicGallerySettings.LyricsWindowStatus.IsOpened)) { - MediaManager_OnFocusedSessionChanged(null); + OnDesiredSessionChanged(); } } else if (message.Sender is MediaFolder) diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/IGSMTCService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/IGSMTCService.cs index 8281059..2604c9b 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/IGSMTCService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/GSMTCService/IGSMTCService.cs @@ -26,6 +26,10 @@ namespace BetterLyrics.WinUI3.Services.GSMTCService MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; } + bool IsScrobbled { get; } + TimeSpan ScrobbledDuration { get; } + TimeSpan TargetScrobbledDuration { get; } + bool CurrentIsPlaying { get; } SongInfo? CurrentSongInfo { get; } TimeSpan CurrentPosition { get; } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlayHistoryService/PlayHistoryService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlayHistoryService/PlayHistoryService.cs index e81ab35..db4618f 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlayHistoryService/PlayHistoryService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlayHistoryService/PlayHistoryService.cs @@ -2,6 +2,7 @@ using BetterLyrics.WinUI3.Models; using BetterLyrics.WinUI3.Models.Db; using BetterLyrics.WinUI3.Models.Stats; +using BetterLyrics.WinUI3.ViewModels; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs index 8161814..264f01a 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/StatsDashboardControlViewModel.cs @@ -194,7 +194,7 @@ namespace BetterLyrics.WinUI3.ViewModels } [RelayCommand] - private void RefreshData() + public void RefreshData() { if (IsCustomRangeSelected) {