chores: improve GSMTC service

This commit is contained in:
Zhe Fang
2026-01-03 22:02:08 -05:00
parent 6fea88a6a1
commit b3059dbeb1
7 changed files with 235 additions and 252 deletions

View File

@@ -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",

View File

@@ -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();

View File

@@ -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()

View File

@@ -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<GSMTCService> 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)

View File

@@ -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; }

View File

@@ -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;

View File

@@ -194,7 +194,7 @@ namespace BetterLyrics.WinUI3.ViewModels
}
[RelayCommand]
private void RefreshData()
public void RefreshData()
{
if (IsCustomRangeSelected)
{