Updated SongPictureInfo use to async copy of picture data stream. Update other classes accordingly.

This commit is contained in:
2025-03-02 23:28:28 -05:00
parent 1a9c1a5478
commit 0675131195
11 changed files with 178 additions and 149 deletions

View File

@@ -1,6 +1,7 @@
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.Input;
using Harmonia.Core.Caching;
using Harmonia.Core.Imaging;
using Harmonia.Core.Models;
@@ -8,9 +9,11 @@ using Harmonia.Core.Player;
using Harmonia.Core.Playlists;
using Harmonia.Core.Scanner;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
namespace Harmonia.UI.ViewModels;
@@ -33,6 +36,7 @@ public partial class PlaybackBarViewModel : ViewModelBase
{
_song = value;
OnPropertyChanged();
OnPropertyChanged(nameof(FormattedSongInfo));
CurrentPosition = 0; // What if player is being loaded and returning to save state?
Position = 0;
@@ -54,6 +58,10 @@ public partial class PlaybackBarViewModel : ViewModelBase
}
}
public string FormattedSongInfo => Song != null
? $"{Song.FileType} - {Song.BitRate} kbps - {Song.SampleRate} Hz"
: string.Empty;
private double _currentPosition;
public double CurrentPosition
{
@@ -123,7 +131,11 @@ public partial class PlaybackBarViewModel : ViewModelBase
}
}
public string Greeting => "Welcome to Harmonia!";
public ICommand PlaySongCommand => new RelayCommand(Play);
public ICommand PauseSongCommand => new RelayCommand(Pause);
public ICommand StopSongCommand => new RelayCommand(Stop);
public ICommand PreviousSongCommand => new RelayCommand(Previous);
public ICommand NextSongCommand => new RelayCommand(Next);
public PlaybackBarViewModel(IAudioPlayer audioPlayer, IAudioImageCache audioImageCache, IPlaylistRepository playlistRepository, IAudioFileScanner audioFileScanner)
{
@@ -133,6 +145,27 @@ public partial class PlaybackBarViewModel : ViewModelBase
_audioImageCache = audioImageCache;
_timer = new(TimeSpan.FromMilliseconds(100), DispatcherPriority.Default, TickTock);
PlayDemoSong(playlistRepository, audioFileScanner);
}
private async Task PlayDemoSong(IPlaylistRepository playlistRepository, IAudioFileScanner audioFileScanner, CancellationToken cancellationToken = default)
{
if (playlistRepository.Get().Count == 0)
{
playlistRepository.AddPlaylist();
Playlist playlist = playlistRepository.Get().First();
//string songPath = @"D:\Music\Game Music\Bobby Prince\Doom II";
//string songPath = @"D:\Music\Anime Music\HimeHina";
string songPath = @"D:\Music\K-Pop";
Song[] songs = await audioFileScanner.GetSongsFromPathAsync(songPath, cancellationToken);
playlist.AddSongs(songs);
}
await _audioPlayer.LoadAsync(playlistRepository.Get().First().Songs[0], PlaybackMode.LoadAndPlay);
}
private void OnAudioPlayerPlayingSongChanged(object? sender, EventArgs e)
@@ -163,7 +196,11 @@ public partial class PlaybackBarViewModel : ViewModelBase
private void SetSongImageSource(SongPictureInfo songPictureInfo)
{
SongImageSource = new(songPictureInfo.Stream);
if (songPictureInfo.Data.Length == 0)
return;
using MemoryStream stream = new(songPictureInfo.Data);
SongImageSource = new(stream);
}
private void TickTock(object? sender, object e)

View File

@@ -14,9 +14,12 @@
<vm:MainViewModel />
</Design.DataContext>
<StackPanel>
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<views:PlaybackBar></views:PlaybackBar>
</StackPanel>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<views:PlaybackBar Grid.Row="1"></views:PlaybackBar>
</Grid>
</UserControl>

View File

@@ -14,80 +14,94 @@
<converter:NullVisibilityConverter x:Key="NullVisibility" />
<converter:SongTitleConverter x:Key="SongTitle" />
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<!-- Slider -->
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Center" Margin="0 0 0 10">
<UserControl.Styles>
<!-- Flat Button -->
<Style Selector="Button.Flat">
<Setter Property="Padding" Value="10"/>
<Setter Property="Margin" Value="8 0 8 0"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
</Style>
<!-- Flat Button Path Icon -->
<Style Selector="PathIcon.FlatButtonIcon">
<Setter Property="Padding" Value="10"/>
<Setter Property="Width" Value="18"/>
<Setter Property="Height" Value="18"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<!-- Flat Button Path Icon (Large) -->
<Style Selector="PathIcon.FlatButtonIcon.Large">
<Setter Property="Width" Value="36"/>
<Setter Property="Height" Value="36"/>
</Style>
</UserControl.Styles>
<Border Background="#1a1a1a" Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Foreground="#aaaaaa" Text="{Binding Position, Converter={StaticResource SecondsToString}}" FontSize="13" Margin="0 0 6 0" VerticalAlignment="Center"></TextBlock>
<Slider Name="TrackSlider" Loaded="Slider_Loaded" Grid.Column="1" Value="{Binding CurrentPosition, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Minimum="0" Maximum="{Binding MaxPosition, Mode=OneWay}" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Foreground="#aaaaaa" Text="{Binding MaxPosition, Converter={StaticResource SecondsToString}}" FontSize="13" Margin="6 0 0 0" VerticalAlignment="Center"></TextBlock>
</Grid>
<!-- Song Info -->
<Grid Grid.Row="1" Grid.Column="0" Name="PlayingSongGrid">
<StackPanel Orientation="Horizontal">
<Grid Margin="0 0 10 0">
<!--<Image Name="PlayingSongImage" Width="80" Height="80"></Image>-->
<Image Source="{Binding SongImageSource, Mode=TwoWay}" Width="80" Height="80"></Image>
<Canvas Background="#19000000"></Canvas>
</Grid>
<StackPanel VerticalAlignment="Center">
<TextBlock Foreground="#dddddd" FontWeight="SemiBold" FontSize="16" LineHeight="20" Text="{Binding Song, Converter={StaticResource SongTitle}}"></TextBlock>
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}"></TextBlock>
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Album}"></TextBlock>
<TextBlock Foreground="#777" FontSize="12" IsVisible="{Binding Song, Converter={StaticResource NullVisibility}}" FontWeight="Normal" Opacity="1.0">
<Run Text="{Binding Song.FileType}"></Run>
<Run Text=" - "></Run>
<Run Text="{Binding Song.BitRate}"></Run>
<Run Text=" kbps - "></Run>
<Run Text="{Binding Song.SampleRate}"></Run>
<Run Text=" Hz"></Run>
</TextBlock>
<!-- Slider -->
<Grid Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" VerticalAlignment="Center" Margin="0 0 0 10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Foreground="#aaaaaa" Text="{Binding Position, Converter={StaticResource SecondsToString}}" FontSize="13" Margin="0 0 6 0" VerticalAlignment="Center"></TextBlock>
<Slider Name="TrackSlider" Loaded="Slider_Loaded" Grid.Column="1" Value="{Binding CurrentPosition, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Minimum="0" Maximum="{Binding MaxPosition, Mode=OneWay}" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Foreground="#aaaaaa" Text="{Binding MaxPosition, Converter={StaticResource SecondsToString}}" FontSize="13" Margin="6 0 0 0" VerticalAlignment="Center"></TextBlock>
</Grid>
<!-- Song Info -->
<Grid Grid.Row="1" Grid.Column="0" Name="PlayingSongGrid">
<StackPanel Orientation="Horizontal">
<Grid Margin="0 0 10 0">
<!--<Image Name="PlayingSongImage" Width="80" Height="80"></Image>-->
<Image Source="{Binding SongImageSource, Mode=TwoWay}" Width="80" Height="80"></Image>
<Canvas Background="#19000000"></Canvas>
</Grid>
<StackPanel VerticalAlignment="Center">
<TextBlock Foreground="#dddddd" FontWeight="SemiBold" FontSize="16" LineHeight="20" Text="{Binding Song, Converter={StaticResource SongTitle}}"></TextBlock>
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}"></TextBlock>
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Album}"></TextBlock>
<TextBlock Foreground="#777" FontSize="12" Text="{Binding FormattedSongInfo}" IsVisible="{Binding Song, Converter={StaticResource NullVisibility}}" FontWeight="Normal" Opacity="1.0">
</TextBlock>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
<!-- Action Buttons -->
<Grid Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<Button Margin="8 0 8 0" Click="PreviousSongButton_Click" Theme="{StaticResource BorderlessButton}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<PathIcon Data="{StaticResource SemiIconBackward}" Margin="0 0 0 0"></PathIcon>
<TextBlock Text="" FontSize="18"/>
</StackPanel>
</Button.Content>
</Button>
<Button Margin="8 0 8 0" Click="StopButton_Click">
<TextBlock Text="&#x0042;" FontSize="18"></TextBlock>
</Button>
<Button Margin="8 0 8 0" Click="PlayButton_Click">
<TextBlock Text="&#x0041;" FontSize="36"></TextBlock>
</Button>
<Button Margin="8 0 8 0" Click="PauseButton_Click">
<TextBlock Text="&#x0043;" FontSize="18"></TextBlock>
</Button>
<Button Margin="8 0 8 0" Click="NextSongButton_Click">
<TextBlock Text="&#x0045;" FontSize="18"></TextBlock>
</Button>
</StackPanel>
<!-- Action Buttons -->
<Grid Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal">
<Button Classes="Flat" Command="{Binding PreviousSongCommand}">
<PathIcon Classes="FlatButtonIcon" Data="{StaticResource SemiIconBackward}"></PathIcon>
</Button>
<Button Classes="Flat" Command="{Binding StopSongCommand}">
<PathIcon Classes="FlatButtonIcon" Data="{StaticResource SemiIconStop}"></PathIcon>
</Button>
<Button Classes="Flat" Command="{Binding PlaySongCommand}">
<PathIcon Classes="FlatButtonIcon Large" Data="{StaticResource SemiIconPlay}"></PathIcon>
</Button>
<Button Classes="Flat" Command="{Binding PauseSongCommand}">
<PathIcon Classes="FlatButtonIcon" Data="{StaticResource SemiIconPause}"></PathIcon>
</Button>
<Button Classes="Flat" Command="{Binding NextSongCommand}">
<PathIcon Classes="FlatButtonIcon" Data="{StaticResource SemiIconFastForward}"></PathIcon>
</Button>
</StackPanel>
</Grid>
</Grid>
</Grid>
</Border>
</UserControl>

View File

@@ -45,29 +45,4 @@ public partial class PlaybackBar : UserControl
_viewModel.CurrentPosition = slider.Value;
_viewModel.IsPositionChangeInProgress = false;
}
private void PlayButton_Click(object? sender, RoutedEventArgs e)
{
_viewModel.Play();
}
private void StopButton_Click(object? sender, RoutedEventArgs e)
{
_viewModel.Stop();
}
private void PauseButton_Click(object? sender, RoutedEventArgs e)
{
_viewModel.Pause();
}
private void PreviousSongButton_Click(object? sender, RoutedEventArgs e)
{
_viewModel.Previous();
}
private void NextSongButton_Click(object sender, RoutedEventArgs e)
{
_viewModel.Next();
}
}