diff --git a/Terminal.Gui b/Terminal.Gui
index f9d117f..5cc4b7f 160000
--- a/Terminal.Gui
+++ b/Terminal.Gui
@@ -1 +1 @@
-Subproject commit f9d117f97f020ec411482253afefafb865fcd71f
+Subproject commit 5cc4b7f70cde25c0bfb57bc48b480a73c692dfbe
diff --git a/smoc.Tests/Fakes/FakeMainWindow.cs b/smoc.Tests/Fakes/FakeMainWindow.cs
index 70268d9..b8c2454 100644
--- a/smoc.Tests/Fakes/FakeMainWindow.cs
+++ b/smoc.Tests/Fakes/FakeMainWindow.cs
@@ -1,5 +1,4 @@
using Smoc.Ui;
-using Smoc.Ui.Drawing;
using Smoc.Ui.Models;
using Terminal.Gui.App;
@@ -13,9 +12,6 @@ public class FakeMainWindow : IMainWindow {
///
public IApplication? App { get; } = FakeApplication.New();
- ///
- public ISixelDriver SixelDriver { get; set; } = new FakeSixelDriver();
-
///
public Mode CurrentMode { get; set; }
diff --git a/smoc.Tests/Fakes/FakeSixelDriver.cs b/smoc.Tests/Fakes/FakeSixelDriver.cs
deleted file mode 100644
index e817c41..0000000
--- a/smoc.Tests/Fakes/FakeSixelDriver.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System.Drawing;
-using Smoc.Ui.Drawing;
-using Terminal.Gui.Drawing;
-
-namespace smoc.Tests.Fakes;
-
-///
-/// A fake implementation of for use in tests.
-///
-public class FakeSixelDriver : ISixelDriver {
- ///
- public double CellAspectRatio => 2.0;
-
- ///
- public bool IsSupported => true;
-
- ///
- public Size? Resolution => null;
-
- ///
- public int MaxPaletteColors => 256;
-
- ///
- public string EncodeSixel(Terminal.Gui.Drawing.Color[,] colors) {
- return "";
- }
-
- ///
- public void EnqueueSixel(SixelToRender sixelToRender) {
- return;
- }
-
- ///
- public void Initialize() {
- return;
- }
-}
\ No newline at end of file
diff --git a/smoc.Tests/TestInit.cs b/smoc.Tests/TestInit.cs
new file mode 100644
index 0000000..65b2e0f
--- /dev/null
+++ b/smoc.Tests/TestInit.cs
@@ -0,0 +1,15 @@
+using System.Runtime.CompilerServices;
+
+///
+/// Initializes the test environment.
+///
+internal static class TestInitializer {
+ ///
+ /// Sets up the test environment.
+ ///
+ [ModuleInitializer]
+ public static void SetupEnvironment() {
+ // Disable real driver IO to prevent terminal.gui from opening a real terminal.
+ Environment.SetEnvironmentVariable("DisableRealDriverIO", "1");
+ }
+}
\ No newline at end of file
diff --git a/smoc.Tests/goldens/NowPlayingBarTest/OnSongChanged_UpdatesSongDetails.golden b/smoc.Tests/goldens/NowPlayingBarTest/OnSongChanged_UpdatesSongDetails.golden
index eb04c8f..cb0db8f 100644
--- a/smoc.Tests/goldens/NowPlayingBarTest/OnSongChanged_UpdatesSongDetails.golden
+++ b/smoc.Tests/goldens/NowPlayingBarTest/OnSongChanged_UpdatesSongDetails.golden
@@ -1,7 +1,7 @@
NowPlayingBarTest.OnSongChanged_UpdatesSongDetails_0:
- ┌╌╌╌╌┐ OnSongChangedUpdatesSongDetails
- ┆ ?? ┆ Radiohead volume: 0%
- └╌╌╌╌┘ --:-- --:--
+ OnSongChangedUpdatesSongDetails
+ ?? Radiohead volume: 0%
+ --:-- --:--
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo.golden b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo.golden
index 076210c..37d76ff 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo.golden
@@ -4,11 +4,11 @@ NowPlayingViewTest.InitialState_ShowsEmptyNowPlayingInfo_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Tall.golden b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Tall.golden
index a142a46..a29ce3d 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Tall.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Tall.golden
@@ -6,7 +6,6 @@ NowPlayingViewTest.InitialState_ShowsEmptyNowPlayingInfo_Tall_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
@@ -15,6 +14,7 @@ NowPlayingViewTest.InitialState_ShowsEmptyNowPlayingInfo_Tall_0:
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Wide.golden b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Wide.golden
index 16f7dae..42eb5a4 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Wide.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/InitialState_ShowsEmptyNowPlayingInfo_Wide.golden
@@ -4,11 +4,11 @@ NowPlayingViewTest.InitialState_ShowsEmptyNowPlayingInfo_Wide_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition.golden b/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition.golden
index d247e0d..706c045 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition.golden
@@ -4,11 +4,11 @@ NowPlayingViewTest.OnPositionChanged_UpdatesPosition_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition_MultipleTimes.golden b/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition_MultipleTimes.golden
index ccf4cae..6525d30 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition_MultipleTimes.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/OnPositionChanged_UpdatesPosition_MultipleTimes.golden
@@ -4,11 +4,11 @@ NowPlayingViewTest.OnPositionChanged_UpdatesPosition_MultipleTimes_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_SongIsNull_UpdatesSongDetails.golden b/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_SongIsNull_UpdatesSongDetails.golden
index ff03699..e43766a 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_SongIsNull_UpdatesSongDetails.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_SongIsNull_UpdatesSongDetails.golden
@@ -4,11 +4,11 @@ NowPlayingViewTest.OnSongChanged_SongIsNull_UpdatesSongDetails_0:
┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
┆ ┆
+ ┆ ?? ┆
┆ ┆
┆ ┆
┆ ┆
diff --git a/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_UpdatesSongDetails.golden b/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_UpdatesSongDetails.golden
index ecab2a7..70585e2 100644
--- a/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_UpdatesSongDetails.golden
+++ b/smoc.Tests/goldens/NowPlayingViewTest/OnSongChanged_UpdatesSongDetails.golden
@@ -3,17 +3,17 @@ NowPlayingViewTest.OnSongChanged_UpdatesSongDetails_0:
- ┌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┐
- ┆ ?? ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- ┆ ┆
- └╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┘
+
+
+
+
+
+ ??
+
+
+
+
+
OnSongChangedUpdatesSongDetails
Radiohead
diff --git a/smoc/Program.cs b/smoc/Program.cs
index b92c619..0f44ec3 100644
--- a/smoc/Program.cs
+++ b/smoc/Program.cs
@@ -8,7 +8,6 @@
using Smoc.Streaming.Subsonic;
using Smoc.Streaming.YouTubeMusic;
using Smoc.Ui;
-using Smoc.Ui.Drawing;
using Terminal.Gui;
using Terminal.Gui.App;
using Terminal.Gui.Configuration;
@@ -62,9 +61,7 @@ public static async Task Main(string[] args) {
application.Mouse.IsMouseDisabled = true;
VimKeyBindings.AddNavigationKeyBindings(application.Keyboard.KeyBindings);
IStreamingClient streamingClient = CreateStreamingClient();
- var sixelDriver = new SixelDriver(application);
- sixelDriver.Initialize();
- using var window = new MainWindow(streamingClient, sixelDriver);
+ using var window = new MainWindow(streamingClient);
try {
application.Run(window, (e) => {
Logging.Error(e.ToString());
diff --git a/smoc/Ui/Components/SixelImageView.cs b/smoc/Ui/Components/SixelImageView.cs
index 5495ca4..0e2aa2d 100644
--- a/smoc/Ui/Components/SixelImageView.cs
+++ b/smoc/Ui/Components/SixelImageView.cs
@@ -1,8 +1,8 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
-using Terminal.Gui.Drawing;
-using Terminal.Gui.ViewBase;
+using Terminal.Gui.App;
+using Terminal.Gui.Views;
using Color = Terminal.Gui.Drawing.Color;
namespace Smoc.Ui.Components;
@@ -10,18 +10,15 @@ namespace Smoc.Ui.Components;
///
/// A view that renders images using Sixel graphics sequences.
///
-public sealed class SixelImageView : View {
- private readonly IMainWindow _mainWindow;
+public sealed class SixelImageView : ImageView {
private Image? _image;
- private SixelToRender? _sixelToRender;
+ private CancellationTokenSource? _cancellationTokenSource;
///
/// Initializes a new instance of the class.
///
- /// The main window.
/// The initial image to display.
- public SixelImageView(IMainWindow mainWindow, Image? image = null) {
- _mainWindow = mainWindow;
+ public SixelImageView(Image? image = null) {
_image = image;
}
@@ -34,7 +31,7 @@ public void ClearImage() {
}
_image = null;
- _sixelToRender = null;
+ Image = null;
SetNeedsDraw();
}
@@ -44,50 +41,45 @@ public void ClearImage() {
/// The image to display.
public void SetImage(Image image) {
_image = image;
- _sixelToRender = null;
UpdateSixelData();
- SetNeedsDraw();
}
protected override void OnFrameChanged(in System.Drawing.Rectangle frame) {
- base.OnFrameChanged(frame);
UpdateSixelData();
- SetNeedsDraw();
}
- protected override bool OnDrawingContent(DrawContext? context) {
- base.OnDrawingContent(context);
-
- if (_sixelToRender is not null) {
- _mainWindow.SixelDriver.EnqueueSixel(_sixelToRender);
- context?.AddDrawnRectangle(GetRenderableArea());
- return true;
- }
-
- return false;
- }
+ private void UpdateSixelData() {
+ _cancellationTokenSource?.Cancel();
+ _cancellationTokenSource = new CancellationTokenSource();
+
+ var token = _cancellationTokenSource.Token;
+ Task.Run(() => {
+ Color[,]? data = null;
+ try {
+ data = GenerateSixelData();
+ } catch (Exception ex) {
+ Logging.Warning($"Failed to render album art: {ex.Message}");
+ return;
+ }
- private System.Drawing.Rectangle GetRenderableArea() {
- var frame = FrameToScreen();
- return new(
- frame.X + (Margin?.Thickness.Left ?? 0),
- frame.Y + (Margin?.Thickness.Top ?? 0),
- frame.Width - (Margin?.Thickness.Horizontal ?? 0),
- frame.Height - (Margin?.Thickness.Vertical ?? 0));
+ App?.Invoke(() => {
+ if (token.IsCancellationRequested) {
+ return;
+ }
+ Image = data;
+ SetNeedsDraw();
+ });
+ }, token);
}
- private void UpdateSixelData() {
- if (_image is null || !_mainWindow.SixelDriver.IsSupported) {
- return;
+ private Color[,] GenerateSixelData() {
+ if (_image is null || App?.Driver?.SixelSupport is not { IsSupported: true }) {
+ throw new InvalidOperationException("Sixel not supported.");
}
- var boundsRect = GetRenderableArea();
- var resizedImage = _image.Clone(
- i => i.Resize(boundsRect.Width * _mainWindow.SixelDriver.Resolution!.Value.Width, boundsRect.Height * _mainWindow.SixelDriver.Resolution!.Value.Height));
- _sixelToRender = new SixelToRender() {
- SixelData = _mainWindow.SixelDriver.EncodeSixel(ConvertToColorArray(resizedImage)),
- ScreenPosition = new System.Drawing.Point(boundsRect.X, boundsRect.Y)
- };
+ var targetSize = FitImageInViewportInPixels(new(_image.Width, _image.Height));
+ var resizedImage = _image.Clone(i => i.Resize(targetSize.Width, targetSize.Height));
+ return ConvertToColorArray(resizedImage);
}
private static Color[,] ConvertToColorArray(Image image) {
diff --git a/smoc/Ui/Drawing/ISixelDriver.cs b/smoc/Ui/Drawing/ISixelDriver.cs
deleted file mode 100644
index 28577c5..0000000
--- a/smoc/Ui/Drawing/ISixelDriver.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System.Drawing;
-using Terminal.Gui.Drawing;
-using Color = Terminal.Gui.Drawing.Color;
-
-namespace Smoc.Ui.Drawing;
-
-///
-/// Provides an abstraction over Sixel graphics rendering.
-///
-public interface ISixelDriver {
-
- ///
- /// Gets the aspect ratio (height/width) of terminal character cells in pixels.
- ///
- double CellAspectRatio { get; }
-
- ///
- /// Gets a value indicating whether the terminal supports Sixel graphics.
- ///
- bool IsSupported { get; }
-
- ///
- /// Gets the detected pixel resolution of a terminal character cell, or null if
- /// detection has not yet completed.
- ///
- Size? Resolution { get; }
-
- ///
- /// The maximum number of colors that can be included in a sixel image. Defaults
- /// to 256.
- ///
- int MaxPaletteColors { get; }
-
- ///
- /// Initializes the Sixel driver, triggering asynchronous detection of Sixel support
- /// and terminal cell resolution.
- ///
- void Initialize();
-
- ///
- /// Enqueues a Sixel image for rendering in the terminal. If the driver has not yet
- /// finished initializing, the render request is deferred until initialization completes.
- ///
- /// The Sixel render request to enqueue.
- void EnqueueSixel(SixelToRender sixelToRender);
-
- ///
- /// Encodes a two-dimensional array of colors into a Sixel-formatted string.
- ///
- /// A 2D array of colors representing the image to encode.
- /// A Sixel-encoded string representation of the image.
- string EncodeSixel(Color[,] colors);
-}
\ No newline at end of file
diff --git a/smoc/Ui/Drawing/SixelDriver.cs b/smoc/Ui/Drawing/SixelDriver.cs
deleted file mode 100644
index dc2e7fe..0000000
--- a/smoc/Ui/Drawing/SixelDriver.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-namespace Smoc.Ui.Drawing;
-
-using System.Collections.Concurrent;
-using System.Drawing;
-using Terminal.Gui.App;
-using Terminal.Gui.Drawing;
-using Color = Terminal.Gui.Drawing.Color;
-
-///
-/// Standard implementation of .
-///
-public sealed class SixelDriver : ISixelDriver {
- private SixelSupportDetector? _sixelSupportDetector;
- private SixelSupportResult? _sixelSupportResult;
- private readonly IApplication _app;
- private readonly ConcurrentQueue> _sixelInitQueue = new();
-
- ///
- public double CellAspectRatio =>
- _sixelSupportResult?.Resolution.Height / (double?)_sixelSupportResult?.Resolution.Width ?? 2.0;
-
- ///
- public bool IsSupported => _sixelSupportResult?.IsSupported ?? false;
-
- ///
- public Size? Resolution => _sixelSupportResult?.Resolution;
-
- ///
- public int MaxPaletteColors => _sixelSupportResult?.MaxPaletteColors ?? 256;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The application instance to use when rendering.
- public SixelDriver(IApplication app) {
- _app = app;
- }
-
- ///
- public void Initialize() {
- EnsureInitialized();
- }
-
- ///
- public void EnqueueSixel(SixelToRender sixelToRender) {
- if (_sixelSupportResult is null) {
- _sixelInitQueue.Enqueue((driver) => driver.EnqueueSixel(sixelToRender));
- EnsureInitialized();
- } else if (_sixelSupportResult is not null && _sixelSupportResult.IsSupported) {
- if (!_app.Driver!.GetSixels().Contains(sixelToRender)) {
- _app.Driver!.GetSixels().Enqueue(sixelToRender);
- }
- }
- }
-
- ///
- public string EncodeSixel(Color[,] colors) {
- var encoder = new SixelEncoder();
- encoder.Quantizer.MaxColors = Math.Min(encoder.Quantizer.MaxColors, MaxPaletteColors);
- return encoder.EncodeSixel(colors);
- }
-
- private void EnsureInitialized() {
- if (_sixelSupportDetector is not null) {
- return;
- }
- _sixelSupportDetector = new SixelSupportDetector(_app.Driver);
- _sixelSupportDetector.Detect((result) => {
- _app.Invoke(() => {
- _sixelSupportResult = result;
- while (_sixelInitQueue.TryDequeue(out var action)) {
- action(this);
- }
- });
- });
- }
-}
\ No newline at end of file
diff --git a/smoc/Ui/IMainWindow.cs b/smoc/Ui/IMainWindow.cs
index 78122f9..5a217b8 100644
--- a/smoc/Ui/IMainWindow.cs
+++ b/smoc/Ui/IMainWindow.cs
@@ -1,4 +1,3 @@
-using Smoc.Ui.Drawing;
using Smoc.Ui.Models;
using Terminal.Gui.App;
@@ -13,11 +12,6 @@ public interface IMainWindow {
///
IApplication? App { get; }
- ///
- /// Gets the sixel driver.
- ///
- ISixelDriver SixelDriver { get; }
-
///
/// Changes the application's current mode (view).
///
diff --git a/smoc/Ui/MainWindow.cs b/smoc/Ui/MainWindow.cs
index d77eb99..2ffba35 100644
--- a/smoc/Ui/MainWindow.cs
+++ b/smoc/Ui/MainWindow.cs
@@ -4,7 +4,6 @@
using Smoc.Services.Audio.SoundFlow;
using Smoc.Services.Streaming;
using Smoc.Streaming;
-using Smoc.Ui.Drawing;
using Smoc.Ui.Models;
using Terminal.Gui.Input;
using Terminal.Gui.ViewBase;
@@ -23,25 +22,20 @@ public sealed class MainWindow : Runnable, IMainWindow {
private readonly IPlaybackQueueService _playbackQueueService;
private readonly CommandService _commandService;
private readonly IPlaybackTrackingService _playbackTrackingService;
- private readonly ISixelDriver _sixelDriver;
private Mode? _currentMode;
private View? _preCommandFocusedView;
private Mode? _preCommandMode;
- ///
- public ISixelDriver SixelDriver => _sixelDriver;
-
///
/// Initializes a new instance of the class.
///
/// The initialized streaming client.
- public MainWindow(IStreamingClient streamingClient, ISixelDriver sixelDriver) {
+ public MainWindow(IStreamingClient streamingClient) {
Width = Dim.Fill();
Height = Dim.Fill();
CanFocus = true;
- _sixelDriver = sixelDriver;
_playbackQueueService = StandardPlaybackQueueService.UsingAudioService(this, streamingClient);
_playbackTrackingService = new StreamingListenHistoryService(
streamingClient,
diff --git a/smoc/Ui/NowPlayingBar.cs b/smoc/Ui/NowPlayingBar.cs
index 43afeef..c1658e7 100644
--- a/smoc/Ui/NowPlayingBar.cs
+++ b/smoc/Ui/NowPlayingBar.cs
@@ -56,16 +56,19 @@ public NowPlayingBar(IMainWindow mainWindow, IPlaybackQueueService playbackQueue
Padding!.Thickness = new Thickness(0, 0, 1, 0);
CanFocus = false;
- _albumArtView = new SixelImageView(_mainWindow) {
+ _albumArtView = new SixelImageView() {
X = Pos.Absolute(1),
Y = Pos.Absolute(0),
Height = Dim.Fill(),
Width = Dim.Func((view) => {
int height = view!.Frame.Height;
- return (int)Math.Round(height * _mainWindow.SixelDriver.CellAspectRatio);
+ var resolution = App?.Driver?.SixelSupport?.Resolution ?? new System.Drawing.Size(1, 2);
+ return (int)Math.Round(height * ((double)resolution.Height / resolution.Width));
}, this) + 1,
+ SixelEncoder = new SixelEncoder(),
BorderStyle = LineStyle.Dashed,
TextAlignment = Alignment.Center,
+ VerticalTextAlignment = Alignment.Center,
Text = "??"
};
_albumArtView.Margin!.Thickness = new Thickness(0, 0, 1, 0);
@@ -200,6 +203,7 @@ private async void OnSongChanged(object? sender, Song? song) {
// Only bother downloading the album art if it has changed.
if (!song.Album.Covers.Any()) {
_albumArtView.ClearImage();
+ _albumArtView.BorderStyle = LineStyle.Dashed;
} else if (_currentAlbum != song.Album) {
_currentAlbum = song.Album;
_albumArtCancellationTokenSource?.Cancel();
@@ -209,6 +213,7 @@ private async void OnSongChanged(object? sender, Song? song) {
var image = await _streamingClient.GetAlbumArtAsync(song.Album, (covers) => covers.OrderBy(c => c.Width).First(), token);
Logging.Debug($"Album art loaded: {song.Title}");
token.ThrowIfCancellationRequested();
+ _albumArtView.BorderStyle = LineStyle.None;
_albumArtView.SetImage(image);
} catch (OperationCanceledException) {
Logging.Debug($"Album art load cancelled: {song.Title}");
@@ -224,6 +229,7 @@ private void Reset() {
_positionLabel.Text = "--:--";
_durationLabel.Text = "--:--";
_albumArtView.ClearImage();
+ _albumArtView.BorderStyle = LineStyle.Dashed;
_volumeLabel.Text = string.Format(Messages.VOLUME, (int)Math.Round(_playbackQueueService.Volume * 100));
_progressBar.Fraction = 0.0f;
}
diff --git a/smoc/Ui/NowPlayingView.cs b/smoc/Ui/NowPlayingView.cs
index 040ea09..3e5589b 100644
--- a/smoc/Ui/NowPlayingView.cs
+++ b/smoc/Ui/NowPlayingView.cs
@@ -53,22 +53,26 @@ public NowPlayingView(IMainWindow mainWindow, CommandService commandService, IPl
_streamingClient = streamingClient;
Width = Dim.Fill();
Height = Dim.Fill();
- _albumArtView = new SixelImageView(_mainWindow) {
+ _albumArtView = new SixelImageView() {
X = Pos.Center(),
Y = Pos.Center() - Pos.Percent(10),
+ SixelEncoder = new SixelEncoder(),
Height = Dim.Func((view) => {
float maxHeight = view!.Frame.Height * _albumArtMaxViewportPercent;
float maxWidth = view!.Frame.Width * _albumArtMaxViewportPercent;
- return (int)Math.Round(Math.Min(maxHeight, maxWidth / _mainWindow.SixelDriver.CellAspectRatio));
+ var resolution = App?.Driver?.SixelSupport?.Resolution ?? new System.Drawing.Size(1, 2);
+ return (int)Math.Round(Math.Min(maxHeight, maxWidth / ((double)resolution.Height / resolution.Width)));
}, this),
Width = Dim.Func((view) => {
float maxHeight = view!.Frame.Height * _albumArtMaxViewportPercent;
float maxWidth = view!.Frame.Width * _albumArtMaxViewportPercent;
- double height = Math.Min(maxHeight, maxWidth / _mainWindow.SixelDriver.CellAspectRatio);
- return (int)Math.Round(height * _mainWindow.SixelDriver.CellAspectRatio);
+ var resolution = App?.Driver?.SixelSupport?.Resolution ?? new System.Drawing.Size(1, 2);
+ double height = Math.Min(maxHeight, maxWidth / ((double)resolution.Height / resolution.Width));
+ return (int)Math.Round(height * ((double)resolution.Height / resolution.Width));
}, this),
BorderStyle = LineStyle.Dashed,
TextAlignment = Alignment.Center,
+ VerticalTextAlignment = Alignment.Center,
Text = "??"
};
_albumArtView.Margin!.Thickness = new Thickness(0, 0, 1, 1);
@@ -140,6 +144,7 @@ private async void OnSongChanged(object? sender, Song? song) {
// Only bother downloading the album art if it has changed.
if (!song.Album.Covers.Any()) {
_albumArtView.ClearImage();
+ _albumArtView.BorderStyle = LineStyle.Dashed;
} else if (_currentAlbum != song.Album) {
_currentAlbum = song.Album;
_albumArtCancellationTokenSource?.Cancel();
@@ -149,6 +154,7 @@ private async void OnSongChanged(object? sender, Song? song) {
var image = await _streamingClient.GetAlbumArtAsync(song.Album, (covers) => covers.OrderByDescending(c => c.Width).First(), token);
Logging.Debug($"Album art loaded: {song.Title}");
token.ThrowIfCancellationRequested();
+ _albumArtView.BorderStyle = LineStyle.None;
_albumArtView.SetImage(image);
} catch (OperationCanceledException) {
Logging.Debug($"Album art load cancelled: {song.Title}");
@@ -175,6 +181,7 @@ private void Reset() {
_positionLabel.Text = "--:--";
_durationLabel.Text = "--:--";
_albumArtView.ClearImage();
+ _albumArtView.BorderStyle = LineStyle.Dashed;
_progressBar.Fraction = 0.0f;
}
}