mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 10:54:55 +08:00
chores: Improve
This commit is contained in:
@@ -69,6 +69,8 @@
|
||||
<converter:TrackToLyricsConverter x:Key="TrackToLyricsConverter" />
|
||||
<converter:IntToBoolConverter x:Key="IntToBoolConverter" />
|
||||
<converter:IndexToDisplayConverter x:Key="IndexToDisplayConverter" />
|
||||
<converter:IntToDoubleConverter x:Key="IntToDoubleConverter" />
|
||||
<converter:MillisecondsToSecondsConverter x:Key="MillisecondsToSecondsConverter" />
|
||||
|
||||
<converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
|
||||
@@ -90,6 +90,10 @@
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.IsLastFMTrackEnabled, Mode=TwoWay}" />
|
||||
</dev:SettingsCard>
|
||||
|
||||
<dev:SettingsCard Header="Discord Presence">
|
||||
<ToggleSwitch IsOn="{x:Bind ViewModel.SelectedMediaSourceProvider.IsDiscordPresenceEnabled, Mode=TwoWay}" />
|
||||
</dev:SettingsCard>
|
||||
|
||||
<!-- LX music server -->
|
||||
<dev:SettingsCard x:Uid="SettingsPageLXMusicServer" Visibility="{x:Bind ViewModel.SelectedMediaSourceProvider.IsLXMusic, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
|
||||
<Grid ColumnSpacing="6">
|
||||
@@ -240,13 +244,13 @@
|
||||
<TextBlock x:Uid="SettingsPageRealtimeStatus" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<dev:SettingsCard x:Uid="LyricsPageLyricsProviderPrefix">
|
||||
<HyperlinkButton
|
||||
Content="{x:Bind ViewModel.LyricsSearchProvider, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}"
|
||||
Content="{x:Bind ViewModel.MediaSessionsService.LyricsSearchProvider, Mode=OneWay, Converter={StaticResource LyricsSearchProviderToDisplayNameConverter}}"
|
||||
IsEnabled="False"
|
||||
NavigateUri="{x:Bind ViewModel.OriginalLyricsRef, Mode=OneWay}" />
|
||||
</dev:SettingsCard>
|
||||
<dev:SettingsCard x:Uid="LyricsPageTranslationProviderPrefix">
|
||||
<HyperlinkButton
|
||||
Content="{x:Bind ViewModel.TranslationSearchProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}"
|
||||
Content="{x:Bind ViewModel.MediaSessionsService.TranslationSearchProvider, Mode=OneWay, Converter={StaticResource TranslationSearchProviderToDisplayNameConverter}}"
|
||||
IsEnabled="False"
|
||||
NavigateUri="{x:Bind ViewModel.TranslatedLyricsRef, Mode=OneWay}" />
|
||||
</dev:SettingsCard>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class IntToDoubleConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int intValue)
|
||||
{
|
||||
return (double)intValue;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Converter
|
||||
{
|
||||
public class MillisecondsToSecondsConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is int intValue)
|
||||
{
|
||||
return intValue / 1000.0;
|
||||
}
|
||||
else if (value is double doubleValue)
|
||||
{
|
||||
return doubleValue / 1000.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,7 +373,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
var window = GetWindowByWindowType<LyricsWindow>();
|
||||
if (window == null) return;
|
||||
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.AutoShowOrHideWindow && !_mediaSessionsService.IsPlaying)
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.AutoShowOrHideWindow && !_mediaSessionsService.CurrentIsPlaying)
|
||||
{
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
@@ -383,7 +383,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
HideWindow<LyricsWindow>();
|
||||
}
|
||||
else if (_liveStatesService.LiveStates.LyricsWindowStatus.AutoShowOrHideWindow && _mediaSessionsService.IsPlaying)
|
||||
else if (_liveStatesService.LiveStates.LyricsWindowStatus.AutoShowOrHideWindow && _mediaSessionsService.CurrentIsPlaying)
|
||||
{
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
|
||||
@@ -272,7 +272,12 @@ namespace BetterLyrics.WinUI3.Models
|
||||
LyricsAlignmentType = TextAlignmentType.Center,
|
||||
},
|
||||
};
|
||||
status.WindowBounds = status.MonitorBounds;
|
||||
status.WindowBounds = new Rect(
|
||||
status.MonitorBounds.X,
|
||||
status.MonitorBounds.Y - 1,
|
||||
status.MonitorBounds.Width,
|
||||
status.MonitorBounds.Height + 1
|
||||
);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,14 @@ namespace BetterLyrics.WinUI3.Models
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial string Provider { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsLastFMTrackEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsDiscordPresenceEnabled { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsTimelineSyncEnabled { get; set; } = true;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int TimelineSyncThreshold { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Unit: ms
|
||||
/// </summary>
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int PositionOffset { get; set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool ResetPositionOffsetOnSongChanged { get; set; } = false;
|
||||
|
||||
@@ -13,10 +13,7 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public partial string Artist { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int? Duration { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial double? DurationMs { get; set; }
|
||||
public partial double DurationMs { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string? PlayerId { get; set; } = null;
|
||||
@@ -27,6 +24,8 @@ namespace BetterLyrics.WinUI3.Models
|
||||
[ObservableProperty]
|
||||
public partial string? SongId { get; set; } = null;
|
||||
|
||||
public double Duration => DurationMs / 1000;
|
||||
|
||||
public SongInfo() { }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +1,53 @@
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using DiscordRPC;
|
||||
using Microsoft.Windows.Storage;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using static Vanara.PInvoke.Kernel32.REASON_CONTEXT;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.DiscordService
|
||||
{
|
||||
public class DiscordService : IDiscordService
|
||||
{
|
||||
private DiscordRpcClient? _client;
|
||||
private RichPresence _richPresence;
|
||||
|
||||
public DiscordService()
|
||||
{
|
||||
_richPresence = new()
|
||||
{
|
||||
StatusDisplay = StatusDisplayType.Name,
|
||||
Type = ActivityType.Listening,
|
||||
};
|
||||
}
|
||||
|
||||
_client = new DiscordRpcClient(Constants.Discord.AppID);
|
||||
_client.OnReady += Client_OnReady;
|
||||
_client.Initialize();
|
||||
public void Enable()
|
||||
{
|
||||
if (_client == null)
|
||||
{
|
||||
_client = new DiscordRpcClient(Constants.Discord.AppID);
|
||||
_client.Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateRichPresence(SongInfo songInfo)
|
||||
{
|
||||
_richPresence.Details = songInfo.Title;
|
||||
_richPresence.State = songInfo.Artist;
|
||||
_richPresence.Timestamps = Timestamps.FromTimeSpan(songInfo.Duration ?? 0);
|
||||
_richPresence.Assets = new Assets
|
||||
_client?.SetPresence(new RichPresence
|
||||
{
|
||||
};
|
||||
_client?.SetPresence(_richPresence);
|
||||
StatusDisplay = StatusDisplayType.Details,
|
||||
Type = ActivityType.Listening,
|
||||
Buttons = new Button[] { new() { Label = "Get this status", Url = Constants.Link.MicrosoftStoreUrl } },
|
||||
Assets = new Assets
|
||||
{
|
||||
LargeImageKey = "banner",
|
||||
SmallImageKey = "logo"
|
||||
},
|
||||
Details = songInfo.Title,
|
||||
State = songInfo.Artist,
|
||||
Timestamps = Timestamps.FromTimeSpan(songInfo.Duration)
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateRichPresence(TimeSpan current, TimeSpan duration)
|
||||
public void Disable()
|
||||
{
|
||||
//_richPresence.Timestamps = new(DateTime.Now - current, DateTime.Now - current + duration);
|
||||
//_client?.SetPresence(_richPresence);
|
||||
_client?.ClearPresence();
|
||||
_client?.Dispose();
|
||||
_client = null;
|
||||
}
|
||||
|
||||
private void Client_OnReady(object sender, DiscordRPC.Message.ReadyMessage args)
|
||||
{
|
||||
Debug.WriteLine("Connected to discord with user {0}", args.User.Username);
|
||||
Debug.WriteLine("Avatar: {0}", args.User.GetAvatarURL(User.AvatarFormat.WebP));
|
||||
Debug.WriteLine("Decoration: {0}", args.User.GetAvatarDecorationURL());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ namespace BetterLyrics.WinUI3.Services.DiscordService
|
||||
{
|
||||
public interface IDiscordService
|
||||
{
|
||||
void Enable();
|
||||
void Disable();
|
||||
void UpdateRichPresence(SongInfo songInfo);
|
||||
void UpdateRichPresence(TimeSpan current, TimeSpan duration);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,17 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
public interface IMediaSessionsService
|
||||
public interface IMediaSessionsService : INotifyPropertyChanged
|
||||
{
|
||||
event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
||||
event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
||||
event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
||||
event EventHandler<AlbumArtChangedEventArgs>? AlbumArtChanged;
|
||||
event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||
event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
||||
|
||||
Task PlayAsync();
|
||||
Task PauseAsync();
|
||||
@@ -23,16 +21,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
Task NextAsync();
|
||||
Task ChangePosition(double seconds);
|
||||
|
||||
MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo();
|
||||
|
||||
void UpdateLyrics();
|
||||
void UpdateTranslations();
|
||||
|
||||
void InitPlaybackShortcuts();
|
||||
|
||||
bool IsPlaying { get; }
|
||||
SongInfo? SongInfo { get; }
|
||||
TimeSpan Position { get; }
|
||||
MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; }
|
||||
bool CurrentIsPlaying { get; }
|
||||
SongInfo? CurrentSongInfo { get; }
|
||||
TimeSpan CurrentPosition { get; }
|
||||
LyricsData? CurrentLyricsData { get; }
|
||||
|
||||
LyricsSearchProvider? LyricsSearchProvider { get; }
|
||||
|
||||
@@ -23,17 +23,17 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private async Task RefreshArtAlbum(CancellationToken token)
|
||||
{
|
||||
if (_cachedSongInfo == null)
|
||||
if (CurrentSongInfo == null)
|
||||
{
|
||||
_logger.LogWarning("Cached song info is null, cannot update album art.");
|
||||
return;
|
||||
}
|
||||
|
||||
IBuffer? buffer = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
|
||||
SongInfo?.PlayerId ?? "",
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo.Album,
|
||||
CurrentSongInfo?.PlayerId ?? "",
|
||||
CurrentSongInfo.Title,
|
||||
CurrentSongInfo.Artist,
|
||||
CurrentSongInfo.Album,
|
||||
_SMTCAlbumArtBuffer,
|
||||
token
|
||||
), token);
|
||||
|
||||
@@ -26,9 +26,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
public event EventHandler<LyricsChangedEventArgs>? LyricsChanged;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial LyricsSearchProvider? LyricsSearchProvider { get; private set; }
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSearchProvider? TranslationSearchProvider { get; set; }
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial TranslationSearchProvider? TranslationSearchProvider { get; private set; }
|
||||
|
||||
[ObservableProperty] public partial bool IsTranslating { get; set; } = false;
|
||||
|
||||
@@ -155,18 +155,18 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
LyricsChanged?.Invoke(this, new LyricsChangedEventArgs(CurrentLyricsData));
|
||||
});
|
||||
|
||||
if (SongInfo != null)
|
||||
if (CurrentSongInfo != null)
|
||||
{
|
||||
_logger.LogInformation("Searching lyrics for: Title={Title}, Artist={Artist}, Album={Album}, DurationMs={DurationMs}",
|
||||
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
|
||||
CurrentSongInfo.Title, CurrentSongInfo.Artist, CurrentSongInfo.Album, CurrentSongInfo.DurationMs);
|
||||
|
||||
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
|
||||
SongInfo.PlayerId ?? "",
|
||||
SongInfo.Title,
|
||||
SongInfo.Artist,
|
||||
SongInfo.Album,
|
||||
SongInfo.DurationMs ?? 0,
|
||||
SongInfo.SongId,
|
||||
CurrentSongInfo.PlayerId ?? "",
|
||||
CurrentSongInfo.Title,
|
||||
CurrentSongInfo.Artist,
|
||||
CurrentSongInfo.Album,
|
||||
CurrentSongInfo.DurationMs,
|
||||
CurrentSongInfo.SongId,
|
||||
token
|
||||
), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
@@ -177,7 +177,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
var lyricsParser = new LyricsParser();
|
||||
lyricsParser.Parse(
|
||||
_settingsService.AppSettings.MappedSongSearchQueries.ToList(),
|
||||
SongInfo.Title, SongInfo.Artist, SongInfo.Album, lyricsSearchResult?.Raw, (int?)SongInfo?.DurationMs, LyricsSearchProvider);
|
||||
CurrentSongInfo.Title, CurrentSongInfo.Artist, CurrentSongInfo.Album, lyricsSearchResult?.Raw, (int?)CurrentSongInfo?.DurationMs, LyricsSearchProvider);
|
||||
_lyricsDataArr = lyricsParser.LyricsDataArr;
|
||||
ApplyChinesePreference();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using BetterLyrics.WinUI3.Services.TranslateService;
|
||||
using BetterLyrics.WinUI3.ViewModels;
|
||||
using BetterLyrics.WinUI3.Views;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.DependencyInjection;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
@@ -42,6 +43,10 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
IRecipient<PropertyChangedMessage<ChineseRomanization>>,
|
||||
IRecipient<PropertyChangedMessage<List<string>>>
|
||||
{
|
||||
private EventSourceReader? _sse = null;
|
||||
private readonly MediaManager _mediaManager = new();
|
||||
private IBuffer? _SMTCAlbumArtBuffer = null;
|
||||
|
||||
private readonly IAlbumArtSearchService _albumArtSearchService;
|
||||
private readonly ILyricsSearchService _lyrcsSearchService;
|
||||
private readonly ITranslateService _translateService;
|
||||
@@ -53,27 +58,13 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
private readonly ILogger<MediaSessionsService> _logger;
|
||||
|
||||
private double _lxMusicPositionSeconds = 0;
|
||||
private double _lxMusicDurationSeconds = 0;
|
||||
private byte[]? _lxMusicAlbumArtBytes = null;
|
||||
|
||||
private bool _cachedIsPlaying = false;
|
||||
private TimeSpan _cachedPosition = 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; }
|
||||
|
||||
private EventSourceReader? _sse = null;
|
||||
|
||||
private readonly MediaManager _mediaManager = new();
|
||||
|
||||
private SongInfo? _cachedSongInfo;
|
||||
private IBuffer? _SMTCAlbumArtBuffer = null;
|
||||
|
||||
public event EventHandler<IsPlayingChangedEventArgs>? IsPlayingChanged;
|
||||
public event EventHandler<TimelineChangedEventArgs>? TimelineChanged;
|
||||
public event EventHandler<SongInfoChangedEventArgs>? SongInfoChanged;
|
||||
public event EventHandler<MediaSourceProvidersInfoEventArgs>? MediaSourceProvidersInfoChanged;
|
||||
|
||||
public bool IsPlaying => _cachedIsPlaying;
|
||||
public SongInfo? SongInfo => _cachedSongInfo;
|
||||
public TimeSpan Position => _cachedPosition;
|
||||
public MediaSourceProviderInfo? CurrentMediaSourceProviderInfo { get; set; }
|
||||
|
||||
public MediaSessionsService(
|
||||
ISettingsService settingsService,
|
||||
@@ -128,9 +119,9 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void UpdatePlayOrPauseSongShortcut()
|
||||
{
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, () =>
|
||||
GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.PlayOrPauseSong, _settingsService.AppSettings.GeneralSettings.PlayOrPauseShortcut, (() =>
|
||||
{
|
||||
if (_cachedIsPlaying)
|
||||
if (CurrentIsPlaying)
|
||||
{
|
||||
_ = PauseAsync();
|
||||
}
|
||||
@@ -138,7 +129,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_ = PlayAsync();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private void UpdatePreviousSongShortcut()
|
||||
@@ -190,7 +181,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
UpdateLyrics();
|
||||
}
|
||||
|
||||
public MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
|
||||
private MediaSourceProviderInfo? GetCurrentMediaSourceProviderInfo()
|
||||
{
|
||||
var desiredSession = GetCurrentSession();
|
||||
return _settingsService.AppSettings.MediaSourceProvidersInfo.FirstOrDefault(x => x.Provider == desiredSession?.Id);
|
||||
@@ -239,30 +230,20 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||
{
|
||||
_cachedPosition = TimeSpan.Zero;
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, TimeSpan.Zero));
|
||||
_discordService.UpdateRichPresence(_cachedPosition, TimeSpan.Zero);
|
||||
});
|
||||
CurrentPosition = TimeSpan.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsMediaSourceTimelineSyncEnabled(mediaSession.Id))
|
||||
{
|
||||
_cachedPosition = timelineProperties?.Position ?? TimeSpan.Zero;
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(_cachedPosition, timelineProperties?.EndTime ?? TimeSpan.Zero));
|
||||
_discordService.UpdateRichPresence(_cachedPosition, timelineProperties?.EndTime ?? TimeSpan.Zero);
|
||||
});
|
||||
CurrentPosition = timelineProperties?.Position ?? TimeSpan.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MediaManager_OnAnyPlaybackStateChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionPlaybackInfo? playbackInfo)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, (() =>
|
||||
{
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null) return;
|
||||
@@ -274,19 +255,17 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
if (!IsMediaSourceEnabled(mediaSession.Id))
|
||||
{
|
||||
_cachedIsPlaying = false;
|
||||
CurrentIsPlaying = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cachedIsPlaying = playbackInfo?.PlaybackStatus switch
|
||||
CurrentIsPlaying = playbackInfo?.PlaybackStatus switch
|
||||
{
|
||||
GlobalSystemMediaTransportControlsSessionPlaybackStatus.Playing => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
IsPlayingChanged?.Invoke(this, new IsPlayingChangedEventArgs(_cachedIsPlaying));
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private void MediaManager_OnAnyMediaPropertyChanged(MediaManager.MediaSession? mediaSession, GlobalSystemMediaTransportControlsSessionMediaProperties? mediaProperties)
|
||||
@@ -296,7 +275,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null)
|
||||
{
|
||||
_cachedSongInfo = SongInfoExtensions.Placeholder;
|
||||
CurrentSongInfo = SongInfoExtensions.Placeholder;
|
||||
}
|
||||
|
||||
string? sessionId = mediaSession?.Id;
|
||||
@@ -307,7 +286,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
if (sessionId != null && !IsMediaSourceEnabled(sessionId))
|
||||
{
|
||||
_cachedSongInfo = SongInfoExtensions.Placeholder;
|
||||
CurrentSongInfo = SongInfoExtensions.Placeholder;
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties?.Title, mediaProperties?.Artist, mediaProperties?.AlbumTitle);
|
||||
@@ -341,16 +320,15 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
songId = mediaProperties?.Genres.FirstOrDefault()?.Replace("NCM-", "");
|
||||
}
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
CurrentSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties?.Title ?? "N/A",
|
||||
Artist = fixedArtist,
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession?.ControlSession?.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
DurationMs = mediaSession?.ControlSession?.GetTimelineProperties().EndTime.TotalMilliseconds ?? 0,
|
||||
PlayerId = sessionId,
|
||||
SongId = songId
|
||||
};
|
||||
_cachedSongInfo.Duration = (int)((_cachedSongInfo.DurationMs ?? 0) / 1000f);
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties?.Title, mediaProperties?.Artist, mediaProperties?.AlbumTitle);
|
||||
@@ -378,11 +356,13 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
}
|
||||
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
||||
CurrentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo();
|
||||
|
||||
UpdateAlbumArt();
|
||||
UpdateLyrics();
|
||||
|
||||
_discordService.UpdateRichPresence(_cachedSongInfo);
|
||||
UpdateDiscordPresence();
|
||||
UpdateCurrentMediaSourceProviderInfoPositionOffset();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -450,18 +430,39 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
|
||||
private void SendNullMessages()
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, (() =>
|
||||
{
|
||||
_cachedSongInfo = SongInfoExtensions.Placeholder;
|
||||
_cachedIsPlaying = false;
|
||||
CurrentSongInfo = SongInfoExtensions.Placeholder;
|
||||
CurrentIsPlaying = false;
|
||||
|
||||
SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(_cachedSongInfo));
|
||||
IsPlayingChanged?.Invoke(this, new IsPlayingChangedEventArgs(_cachedIsPlaying));
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.Zero, TimeSpan.Zero));
|
||||
CurrentMediaSourceProviderInfo = GetCurrentMediaSourceProviderInfo();
|
||||
|
||||
_discordService.UpdateRichPresence(_cachedSongInfo);
|
||||
_discordService.UpdateRichPresence(TimeSpan.Zero, TimeSpan.Zero);
|
||||
});
|
||||
CurrentPosition = TimeSpan.Zero;
|
||||
|
||||
_discordService.Disable();
|
||||
UpdateCurrentMediaSourceProviderInfoPositionOffset();
|
||||
}));
|
||||
}
|
||||
|
||||
private void UpdateCurrentMediaSourceProviderInfoPositionOffset()
|
||||
{
|
||||
if (CurrentPosition.TotalSeconds <= 1 && CurrentMediaSourceProviderInfo?.ResetPositionOffsetOnSongChanged == true)
|
||||
{
|
||||
CurrentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDiscordPresence()
|
||||
{
|
||||
if (CurrentMediaSourceProviderInfo?.IsDiscordPresenceEnabled == true && CurrentSongInfo != null)
|
||||
{
|
||||
_discordService.Enable();
|
||||
_discordService.UpdateRichPresence(CurrentSongInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
_discordService.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SendFocusedMessagesAsync()
|
||||
@@ -531,7 +532,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||
{
|
||||
if (PlayerIdMatcher.IsLXMusic(_cachedSongInfo?.PlayerId))
|
||||
if (PlayerIdMatcher.IsLXMusic(CurrentSongInfo?.PlayerId))
|
||||
{
|
||||
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
if (data.ValueKind == JsonValueKind.Number)
|
||||
@@ -542,13 +543,13 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
else if (e.Event == "duration")
|
||||
{
|
||||
_lxMusicDurationSeconds = data.GetDouble();
|
||||
CurrentSongInfo?.DurationMs = data.GetDouble() * 1000;
|
||||
UpdateDiscordPresence();
|
||||
}
|
||||
|
||||
if (IsMediaSourceTimelineSyncEnabled(_cachedSongInfo?.PlayerId))
|
||||
if (IsMediaSourceTimelineSyncEnabled(CurrentSongInfo?.PlayerId))
|
||||
{
|
||||
TimelineChanged?.Invoke(this, new TimelineChangedEventArgs(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds)));
|
||||
_discordService.UpdateRichPresence(TimeSpan.FromSeconds(_lxMusicPositionSeconds), TimeSpan.FromSeconds(_lxMusicDurationSeconds));
|
||||
CurrentPosition = TimeSpan.FromSeconds(_lxMusicPositionSeconds);
|
||||
}
|
||||
}
|
||||
else if (data.ValueKind == JsonValueKind.String)
|
||||
|
||||
@@ -19,28 +19,20 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
public partial class LyricsPageViewModel : BaseViewModel,
|
||||
IRecipient<PropertyChangedMessage<TimeSpan>>
|
||||
{
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
public IMediaSessionsService MediaSessionsService { get; private set; }
|
||||
private readonly ILiveStatesService _liveStatesService;
|
||||
|
||||
private readonly ThrottleHelper _timelineThrottle = new(TimeSpan.FromSeconds(1));
|
||||
|
||||
public LyricsPageViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
|
||||
public LyricsPageViewModel(IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_liveStatesService = liveStatesService;
|
||||
MediaSessionsService = mediaSessionsService;
|
||||
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
|
||||
Volume = SystemVolumeHelper.MasterVolume;
|
||||
SystemVolumeHelper.VolumeNotification += SystemVolumeHelper_VolumeNotification;
|
||||
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
_mediaSessionsService.SongInfoChanged += PlaybackService_SongInfoChanged;
|
||||
_mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
|
||||
_mediaSessionsService.TimelineChanged += PlaybackService_TimelineChanged;
|
||||
|
||||
IsSongPlaying = _mediaSessionsService.IsPlaying;
|
||||
}
|
||||
|
||||
private void SystemVolumeHelper_VolumeNotification(object? sender, int e)
|
||||
@@ -48,31 +40,12 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
Volume = e;
|
||||
}
|
||||
|
||||
private void PlaybackService_TimelineChanged(object? sender, Events.TimelineChangedEventArgs e)
|
||||
{
|
||||
SongDurationSeconds = (int)e.End.TotalSeconds;
|
||||
}
|
||||
|
||||
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
|
||||
{
|
||||
IsSongPlaying = e.IsPlaying;
|
||||
}
|
||||
|
||||
private void PlaybackService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
SongInfo = e.SongInfo;
|
||||
SongDurationSeconds = SongInfo?.Duration ?? 0;
|
||||
}
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LiveStates LiveStates { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial double TimelinePositionSeconds { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int SongDurationSeconds { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial int Volume { get; set; }
|
||||
|
||||
@@ -82,12 +55,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial double BottomCommandFlyoutTriggerOpacity { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial SongInfo? SongInfo { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsSongPlaying { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial float TimelineSliderThumbOpacity { get; set; } = 0f;
|
||||
|
||||
@@ -107,30 +74,30 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[RelayCommand]
|
||||
private async Task PlaySongAsync()
|
||||
{
|
||||
await _mediaSessionsService.PlayAsync();
|
||||
await MediaSessionsService.PlayAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task PauseSongAsync()
|
||||
{
|
||||
await _mediaSessionsService.PauseAsync();
|
||||
await MediaSessionsService.PauseAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task PreviousSongAsync()
|
||||
{
|
||||
await _mediaSessionsService.PreviousAsync();
|
||||
await MediaSessionsService.PreviousAsync();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task NextSongAsync()
|
||||
{
|
||||
await _mediaSessionsService.NextAsync();
|
||||
await MediaSessionsService.NextAsync();
|
||||
}
|
||||
|
||||
partial void OnTimelineSliderThumbSecondsChanged(double value)
|
||||
{
|
||||
TimelineSliderThumbLyricsLine = _mediaSessionsService.CurrentLyricsData?.GetLyricsLine(value);
|
||||
TimelineSliderThumbLyricsLine = MediaSessionsService.CurrentLyricsData?.GetLyricsLine(value);
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<TimeSpan> message)
|
||||
@@ -149,5 +116,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,8 +93,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
$"Syllable prog: {charProgress}\n" +
|
||||
$"Visible lines: [{_startVisibleLineIndex}, {_endVisibleLineIndex}]\n" +
|
||||
$"Total line count: {GetMaxLyricsLineIndexBoundaries().Item2 + 1}\n" +
|
||||
$"Cur time: {TotalTime + _positionOffset}\n" +
|
||||
$"Song duration: {TimeSpan.FromMilliseconds(SongInfo?.DurationMs ?? 0)}\n" +
|
||||
$"Cur time: {TotalTime + TimeSpan.FromMilliseconds(_mediaSessionsService.CurrentMediaSourceProviderInfo?.PositionOffset ?? 0)}\n" +
|
||||
$"Song duration: {TimeSpan.FromMilliseconds(_mediaSessionsService.CurrentSongInfo?.DurationMs ?? 0)}\n" +
|
||||
$"Y offset: {_canvasYScrollTransition.Value}",
|
||||
new Vector2(10, 40),
|
||||
ThemeTypeSent == Microsoft.UI.Xaml.ElementTheme.Light ? Colors.Black : Colors.White,
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using Windows.UI;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
@@ -22,9 +24,11 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
IRecipient<PropertyChangedMessage<LineRenderingType>>,
|
||||
IRecipient<PropertyChangedMessage<ElementTheme>>,
|
||||
IRecipient<PropertyChangedMessage<EasingType>>,
|
||||
IRecipient<PropertyChangedMessage<TimeSpan>>,
|
||||
IRecipient<PropertyChangedMessage<AlbumArtLayoutSettings>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsBackgroundSettings>>,
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowStatus>>
|
||||
IRecipient<PropertyChangedMessage<LyricsWindowStatus>>,
|
||||
IRecipient<PropertyChangedMessage<SongInfo?>>
|
||||
{
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
@@ -54,13 +58,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_isLyrics3DMatrixChanged = true;
|
||||
}
|
||||
}
|
||||
else if (message.Sender is MediaSourceProviderInfo)
|
||||
{
|
||||
if (message.PropertyName == nameof(MediaSourceProviderInfo.IsLastFMTrackEnabled))
|
||||
{
|
||||
UpdateIsLastFMTrackEnabled();
|
||||
}
|
||||
}
|
||||
else if (message.Sender is LyricsStyleSettings)
|
||||
{
|
||||
if (message.PropertyName == nameof(LyricsStyleSettings.IsDynamicLyricsFontSize))
|
||||
@@ -256,17 +253,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
else if (message.Sender is MediaSourceProviderInfo)
|
||||
{
|
||||
if (message.PropertyName == nameof(MediaSourceProviderInfo.TimelineSyncThreshold))
|
||||
{
|
||||
UpdateTimelineSyncThreshold();
|
||||
}
|
||||
else if (message.PropertyName == nameof(MediaSourceProviderInfo.PositionOffset))
|
||||
{
|
||||
UpdatePositionOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LineRenderingType> message)
|
||||
@@ -436,5 +422,60 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<SongInfo?> message)
|
||||
{
|
||||
if (_mediaSessionsService.CurrentSongInfo?.Title != _songTitle || _mediaSessionsService.CurrentSongInfo?.Artist != _songArtist)
|
||||
{
|
||||
_lastSongTitle = _songTitle;
|
||||
_songTitle = _mediaSessionsService.CurrentSongInfo?.Title;
|
||||
_isSongTitleChanged = true;
|
||||
|
||||
_lastSongArtist = _songArtist;
|
||||
_songArtist = _mediaSessionsService.CurrentSongInfo?.Artist;
|
||||
_isSongArtistChanged = true;
|
||||
|
||||
_lastSongAlbum = _songAlbum;
|
||||
_songAlbum = _mediaSessionsService.CurrentSongInfo?.Album;
|
||||
_isSongAlbumChanged = true;
|
||||
|
||||
_songDurationMs = (int)(_mediaSessionsService.CurrentSongInfo?.DurationMs ?? TimeSpan.FromMinutes(99).TotalMilliseconds);
|
||||
|
||||
_songInfoOpacityTransition.Reset(0f);
|
||||
_songInfoOpacityTransition.StartTransition(1f);
|
||||
|
||||
TotalTime = TimeSpan.Zero;
|
||||
|
||||
// 处理 Last.fm 追踪
|
||||
_totalPlayingTime = TimeSpan.Zero;
|
||||
_isLastFMTracked = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<TimeSpan> message)
|
||||
{
|
||||
if (message.Sender is IMediaSessionsService)
|
||||
{
|
||||
if (message.PropertyName == nameof(IMediaSessionsService.CurrentPosition))
|
||||
{
|
||||
var diff = Math.Abs(TotalTime.TotalMilliseconds - _mediaSessionsService.CurrentPosition.TotalMilliseconds);
|
||||
var timelineSyncThreshold = _mediaSessionsService.CurrentMediaSourceProviderInfo?.TimelineSyncThreshold ?? 0;
|
||||
if (diff >= timelineSyncThreshold)
|
||||
{
|
||||
TotalTime = _mediaSessionsService.CurrentPosition;
|
||||
if (TotalTime.TotalSeconds <= 1)
|
||||
{
|
||||
_totalPlayingTime = TimeSpan.Zero;
|
||||
_isLastFMTracked = false;
|
||||
}
|
||||
}
|
||||
// 大跨度,刷新布局,避免歌词不显示
|
||||
if (diff >= timelineSyncThreshold + 5000)
|
||||
{
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +77,17 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
_elapsedTime = args.Timing.ElapsedTime;
|
||||
|
||||
if (IsPlaying)
|
||||
if (_mediaSessionsService.CurrentIsPlaying)
|
||||
{
|
||||
TotalTime += _elapsedTime;
|
||||
_totalPlayingTime += _elapsedTime;
|
||||
if (_isLastFMTrackEnabled && !_isLastFMTracked && SongInfo?.Duration != null && SongInfo.Duration > 0 && _totalPlayingTime.TotalSeconds >= SongInfo.Duration * 0.5)
|
||||
if ((_mediaSessionsService.CurrentMediaSourceProviderInfo?.IsLastFMTrackEnabled ?? false) &&
|
||||
_isLastFMTracked == false &&
|
||||
_mediaSessionsService.CurrentSongInfo?.Duration > 0 &&
|
||||
_totalPlayingTime.TotalSeconds >= _mediaSessionsService.CurrentSongInfo.Duration * 0.5)
|
||||
{
|
||||
_isLastFMTracked = true;
|
||||
_lastFMService.TrackAsync(SongInfo);
|
||||
_lastFMService.TrackAsync(_mediaSessionsService.CurrentSongInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,24 +862,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTimelineSyncThreshold()
|
||||
{
|
||||
var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
|
||||
_timelineSyncThreshold = current?.TimelineSyncThreshold ?? 0;
|
||||
}
|
||||
|
||||
private void UpdatePositionOffset()
|
||||
{
|
||||
var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
|
||||
_positionOffset = TimeSpan.FromMilliseconds(current?.PositionOffset ?? 0);
|
||||
}
|
||||
|
||||
private void UpdateIsLastFMTrackEnabled()
|
||||
{
|
||||
var current = _mediaSessionsService.GetCurrentMediaSourceProviderInfo();
|
||||
_isLastFMTrackEnabled = current?.IsLastFMTrackEnabled ?? false;
|
||||
}
|
||||
|
||||
private void UpdateSongInfoFontSize()
|
||||
{
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.AlbumArtLayoutSettings.IsAutoSongInfoFontSize)
|
||||
|
||||
@@ -57,8 +57,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial TimeSpan TotalTime { get; set; } = TimeSpan.Zero;
|
||||
|
||||
private TimeSpan _positionOffset = TimeSpan.Zero;
|
||||
|
||||
private int _songDurationMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds;
|
||||
|
||||
private Stopwatch? _drawFrameStopwatch;
|
||||
@@ -139,11 +137,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private bool _isDebugOverlayEnabled = false;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsPlaying { get; set; } = false;
|
||||
|
||||
private int _timelineSyncThreshold = 0;
|
||||
|
||||
private int _phoneticLyricsFontSize = 18;
|
||||
private int _originalLyricsFontSize = 36;
|
||||
private int _translatedLyricsFontSize = 18;
|
||||
@@ -185,9 +178,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private CanvasGeometry? _spectrumGeometry = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial SongInfo? SongInfo { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedRecipients]
|
||||
public partial ElementTheme ThemeTypeSent { get; set; }
|
||||
@@ -213,15 +203,8 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
UpdateSongInfoFontSize();
|
||||
|
||||
_timelineSyncThreshold = 0;
|
||||
|
||||
_mediaSessionsService.IsPlayingChanged += MediaSessionsService_IsPlayingChanged;
|
||||
_mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
|
||||
_mediaSessionsService.AlbumArtChanged += MediaSessionsService_AlbumArtChangedChanged;
|
||||
_mediaSessionsService.LyricsChanged += MediaSessionsService_LyricsChanged;
|
||||
_mediaSessionsService.TimelineChanged += MediaSessionsService_TimelineChanged;
|
||||
|
||||
IsPlaying = _mediaSessionsService.IsPlaying;
|
||||
|
||||
UpdateColorConfig();
|
||||
|
||||
@@ -236,7 +219,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private int GetCurrentPlayingLineIndex()
|
||||
{
|
||||
var totalMs = TotalTime.TotalMilliseconds + _positionOffset.TotalMilliseconds;
|
||||
var totalMs = TotalTime.TotalMilliseconds + _mediaSessionsService.CurrentMediaSourceProviderInfo?.PositionOffset ?? 0;
|
||||
if (totalMs < _currentLyricsData?.LyricsLines.FirstOrDefault()?.StartMs) return 0;
|
||||
|
||||
for (int i = 0; i < _currentLyricsData?.LyricsLines.Count; i++)
|
||||
@@ -272,7 +255,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
else if (nextLine != null) lineEndMs = nextLine.StartMs;
|
||||
else lineEndMs = _songDurationMs;
|
||||
|
||||
double now = (double)TotalTime.TotalMilliseconds + (double)_positionOffset.TotalMilliseconds;
|
||||
double now = (double)TotalTime.TotalMilliseconds + (double)(_mediaSessionsService.CurrentMediaSourceProviderInfo?.PositionOffset ?? 0);
|
||||
|
||||
// 1. 还没到本句
|
||||
if (now < line.StartMs)
|
||||
@@ -356,11 +339,9 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
private Tuple<int, int> GetMaxLyricsLineIndexBoundaries()
|
||||
{
|
||||
if (
|
||||
SongInfo == null
|
||||
if (_mediaSessionsService.CurrentSongInfo == null
|
||||
|| _currentLyricsData == null
|
||||
|| _currentLyricsData.LyricsLines.Count == 0
|
||||
)
|
||||
|| _currentLyricsData.LyricsLines.Count == 0)
|
||||
{
|
||||
return new Tuple<int, int>(-1, -1);
|
||||
}
|
||||
@@ -368,65 +349,6 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
return new Tuple<int, int>(0, _currentLyricsData.LyricsLines.Count - 1);
|
||||
}
|
||||
|
||||
private void MediaSessionsService_IsPlayingChanged(object? sender, IsPlayingChangedEventArgs e)
|
||||
{
|
||||
IsPlaying = e.IsPlaying;
|
||||
}
|
||||
|
||||
private void MediaSessionsService_TimelineChanged(object? sender, TimelineChangedEventArgs e)
|
||||
{
|
||||
var diff = Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds);
|
||||
if (diff >= _timelineSyncThreshold)
|
||||
{
|
||||
TotalTime = e.Position;
|
||||
if (TotalTime.TotalSeconds <= 1)
|
||||
{
|
||||
_totalPlayingTime = TimeSpan.Zero;
|
||||
_isLastFMTracked = false;
|
||||
}
|
||||
}
|
||||
// 大跨度,刷新布局,避免歌词不显示
|
||||
if (diff >= _timelineSyncThreshold + 5000)
|
||||
{
|
||||
_isLayoutChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, SongInfoChangedEventArgs e)
|
||||
{
|
||||
SongInfo = e.SongInfo;
|
||||
|
||||
UpdateTimelineSyncThreshold();
|
||||
UpdatePositionOffset();
|
||||
UpdateIsLastFMTrackEnabled();
|
||||
|
||||
if (SongInfo?.Title != _songTitle || SongInfo?.Artist != _songArtist)
|
||||
{
|
||||
_lastSongTitle = _songTitle;
|
||||
_songTitle = SongInfo?.Title;
|
||||
_isSongTitleChanged = true;
|
||||
|
||||
_lastSongArtist = _songArtist;
|
||||
_songArtist = SongInfo?.Artist;
|
||||
_isSongArtistChanged = true;
|
||||
|
||||
_lastSongAlbum = _songAlbum;
|
||||
_songAlbum = SongInfo?.Album;
|
||||
_isSongAlbumChanged = true;
|
||||
|
||||
_songDurationMs = (int)(SongInfo?.DurationMs ?? TimeSpan.FromMinutes(99).TotalMilliseconds);
|
||||
|
||||
_songInfoOpacityTransition.Reset(0f);
|
||||
_songInfoOpacityTransition.StartTransition(1f);
|
||||
|
||||
TotalTime = TimeSpan.Zero;
|
||||
|
||||
// 处理 Last.fm 追踪
|
||||
_totalPlayingTime = TimeSpan.Zero;
|
||||
_isLastFMTracked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void MediaSessionsService_AlbumArtChangedChanged(object? sender, AlbumArtChangedEventArgs e)
|
||||
{
|
||||
_lastAlbumArtCanvasBitmap?.Dispose();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Enums;
|
||||
using BetterLyrics.WinUI3.Helper;
|
||||
using BetterLyrics.WinUI3.Models;
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||||
@@ -6,13 +7,16 @@ using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class LyricsSearchControlViewModel : BaseViewModel
|
||||
public partial class LyricsSearchControlViewModel : BaseViewModel,
|
||||
IRecipient<PropertyChangedMessage<SongInfo?>>
|
||||
{
|
||||
private readonly ILyricsSearchService _lyricsSearchService;
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
@@ -49,13 +53,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
|
||||
_mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
|
||||
|
||||
InitMappedSongSearchQuery();
|
||||
}
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
InitMappedSongSearchQuery();
|
||||
}
|
||||
|
||||
@@ -63,19 +60,19 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
LyricsSearchResults.Clear();
|
||||
LyricsDataArr = null;
|
||||
if (_mediaSessionsService.SongInfo != null)
|
||||
if (_mediaSessionsService.CurrentSongInfo != null)
|
||||
{
|
||||
var found = GetMappedSongSearchQueryFromSettings();
|
||||
if (found == null)
|
||||
{
|
||||
MappedSongSearchQuery = new MappedSongSearchQuery
|
||||
{
|
||||
OriginalTitle = _mediaSessionsService.SongInfo.Title,
|
||||
OriginalArtist = _mediaSessionsService.SongInfo.Artist,
|
||||
OriginalAlbum = _mediaSessionsService.SongInfo.Album,
|
||||
MappedTitle = _mediaSessionsService.SongInfo.Title,
|
||||
MappedArtist = _mediaSessionsService.SongInfo.Artist,
|
||||
MappedAlbum = _mediaSessionsService.SongInfo.Album,
|
||||
OriginalTitle = _mediaSessionsService.CurrentSongInfo.Title,
|
||||
OriginalArtist = _mediaSessionsService.CurrentSongInfo.Artist,
|
||||
OriginalAlbum = _mediaSessionsService.CurrentSongInfo.Album,
|
||||
MappedTitle = _mediaSessionsService.CurrentSongInfo.Title,
|
||||
MappedArtist = _mediaSessionsService.CurrentSongInfo.Artist,
|
||||
MappedAlbum = _mediaSessionsService.CurrentSongInfo.Album,
|
||||
};
|
||||
}
|
||||
else
|
||||
@@ -87,13 +84,13 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private MappedSongSearchQuery? GetMappedSongSearchQueryFromSettings()
|
||||
{
|
||||
if (_mediaSessionsService.SongInfo == null)
|
||||
if (_mediaSessionsService.CurrentSongInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var found = AppSettings.MappedSongSearchQueries
|
||||
.Where(x => x.OriginalTitle == _mediaSessionsService.SongInfo.Title && x.OriginalArtist == _mediaSessionsService.SongInfo.Artist && x.OriginalAlbum == _mediaSessionsService.SongInfo.Album);
|
||||
.Where(x => x.OriginalTitle == _mediaSessionsService.CurrentSongInfo.Title && x.OriginalArtist == _mediaSessionsService.CurrentSongInfo.Artist && x.OriginalAlbum == _mediaSessionsService.CurrentSongInfo.Album);
|
||||
|
||||
return found.FirstOrDefault();
|
||||
}
|
||||
@@ -117,7 +114,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
MappedSongSearchQuery.MappedTitle,
|
||||
MappedSongSearchQuery.MappedArtist,
|
||||
MappedSongSearchQuery.MappedAlbum,
|
||||
_mediaSessionsService.SongInfo?.DurationMs ?? 0, token);
|
||||
_mediaSessionsService.CurrentSongInfo?.DurationMs ?? 0, token);
|
||||
}, token)];
|
||||
IsSearching = false;
|
||||
});
|
||||
@@ -181,7 +178,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
MappedSongSearchQuery?.OriginalTitle ?? "",
|
||||
MappedSongSearchQuery?.OriginalArtist ?? "",
|
||||
MappedSongSearchQuery?.OriginalAlbum ?? "",
|
||||
value?.Raw, (int?)_mediaSessionsService.SongInfo?.DurationMs, value?.Provider);
|
||||
value?.Raw, (int?)_mediaSessionsService.CurrentSongInfo?.DurationMs, value?.Provider);
|
||||
LyricsDataArr = [.. lyricsParser.LyricsDataArr];
|
||||
}
|
||||
else
|
||||
@@ -198,5 +195,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
}
|
||||
_mediaSessionsService.ChangePosition(value.StartMs / 1000.0);
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<SongInfo?> message)
|
||||
{
|
||||
if (message.Sender is IMediaSessionsService)
|
||||
{
|
||||
if (message.PropertyName == nameof(IMediaSessionsService.CurrentSongInfo))
|
||||
{
|
||||
InitMappedSongSearchQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,31 +26,23 @@ namespace BetterLyrics.WinUI3
|
||||
{
|
||||
public partial class LyricsWindowViewModel
|
||||
: BaseWindowViewModel,
|
||||
IRecipient<PropertyChangedMessage<bool>>,
|
||||
IRecipient<PropertyChangedMessage<List<string>>>,
|
||||
IRecipient<PropertyChangedMessage<ElementTheme>>
|
||||
{
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
private readonly ILiveStatesService _liveStatesService;
|
||||
|
||||
private ForegroundWindowWatcher? _fgWindowWatcher = null;
|
||||
private DispatcherQueueTimer? _fgWindowWatcherTimer = null;
|
||||
|
||||
public LyricsWindowViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
|
||||
public LyricsWindowViewModel(ISettingsService settingsService, ILiveStatesService liveStatesService)
|
||||
{
|
||||
_settingsService = settingsService;
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
_liveStatesService = liveStatesService;
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
|
||||
_mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
|
||||
}
|
||||
|
||||
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
|
||||
{
|
||||
WindowHelper.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
}
|
||||
|
||||
[ObservableProperty] public partial AppSettings AppSettings { get; set; }
|
||||
@@ -226,5 +218,16 @@ namespace BetterLyrics.WinUI3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<bool> message)
|
||||
{
|
||||
if (message.Sender is IMediaSessionsService)
|
||||
{
|
||||
if (message.PropertyName == nameof(IMediaSessionsService.CurrentIsPlaying))
|
||||
{
|
||||
WindowHelper.SetLyricsWindowVisibilityByPlayingStatus(_dispatcherQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
public partial class PlaybackSettingsControlViewModel : BaseViewModel,
|
||||
IRecipient<PropertyChangedMessage<LyricsSearchProvider?>>,
|
||||
IRecipient<PropertyChangedMessage<TranslationSearchProvider?>>
|
||||
public partial class PlaybackSettingsControlViewModel : BaseViewModel
|
||||
{
|
||||
private readonly IMediaSessionsService _mediaSessionsService;
|
||||
public IMediaSessionsService MediaSessionsService;
|
||||
private readonly ITranslateService _libreTranslateService;
|
||||
private readonly ILastFMService _lastFMService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
@@ -47,12 +45,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
[ObservableProperty]
|
||||
public partial bool IsLXMusicServerTesting { get; set; } = false;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial LyricsSearchProvider? LyricsSearchProvider { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial TranslationSearchProvider? TranslationSearchProvider { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string OriginalLyricsRef { get; set; } = "about:blank";
|
||||
|
||||
@@ -72,8 +64,9 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
ILastFMService lastFMService,
|
||||
IResourceService resourceService)
|
||||
{
|
||||
MediaSessionsService = mediaSessionsService;
|
||||
|
||||
_settingsService = settingsService;
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
_libreTranslateService = libreTranslateService;
|
||||
_resourceService = resourceService;
|
||||
|
||||
@@ -81,8 +74,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
_lastFMService.UserChanged += LastFMService_UserChanged;
|
||||
_lastFMService.IsAuthenticatedChanged += LastFMService_IsAuthenticatedChanged;
|
||||
|
||||
_mediaSessionsService.SongInfoChanged += MediaSessionsService_SongInfoChanged;
|
||||
|
||||
AppSettings = _settingsService.AppSettings;
|
||||
AppSettings.MediaSourceProvidersInfo.CollectionChanged += MediaSourceProvidersInfo_CollectionChanged;
|
||||
|
||||
@@ -93,9 +84,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IsLastFMAuthenticated = _lastFMService.IsAuthenticated;
|
||||
LastFMUser = _lastFMService.User;
|
||||
|
||||
LyricsSearchProvider = _mediaSessionsService.LyricsSearchProvider;
|
||||
TranslationSearchProvider = _mediaSessionsService.TranslationSearchProvider;
|
||||
|
||||
SelectedMediaSourceProvider = AppSettings.MediaSourceProvidersInfo.FirstOrDefault();
|
||||
}
|
||||
|
||||
@@ -114,15 +102,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
LastFMUser = e.User;
|
||||
}
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.PlayerId)?.FirstOrDefault();
|
||||
if (_mediaSessionsService.Position.TotalSeconds <= 1 && current?.ResetPositionOffsetOnSongChanged == true)
|
||||
{
|
||||
current.PositionOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void MediaSessionsService_SessionIdsChanged(object? sender, Events.MediaSourceProvidersInfoEventArgs e)
|
||||
{
|
||||
SelectedMediaSourceProvider = AppSettings.MediaSourceProvidersInfo.FirstOrDefault();
|
||||
@@ -201,29 +180,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
private void SaveAppleMusicMediaUserToken()
|
||||
{
|
||||
PasswordVaultHelper.Save(Constants.App.AppName, Constants.AppleMusic.MediaUserTokenKey, AppleMusicMediaUserToken);
|
||||
_mediaSessionsService.UpdateLyrics();
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<LyricsSearchProvider?> message)
|
||||
{
|
||||
if (message.Sender is MediaSessionsService)
|
||||
{
|
||||
if (message.PropertyName == nameof(MediaSessionsService.LyricsSearchProvider))
|
||||
{
|
||||
LyricsSearchProvider = message.NewValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<TranslationSearchProvider?> message)
|
||||
{
|
||||
if (message.Sender is MediaSessionsService)
|
||||
{
|
||||
if (message.PropertyName == nameof(MediaSessionsService.TranslationSearchProvider))
|
||||
{
|
||||
TranslationSearchProvider = message.NewValue;
|
||||
}
|
||||
}
|
||||
MediaSessionsService.UpdateLyrics();
|
||||
}
|
||||
|
||||
partial void OnSelectedTargetLanguageIndexChanged(int value)
|
||||
|
||||
@@ -201,13 +201,13 @@
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.IsSongPlaying, Mode=OneWay}"
|
||||
Binding="{x:Bind ViewModel.MediaSessionsService.CurrentIsPlaying, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.IsSongPlaying, Mode=OneWay}"
|
||||
Binding="{x:Bind ViewModel.MediaSessionsService.CurrentIsPlaying, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
@@ -221,13 +221,13 @@
|
||||
Style="{StaticResource GhostButtonStyle}">
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.IsSongPlaying, Mode=OneWay}"
|
||||
Binding="{x:Bind ViewModel.MediaSessionsService.CurrentIsPlaying, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="True">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" />
|
||||
</interactivity:DataTriggerBehavior>
|
||||
<interactivity:DataTriggerBehavior
|
||||
Binding="{x:Bind ViewModel.IsSongPlaying, Mode=OneWay}"
|
||||
Binding="{x:Bind ViewModel.MediaSessionsService.CurrentIsPlaying, Mode=OneWay}"
|
||||
ComparisonCondition="Equal"
|
||||
Value="False">
|
||||
<interactivity:ChangePropertyAction PropertyName="Visibility" Value="Visible" />
|
||||
@@ -316,7 +316,7 @@
|
||||
Margin="0,-32,0,0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Maximum="{x:Bind ViewModel.SongDurationSeconds, Mode=OneWay}"
|
||||
Maximum="{x:Bind ViewModel.MediaSessionsService.CurrentSongInfo.DurationMs, Mode=OneWay, Converter={StaticResource MillisecondsToSecondsConverter}}"
|
||||
Minimum="0"
|
||||
Style="{StaticResource GhostSliderStyle}"
|
||||
ThumbToolTipValueConverter="{StaticResource SecondsToFormattedTimeConverter}"
|
||||
|
||||
Reference in New Issue
Block a user