mirror of
https://github.com/Royce551/FRESHMusicPlayer.git
synced 2025-01-22 10:51:52 -05:00
Redesigned Track Info
This commit is contained in:
parent
697ae24fab
commit
d6da528e14
7 changed files with 338 additions and 30 deletions
|
@ -0,0 +1,63 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FRESHMusicPlayer.Controls.BlurryImage
|
||||
{
|
||||
|
||||
// Code taken from https://github.com/PieroCastillo/Aura.UI/blob/master/src/Aura.UI/Rendering/BlurImageRender.cs;
|
||||
// I just didn't want to depend on everything else Aura.UI has
|
||||
|
||||
public class BlurImageRender : DrawOperationBase, ICustomDrawOperation
|
||||
{
|
||||
public BlurImageRender(MemoryStream data, Rect src, Rect dest, float levelX, float levelY, IFormattedTextImpl noSkia) : base(src, noSkia)
|
||||
{
|
||||
_data = data;
|
||||
_levelx = levelX;
|
||||
_levely = levelY;
|
||||
_dest = dest;
|
||||
}
|
||||
|
||||
private MemoryStream _data;
|
||||
private Rect _dest;
|
||||
private float _levelx;
|
||||
private float _levely;
|
||||
|
||||
public override void Render(IDrawingContextImpl drw_context)
|
||||
{
|
||||
base.Render(drw_context);
|
||||
|
||||
if (drw_context is ISkiaDrawingContextImpl context)
|
||||
{
|
||||
var canvas = context.SkCanvas;
|
||||
|
||||
if (_data == null)
|
||||
return;
|
||||
|
||||
|
||||
using (var bitmap = SKBitmap.Decode(_data.ToArray()))
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
if (bitmap == null)
|
||||
{
|
||||
Debug.WriteLine("bitmap is null");
|
||||
return;
|
||||
}
|
||||
var img = SKImage.FromBitmap(bitmap);
|
||||
|
||||
paint.ImageFilter = SKImageFilter.CreateBlur(_levelx, _levely);
|
||||
canvas.DrawImage(img, _dest.ToSKRect(), Bounds.ToSKRect(), paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FRESHMusicPlayer.Controls.BlurryImage
|
||||
{
|
||||
// Code taken from https://github.com/PieroCastillo/Aura.UI/blob/master/src/Aura.UI/Controls/BlurryImage/BlurryImage.cs;
|
||||
// I just didn't want to depend on everything else Aura.UI has
|
||||
|
||||
public class BlurryImage : Control
|
||||
{
|
||||
static BlurryImage()
|
||||
{
|
||||
AffectsRender<BlurryImage>(BlurLevelProperty, SourceProperty, StretchDirectionProperty, StretchProperty);
|
||||
AffectsMeasure<BlurryImage>(BlurLevelProperty, SourceProperty, StretchDirectionProperty, StretchProperty);
|
||||
AffectsArrange<BlurryImage>(BlurLevelProperty, SourceProperty, StretchDirectionProperty, StretchProperty);
|
||||
|
||||
ClipToBoundsProperty.OverrideDefaultValue<BlurryImage>(true);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
var source = Source;
|
||||
var mem = new MemoryStream();
|
||||
Source.Save(mem);
|
||||
|
||||
if (source != null && mem.Length > 0 && Bounds.Width > 0 && Bounds.Height > 0)
|
||||
{
|
||||
Rect viewPort = new Rect(Bounds.Size);
|
||||
Size sourceSize = source.Size;
|
||||
|
||||
Vector scale = Stretch.CalculateScaling(Bounds.Size, sourceSize, StretchDirection);
|
||||
Size scaledSize = sourceSize * scale;
|
||||
Rect destRect = viewPort
|
||||
.CenterRect(new Rect(scaledSize))
|
||||
.Intersect(viewPort);
|
||||
Rect sourceRect = new Rect(sourceSize)
|
||||
.CenterRect(new Rect(destRect.Size / scale));
|
||||
|
||||
var interpolationMode = RenderOptions.GetBitmapInterpolationMode(this);
|
||||
context.Custom(new BlurImageRender(mem, destRect, sourceRect, BlurLevel, BlurLevel, null));
|
||||
// Dispatcher.UIThread.InvokeAsync(InvalidateVisual, DispatcherPriority.Background);
|
||||
}
|
||||
}
|
||||
|
||||
///<inheritdoc/>
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var source = Source;
|
||||
var result = new Size();
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
result = Stretch.CalculateSize(availableSize, source.Size, StretchDirection);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var source = Source;
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
var sourceSize = source.Size;
|
||||
var result = Stretch.CalculateSize(finalSize, sourceSize);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Size();
|
||||
}
|
||||
}
|
||||
|
||||
public float BlurLevel
|
||||
{
|
||||
get => GetValue(BlurLevelProperty);
|
||||
set => SetValue(BlurLevelProperty, value);
|
||||
}
|
||||
|
||||
public IBitmap Source
|
||||
{
|
||||
get => GetValue(SourceProperty);
|
||||
set => SetValue(SourceProperty, value);
|
||||
}
|
||||
|
||||
public Stretch Stretch
|
||||
{
|
||||
get => GetValue(StretchProperty);
|
||||
set => SetValue(StretchProperty, value);
|
||||
}
|
||||
|
||||
public StretchDirection StretchDirection
|
||||
{
|
||||
get => GetValue(StretchDirectionProperty);
|
||||
set => SetValue(StretchDirectionProperty, value);
|
||||
}
|
||||
|
||||
public readonly static StyledProperty<IBitmap> SourceProperty =
|
||||
AvaloniaProperty.Register<BlurryImage, IBitmap>(nameof(Source));
|
||||
|
||||
public readonly static StyledProperty<Stretch> StretchProperty =
|
||||
Image.StretchProperty.AddOwner<BlurryImage>();
|
||||
|
||||
public readonly static StyledProperty<StretchDirection> StretchDirectionProperty =
|
||||
Image.StretchDirectionProperty.AddOwner<BlurryImage>();
|
||||
|
||||
public readonly static StyledProperty<float> BlurLevelProperty =
|
||||
AvaloniaProperty.Register<BlurryImage, float>(nameof(BlurLevel), 16);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.SceneGraph;
|
||||
using Avalonia.Skia;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace FRESHMusicPlayer.Controls.BlurryImage
|
||||
{
|
||||
public abstract class DrawOperationBase : ICustomDrawOperation
|
||||
{
|
||||
public DrawOperationBase(Rect bounds, IFormattedTextImpl noSkia)
|
||||
{
|
||||
Bounds = bounds;
|
||||
NoSkia = noSkia;
|
||||
}
|
||||
|
||||
public virtual Rect Bounds { get; private set; }
|
||||
public virtual IFormattedTextImpl NoSkia { get; private set; }
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public virtual bool Equals(ICustomDrawOperation other) => false;
|
||||
|
||||
public virtual bool HitTest(Point p) => true;
|
||||
|
||||
public virtual void Render(IDrawingContextImpl context)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual bool CheckSkia(IDrawingContextImpl context)
|
||||
{
|
||||
if (context is ISkiaDrawingContextImpl)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ namespace FRESHMusicPlayer.ViewModels
|
|||
public ObservableCollection<DisplayLanguage> AvailableLanguages { get; } = new()
|
||||
{
|
||||
new("Automatic", "automatic"),
|
||||
new("English", "en"),
|
||||
new("German", "de"),
|
||||
new("Vietnamese", "vi")
|
||||
};
|
||||
|
||||
|
|
|
@ -26,30 +26,58 @@ namespace FRESHMusicPlayer.ViewModels
|
|||
get => bitrateText;
|
||||
set => this.RaiseAndSetIfChanged(ref bitrateText, value);
|
||||
}
|
||||
|
||||
private string discNumberText;
|
||||
public string DiscNumberText
|
||||
{
|
||||
get => discNumberText;
|
||||
set => this.RaiseAndSetIfChanged(ref discNumberText, value);
|
||||
}
|
||||
private bool discNumberShouldBeVisible = true;
|
||||
public bool DiscNumberShouldBeVisible
|
||||
{
|
||||
get => discNumberShouldBeVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref discNumberShouldBeVisible, value);
|
||||
}
|
||||
|
||||
private string trackNumberText;
|
||||
public string TrackNumberText
|
||||
{
|
||||
get => trackNumberText;
|
||||
set => this.RaiseAndSetIfChanged(ref trackNumberText, value);
|
||||
}
|
||||
private bool trackNumberShouldBeVisible = true;
|
||||
public bool TrackNumberShouldBeVisible
|
||||
{
|
||||
get => trackNumberShouldBeVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref trackNumberShouldBeVisible, value);
|
||||
}
|
||||
|
||||
private string yearText;
|
||||
public string YearText
|
||||
{
|
||||
get => yearText;
|
||||
set => this.RaiseAndSetIfChanged(ref yearText, value);
|
||||
}
|
||||
private bool yearShouldBeVisible = true;
|
||||
public bool YearShouldBeVisible
|
||||
{
|
||||
get => yearShouldBeVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref yearShouldBeVisible, value);
|
||||
}
|
||||
|
||||
private string albumText;
|
||||
public string AlbumText
|
||||
{
|
||||
get => albumText;
|
||||
set => this.RaiseAndSetIfChanged(ref albumText, value);
|
||||
}
|
||||
private bool albumShouldBeVisible = true;
|
||||
public bool AlbumShouldBeVisible
|
||||
{
|
||||
get => albumShouldBeVisible;
|
||||
set => this.RaiseAndSetIfChanged(ref albumShouldBeVisible, value);
|
||||
}
|
||||
|
||||
public TrackInfoViewModel()
|
||||
{
|
||||
|
@ -70,20 +98,26 @@ namespace FRESHMusicPlayer.ViewModels
|
|||
{
|
||||
var track = new Track(Player.FilePath);
|
||||
|
||||
if (track.EmbeddedPictures.Count > 0)
|
||||
CoverArt = new Bitmap(new MemoryStream(track.EmbeddedPictures[0].PictureData));
|
||||
else
|
||||
CoverArt = null;
|
||||
CoverArt = track.EmbeddedPictures.Count <= 0 ? null : new Bitmap(new MemoryStream(track.EmbeddedPictures[0].PictureData));
|
||||
|
||||
BitrateText = track.Bitrate == 0 ? null : $"Bitrate - {track.Bitrate}kbps {track.SampleRate / 1000}kHz";
|
||||
DiscNumberShouldBeVisible = true;
|
||||
TrackNumberShouldBeVisible = true;
|
||||
YearShouldBeVisible = true;
|
||||
AlbumShouldBeVisible = true;
|
||||
|
||||
DiscNumberText = track.DiscNumber == 0 ? null : $"Disc {track.DiscNumber}";
|
||||
if (track.DiscTotal > 0) DiscNumberText = $"Disc {track.DiscNumber}/{track.DiscTotal}";
|
||||
TrackNumberText = track.TrackNumber == 0 ? null : $"Track {track.TrackNumber}";
|
||||
if (track.TrackTotal > 0) TrackNumberText = $"Track {track.TrackNumber}/{track.TrackTotal}";
|
||||
BitrateText = $"{track.Bitrate}kbps {track.SampleRate / 1000}kHz";
|
||||
|
||||
YearText = track.Year == 0 ? null : $"Year {track.Year}";
|
||||
AlbumText = track.Album is null ? null : $"Album - {track.Album}";
|
||||
if (track.DiscNumber == 0) DiscNumberShouldBeVisible = false;
|
||||
else DiscNumberText = track.DiscTotal <= 0 ? track.DiscNumber.ToString() : $"{track.DiscNumber}/{track.DiscTotal}";
|
||||
|
||||
if (track.TrackNumber == 0) TrackNumberShouldBeVisible = false;
|
||||
else TrackNumberText = track.TrackTotal <= 0 ? track.TrackNumber.ToString() : $"{track.TrackNumber}/{track.TrackTotal}";
|
||||
|
||||
if (track.Year == 0) YearShouldBeVisible = false;
|
||||
else YearText = track.Year.ToString();
|
||||
|
||||
if (track.Album is null) AlbumShouldBeVisible = false;
|
||||
else AlbumText = track.Album;
|
||||
}
|
||||
|
||||
private void Player_SongChanged(object sender, EventArgs e) => Update();
|
||||
|
|
|
@ -9,6 +9,7 @@ using System;
|
|||
using System.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using FRESHMusicPlayer.Utilities;
|
||||
|
||||
namespace FRESHMusicPlayer.Views
|
||||
{
|
||||
|
@ -122,6 +123,20 @@ namespace FRESHMusicPlayer.Views
|
|||
ViewModel.PlayPauseCommand();
|
||||
break;
|
||||
}
|
||||
switch (e.Key)
|
||||
{
|
||||
case Key.F1:
|
||||
InterfaceUtils.OpenURL("https://royce551.github.io/FRESHMusicPlayer/docs/index.html");
|
||||
break;
|
||||
case Key.F2:
|
||||
GC.Collect(2);
|
||||
break;
|
||||
case Key.F3:
|
||||
throw new Exception("Exception for debugging");
|
||||
case Key.F4:
|
||||
Topmost = !Topmost;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDragEnter(object sender, DragEventArgs e)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:FRESHMusicPlayer.Controls.BlurryImage"
|
||||
xmlns:vm="using:FRESHMusicPlayer.ViewModels"
|
||||
mc:Ignorable="d" Width="500" Height="300"
|
||||
x:Class="FRESHMusicPlayer.Views.TrackInfo" WindowStartupLocation="CenterOwner" Closing="OnClosing"
|
||||
|
@ -10,26 +11,50 @@
|
|||
<vm:TrackInfoViewModel/>
|
||||
</Window.DataContext>
|
||||
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width=".5*"/>
|
||||
<ColumnDefinition Width=".5*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Panel>
|
||||
<controls:BlurryImage ZIndex="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Source="{Binding CoverArt}" BlurLevel="10" Stretch="UniformToFill" Margin="-10"/>
|
||||
<Rectangle ZIndex="1" Fill="{StaticResource BackgroundColor}" Opacity="0.55"/>
|
||||
<Grid ZIndex="2" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Stretch">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="1*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<CheckBox Grid.ColumnSpan="2" IsChecked="{Binding $parent[Window].Topmost}" Content="Pin to top"/>
|
||||
<CheckBox Grid.ColumnSpan="3" IsChecked="{Binding $parent[Window].Topmost}" Content="Pin to top"/>
|
||||
|
||||
<Image Grid.Row="1" Grid.Column="0" Source="{Binding CoverArt}"/>
|
||||
<Image Grid.Row="1" Grid.Column="0" Source="{Binding CoverArt}" HorizontalAlignment="Right">
|
||||
</Image>
|
||||
|
||||
<StackPanel Grid.Row="1" Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center" Spacing="5">
|
||||
<TextBlock Text="{Binding BitrateText}" TextWrapping="Wrap"/>
|
||||
<TextBlock Text="{Binding DiscNumberText}" TextWrapping="Wrap"/>
|
||||
<TextBlock Text="{Binding TrackNumberText}" TextWrapping="Wrap"/>
|
||||
<TextBlock Text="{Binding YearText}" TextWrapping="Wrap"/>
|
||||
<TextBlock Text="{Binding AlbumText}" TextWrapping="Wrap"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Grid.Column="1" Margin="10,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" Margin="0,2" Text="Bitrate" Foreground="{StaticResource SecondaryTextColor}"/>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" Margin="0,2" Text="Disc" Foreground="{StaticResource SecondaryTextColor}" IsVisible="{Binding DiscNumberShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="0" Grid.Row="2" Margin="0,2" Text="Track" Foreground="{StaticResource SecondaryTextColor}" IsVisible="{Binding TrackNumberShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="0" Grid.Row="3" Margin="0,2" Text="Year" Foreground="{StaticResource SecondaryTextColor}" IsVisible="{Binding YearShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="0" Grid.Row="4" Margin="0,2" Text="Album" Foreground="{StaticResource SecondaryTextColor}" IsVisible="{Binding AlbumShouldBeVisible}"/>
|
||||
|
||||
<TextBlock Grid.Column="1" Grid.Row="0" Margin="10,2,0,2" Text="{Binding BitrateText}"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" Margin="10,2,0,2" Text="{Binding DiscNumberText}" IsVisible="{Binding DiscNumberShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="2" Margin="10,2,0,2" Text="{Binding TrackNumberText}" IsVisible="{Binding TrackNumberShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="3" Margin="10,2,0,2" Text="{Binding YearText}" IsVisible="{Binding YearShouldBeVisible}"/>
|
||||
<TextBlock Grid.Column="1" Grid.Row="4" Margin="10,2,0,2" Text="{Binding AlbumText}" IsVisible="{Binding AlbumShouldBeVisible}"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Panel>
|
||||
|
||||
</Window>
|
||||
|
|
Loading…
Reference in a new issue