Added AvaloniaUI project.

This commit is contained in:
2025-03-01 17:03:06 -05:00
parent f78fe6fa2b
commit fc28004c89
25 changed files with 616 additions and 2 deletions

View File

@@ -0,0 +1,178 @@
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using Harmonia.Core.Caching;
using Harmonia.Core.Imaging;
using Harmonia.Core.Models;
using Harmonia.Core.Player;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Harmonia.UI.ViewModels;
public partial class PlaybackBarViewModel : ViewModelBase
{
private readonly IAudioPlayer _audioPlayer;
private readonly IAudioImageCache _audioImageCache;
private bool _isPositionChangeInProgress;
private CancellationTokenSource? _audioImageCancellationTokenSource;
private Song? _song;
public Song? Song
{
get
{
return _song;
}
private set
{
_song = value;
OnPropertyChanged();
CurrentPosition = 0; // What if player is being loaded and returning to save state?
Position = 0;
MaxPosition = value?.Length.TotalSeconds ?? 0;
}
}
private Bitmap? _songImageSource;
public Bitmap? SongImageSource
{
get
{
return _songImageSource;
}
private set
{
_songImageSource = value;
OnPropertyChanged();
}
}
private double _currentPosition;
public double CurrentPosition
{
get
{
return _currentPosition;
}
set
{
_currentPosition = value;
OnPropertyChanged();
if (_isPositionChangeInProgress)
_audioPlayer.Position = value;
}
}
private double _position;
public double Position
{
get
{
return _position;
}
private set
{
_position = value;
OnPropertyChanged();
}
}
private double _maxPosition;
public double MaxPosition
{
get
{
return _maxPosition;
}
set
{
_maxPosition = value;
OnPropertyChanged();
}
}
public bool IsRandom
{
get
{
return _audioPlayer.IsRandom;
}
private set
{
_audioPlayer.IsRandom = value;
OnPropertyChanged();
}
}
public string Greeting => "Welcome to Harmonia!";
public PlaybackBarViewModel(IAudioPlayer audioPlayer, IAudioImageCache audioImageCache)
{
_audioPlayer = audioPlayer;
_audioPlayer.PlayingSongChanged += OnAudioPlayerPlayingSongChanged;
_audioImageCache = audioImageCache;
}
private void OnAudioPlayerPlayingSongChanged(object? sender, EventArgs e)
{
Song = _audioPlayer.PlayingSong?.Song;
Task.Run(UpdateImage);
}
private async Task UpdateImage()
{
// TODO: Show default picture
if (Song == null)
return;
if (_audioImageCancellationTokenSource != null)
await _audioImageCancellationTokenSource.CancelAsync();
_audioImageCancellationTokenSource = new();
CancellationToken cancellationToken = _audioImageCancellationTokenSource.Token;
SongPictureInfo? songPictureInfo = await _audioImageCache.GetAsync(Song, cancellationToken);
if (songPictureInfo == null)
return;
await Dispatcher.UIThread.InvokeAsync(() => SetSongImageSource(songPictureInfo));
}
private void SetSongImageSource(SongPictureInfo songPictureInfo)
{
SongImageSource = new(songPictureInfo.Stream);
}
public void Play()
{
_audioPlayer.Play();
}
public void Pause()
{
_audioPlayer.Pause();
}
public void Stop()
{
_audioPlayer.Stop();
CurrentPosition = 0;
Position = 0;
}
public void Previous()
{
_audioPlayer.PreviousAsync();
}
public void Next()
{
_audioPlayer.NextAsync();
}
}