diff --git a/Harmonia.WinUI/App.xaml.cs b/Harmonia.WinUI/App.xaml.cs index 8a49cc0..3cd5a6e 100644 --- a/Harmonia.WinUI/App.xaml.cs +++ b/Harmonia.WinUI/App.xaml.cs @@ -58,7 +58,7 @@ public partial class App : Application await sessionService.LoadAsync(); ISessionRestorer sessionRestorer = ServiceProvider.GetRequiredService(); - sessionRestorer.Restore(); + await sessionRestorer.RestoreAsync(); ISessionTracker sessionTracker = ServiceProvider.GetRequiredService(); sessionTracker.Start(); diff --git a/Harmonia.WinUI/MainWindow.xaml.cs b/Harmonia.WinUI/MainWindow.xaml.cs index 30daf16..753ce98 100644 --- a/Harmonia.WinUI/MainWindow.xaml.cs +++ b/Harmonia.WinUI/MainWindow.xaml.cs @@ -9,12 +9,14 @@ public sealed partial class MainWindow : Window private const string ApplicationTitle = "Harmonia"; private readonly ISessionService _sessionService; + private readonly ISessionTracker _sessionTracker; private bool _isSaved; - public MainWindow(ISessionService sessionService) + public MainWindow(ISessionService sessionService, ISessionTracker sessionTracker) { _sessionService = sessionService; + _sessionTracker = sessionTracker; InitializeComponent(); InitializeTitleBar(); @@ -57,6 +59,7 @@ public sealed partial class MainWindow : Window args.Handled = true; + _sessionTracker.Capture(); await _sessionService.SaveAsync(); _isSaved = true; diff --git a/Harmonia.WinUI/Session/AudioPlayerState.cs b/Harmonia.WinUI/Session/AudioPlayerState.cs index 2f9d113..c571bb4 100644 --- a/Harmonia.WinUI/Session/AudioPlayerState.cs +++ b/Harmonia.WinUI/Session/AudioPlayerState.cs @@ -1,11 +1,13 @@ -namespace Harmonia.WinUI.Session; +using Harmonia.Core.Engine; + +namespace Harmonia.WinUI.Session; public partial class AudioPlayerState { public string? PlaylistUID { get; set; } public string? PlaylistSongUID { get; set; } public double Position { get; set; } = 0.0; - public string? PlaybackState { get; set; } + public AudioPlaybackState PlaybackState { get; set; } = AudioPlaybackState.Stopped; public double Volume { get; set; } = 1.0; public bool IsMuted { get; set; } public string? RepeatState { get; set; } diff --git a/Harmonia.WinUI/Session/ISessionRestorer.cs b/Harmonia.WinUI/Session/ISessionRestorer.cs index 83b0e6f..a514141 100644 --- a/Harmonia.WinUI/Session/ISessionRestorer.cs +++ b/Harmonia.WinUI/Session/ISessionRestorer.cs @@ -1,6 +1,8 @@ -namespace Harmonia.WinUI.Session; +using System.Threading.Tasks; + +namespace Harmonia.WinUI.Session; public interface ISessionRestorer { - void Restore(); + Task RestoreAsync(); } \ No newline at end of file diff --git a/Harmonia.WinUI/Session/ISessionTracker.cs b/Harmonia.WinUI/Session/ISessionTracker.cs index 92808ef..89c75e1 100644 --- a/Harmonia.WinUI/Session/ISessionTracker.cs +++ b/Harmonia.WinUI/Session/ISessionTracker.cs @@ -3,4 +3,5 @@ namespace Harmonia.WinUI.Session; public interface ISessionTracker { void Start(); + void Capture(); } \ No newline at end of file diff --git a/Harmonia.WinUI/Session/SessionRestorer.cs b/Harmonia.WinUI/Session/SessionRestorer.cs index 703a866..6101ec4 100644 --- a/Harmonia.WinUI/Session/SessionRestorer.cs +++ b/Harmonia.WinUI/Session/SessionRestorer.cs @@ -1,7 +1,9 @@ -using Harmonia.Core.Player; +using Harmonia.Core.Engine; +using Harmonia.Core.Player; using Harmonia.Core.Playlists; using System; using System.Linq; +using System.Threading.Tasks; namespace Harmonia.WinUI.Session; @@ -10,10 +12,10 @@ public class SessionRestorer( IPlaylistManager playlistManager, IAudioPlayer audioPlayer) : ISessionRestorer { - public void Restore() + public async Task RestoreAsync() { RestorePlaylist(); - RestoreAudioPlayer(); + await RestoreAudioPlayerAsync(); } private void RestorePlaylist() @@ -31,7 +33,7 @@ public class SessionRestorer( playlistManager.CurrentPlaylist = playlist; } - private void RestoreAudioPlayer() + private async Task RestoreAudioPlayerAsync() { AudioPlayerState audioPlayerState = sessionService.Session.Player; @@ -43,13 +45,27 @@ public class SessionRestorer( if (playlist is null) return; - PlaylistSong? song = playlist.Songs.FirstOrDefault(s => s.UID == audioPlayerState.PlaylistSongUID); + PlaylistSong? playlistSong = playlist.Songs.FirstOrDefault(s => s.UID == audioPlayerState.PlaylistSongUID); - if (song is null) + if (playlistSong is null) return; - //PlaybackMode playbackMode = audioPlayerState.PlaybackState + await audioPlayer.LoadAsync(playlistSong, PlaybackMode.LoadOnly); - audioPlayer.LoadAsync(song, PlaybackMode.LoadOnly); + if (audioPlayerState.Position > 0 && audioPlayerState.Position <= playlistSong.Song.Length.TotalSeconds) + audioPlayer.Position = audioPlayerState.Position; + + switch (audioPlayerState.PlaybackState) + { + case AudioPlaybackState.Playing: + audioPlayer.Play(); + break; + case AudioPlaybackState.Paused: + audioPlayer.Pause(); + break; + case AudioPlaybackState.Stopped: + audioPlayer.Stop(); + break; + } } } \ No newline at end of file diff --git a/Harmonia.WinUI/Session/SessionTracker.cs b/Harmonia.WinUI/Session/SessionTracker.cs index 76303b6..cbaf3ba 100644 --- a/Harmonia.WinUI/Session/SessionTracker.cs +++ b/Harmonia.WinUI/Session/SessionTracker.cs @@ -13,6 +13,7 @@ public class SessionTracker( { playlistManager.CurrentPlaylistChanged += OnCurrentPlaylistChanged; audioPlayer.PlayingSongChanged += OnPlayingSongChanged; + audioPlayer.PropertyChanged += OnAudioPlayerPropertyChanged; } private void OnCurrentPlaylistChanged(object? sender, EventArgs e) @@ -26,4 +27,19 @@ public class SessionTracker( AudioPlayerState audioPlayerState = sessionService.Session.Player; audioPlayerState.PlaylistSongUID = e.NewSong?.UID; } + + private void OnAudioPlayerPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(IAudioPlayer.State): + sessionService.Session.Player.PlaybackState = audioPlayer.State; + break; + } + } + + public void Capture() + { + sessionService.Session.Player.Position = audioPlayer.Position; + } } diff --git a/Harmonia.WinUI/ViewModels/PlayerViewModel.cs b/Harmonia.WinUI/ViewModels/PlayerViewModel.cs index 6cbd599..d05472d 100644 --- a/Harmonia.WinUI/ViewModels/PlayerViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlayerViewModel.cs @@ -225,6 +225,20 @@ public partial class PlayerViewModel : ViewModelBase _timer.Tick += TickTock; _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + + TryRestore(); + } + + private void TryRestore() + { + if (_audioPlayer.PlayingSong is null) + return; + + Song = _audioPlayer.PlayingSong.Song; + Position = _audioPlayer.Position; + CurrentPosition = _audioPlayer.Position; + + Task.Run(UpdateImage); } #region Event Handlers diff --git a/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs b/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs index 62a6254..07c32b4 100644 --- a/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs @@ -50,6 +50,17 @@ public partial class PlayingSongViewModel : ViewModelBase _audioBitmapImageCache = audioBitmapImageCache; _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + + TryRestore(); + } + + private void TryRestore() + { + if (_audioPlayer.PlayingSong is null) + return; + + Song = _audioPlayer.PlayingSong.Song; + Task.Run(UpdateImage); } private void OnAudioPlayerPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) diff --git a/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs b/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs index 9014b68..c40dc1b 100644 --- a/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs @@ -220,6 +220,8 @@ public partial class PlaylistDetailViewModel : ViewModelBase FilteredPlaylistSongs.CollectionChanged += OnFilteredPlaylistSongsCollectionChanged; Playlist = _playlistManager.CurrentPlaylist; // Testing + PlayingSong = _audioPlayer.PlayingSong; // Testing + UpdateFilteredSongs(); } diff --git a/Harmonia.WinUI/Views/PlaylistDetailView.xaml.cs b/Harmonia.WinUI/Views/PlaylistDetailView.xaml.cs index 7907cf9..9409ee9 100644 --- a/Harmonia.WinUI/Views/PlaylistDetailView.xaml.cs +++ b/Harmonia.WinUI/Views/PlaylistDetailView.xaml.cs @@ -56,6 +56,16 @@ public sealed partial class PlaylistDetailView : UserControl SortSelectedByMenuFlyoutSubItem.IsEnabled = _viewModel.SortSelectedCommand.CanExecute(null); SortSelectedByMenuFlyoutSubItem.IsEnabled = _viewModel.SortSelectedCommand.CanExecute(null); + + Loaded += OnLoaded; + } + + private void OnLoaded(object sender, RoutedEventArgs e) + { + Loaded -= OnLoaded; + + // Defer until the ListView has completed its first layout/container realization pass. + DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, BringPlayingSongIntoView); } private void OnViewModelPropertyChanging(object? sender, PropertyChangingEventArgs e) @@ -274,7 +284,7 @@ public sealed partial class PlaylistDetailView : UserControl if (args.NewValue is not PlaylistSong playlistSong) return; - bool isPlaying = playlistSong == _viewModel.PlayingSong; + bool isPlaying = playlistSong.UID == _viewModel.PlayingSong?.UID; UpdateListViewItemStyle(sender, isPlaying); }