Skip to content

Commit

Permalink
upd - prt - Made the CLI resizable
Browse files Browse the repository at this point in the history
---

Using Terminaux 2.0's brand new feature, Screen, we've managed to make the CLI resizable.

---

Type: upd
Breaking: False
Doc Required: False
Part: 2/2
  • Loading branch information
AptiviCEO committed Dec 14, 2023
1 parent b403d72 commit d51145e
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 50 deletions.
2 changes: 2 additions & 0 deletions BassBoom.Cli/BassBoomCli.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using BassBoom.Cli.CliBase;
using System;
using System.IO;
using Terminaux.Base;
using Terminaux.Writer.ConsoleWriters;

namespace BassBoom.Cli
Expand Down Expand Up @@ -48,6 +49,7 @@ static int Main(string[] args)
}

// Now, open an interactive TUI
ConsoleResizeListener.StartResizeListener();
Player.PlayerLoop();
}
catch (Exception ex)
Expand Down
140 changes: 100 additions & 40 deletions BassBoom.Cli/CliBase/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
using System.Text;
using System.Threading;
using Terminaux.Base;
using Terminaux.Base.Buffered;
using Terminaux.Colors;
using Terminaux.Inputs;
using Terminaux.Inputs.Styles.Infobox;
Expand Down Expand Up @@ -57,6 +58,7 @@ internal static class Player
internal static bool advance = false;
internal static bool populate = true;
internal static bool paused = false;
internal static bool failedToPlay = false;
internal static string cachedLyric = "";
internal static readonly List<string> musicFiles = [];
internal static readonly List<CachedSongInfo> cachedInfos = [];
Expand All @@ -65,29 +67,51 @@ public static void PlayerLoop()
{
InitBasolia.Init();
volume = PlaybackTools.GetVolume().baseLinear;
exiting = false;
rerender = true;
paused = false;
populate = true;
advance = false;

// Populate the screen
Screen playerScreen = new();
ScreenTools.SetCurrent(playerScreen);

// First, clear the screen to draw our TUI
while (!exiting)
{
ScreenPart screenPart = new();
Thread.Sleep(1);
try
{
// Redraw if necessary
if (ConsoleResizeListener.WasResized(true))
rerender = true;
bool wasRerendered = rerender;
if (rerender)
{
rerender = false;
HandleDraw();
screenPart.AddDynamicText(HandleDraw);
}

// Current duration
position = FileTools.IsOpened ? PlaybackPositioningTools.GetCurrentDuration() : 0;
var posSpan = FileTools.IsOpened ? PlaybackPositioningTools.GetCurrentDurationSpan() : new();
ProgressBarColor.WriteProgress(100 * (position / (double)total), 2, ConsoleWrapper.WindowHeight - 8, 6, ConsoleColors.DarkYellow, ConsoleColors.White);
TextWriterWhereColor.WriteWhere($"{posSpan} / {totalSpan}", 3, ConsoleWrapper.WindowHeight - 9);
TextWriterWhereColor.WriteWhere($"Seek: {PlayerControls.seekRate:0.00} | Vol: {volume:0.00}", ConsoleWrapper.WindowWidth - $"Seek: {PlayerControls.seekRate:0.00} | Vol: {volume:0.00}".Length - 3, ConsoleWrapper.WindowHeight - 9);
string indicator =
$"Seek: {PlayerControls.seekRate:0.00} | " +
$"Volume: {volume:0.00}";
screenPart.AddDynamicText(() =>
{
var buffer = new StringBuilder();
buffer.Append(
ProgressBarColor.RenderProgress(100 * (position / (double)total), 2, ConsoleWrapper.WindowHeight - 8, 3, 3, ConsoleColors.DarkYellow, ConsoleColors.Gray, ConsoleColors.Black) +
TextWriterWhereColor.RenderWhere($"{posSpan} / {totalSpan}", 3, ConsoleWrapper.WindowHeight - 9, ConsoleColors.White, ConsoleColors.Black) +
TextWriterWhereColor.RenderWhere(indicator, ConsoleWrapper.WindowWidth - indicator.Length - 3, ConsoleWrapper.WindowHeight - 9, ConsoleColors.White, ConsoleColors.Black)
);
return buffer.ToString();
});

// Check the mode
// Get the lyrics
if (PlaybackTools.Playing)
{
// Print the lyrics, if any
Expand All @@ -97,31 +121,45 @@ public static void PlayerLoop()
if (current != cachedLyric || wasRerendered)
{
cachedLyric = current;
TextWriterWhereColor.WriteWhere(ConsoleExtensions.GetClearLineToRightSequence(), 0, ConsoleWrapper.WindowHeight - 10);
CenteredTextColor.WriteCentered(ConsoleWrapper.WindowHeight - 10, lyricInstance.GetLastLineCurrent());
screenPart.AddDynamicText(() =>
{
var buffer = new StringBuilder();
buffer.Append(
TextWriterWhereColor.RenderWhere(ConsoleExtensions.GetClearLineToRightSequence(), 0, ConsoleWrapper.WindowHeight - 10, ConsoleColors.White, ConsoleColors.Black) +
CenteredTextColor.RenderCentered(ConsoleWrapper.WindowHeight - 10, lyricInstance.GetLastLineCurrent(), ConsoleColors.White, ConsoleColors.Black)
);
return buffer.ToString();
});
}
}
else
cachedLyric = "";

// Wait for any keystroke asynchronously
if (ConsoleWrapper.KeyAvailable)
{
var keystroke = Input.DetectKeypress();
HandleKeypressPlayMode(keystroke);
}
}
else
{
TextWriterWhereColor.WriteWhere(ConsoleExtensions.GetClearLineToRightSequence(), 0, ConsoleWrapper.WindowHeight - 10);
cachedLyric = "";

// Wait for any keystroke
if (ConsoleWrapper.KeyAvailable)
screenPart.AddDynamicText(() =>
{
var keystroke = Input.DetectKeypress();
var buffer = new StringBuilder();
buffer.Append(
TextWriterWhereColor.RenderWhere(ConsoleExtensions.GetClearLineToRightSequence(), 0, ConsoleWrapper.WindowHeight - 10, ConsoleColors.White, ConsoleColors.Black)
);
return buffer.ToString();
});
}

// Render the buffer
playerScreen.AddBufferedPart("BassBoom Player", screenPart);
ScreenTools.Render();

// Handle the keystroke
if (ConsoleWrapper.KeyAvailable)
{
var keystroke = Input.DetectKeypress();
if (PlaybackTools.Playing)
HandleKeypressPlayMode(keystroke);
else
HandleKeypressIdleMode(keystroke);
}
}
}
catch (BasoliaException bex)
Expand All @@ -145,6 +183,7 @@ public static void PlayerLoop()
InfoBoxColor.WriteInfoBox("There's an unknown error when trying to process the music file.\n\n" + ex.Message);
rerender = true;
}
playerScreen.RemoveBufferedParts();
}

// Close the file if open
Expand All @@ -154,6 +193,7 @@ public static void PlayerLoop()
// Restore state
ConsoleWrapper.CursorVisible = true;
ColorTools.LoadBack();
ScreenTools.UnsetCurrent(playerScreen);
}

private static void HandleKeypressIdleMode(ConsoleKeyInfo keystroke)
Expand Down Expand Up @@ -275,52 +315,71 @@ private static void HandleKeypressPlayMode(ConsoleKeyInfo keystroke)

private static void HandlePlay()
{
foreach (var musicFile in musicFiles.Skip(currentSong - 1))
try
{
if (!advance || exiting)
return;
else
populate = true;
currentSong = musicFiles.IndexOf(musicFile) + 1;
PlayerControls.PopulateMusicFileInfo(musicFile);
PlayerControls.RenderSongName(musicFile);
if (paused)
foreach (var musicFile in musicFiles.Skip(currentSong - 1))
{
paused = false;
PlaybackPositioningTools.SeekToFrame(position);
if (!advance || exiting)
return;
else
populate = true;
currentSong = musicFiles.IndexOf(musicFile) + 1;
PlayerControls.PopulateMusicFileInfo(musicFile);
TextWriterColor.WritePlain(PlayerControls.RenderSongName(musicFile), false);
if (paused)
{
paused = false;
PlaybackPositioningTools.SeekToFrame(position);
}
PlaybackTools.Play();
}
PlaybackTools.Play();
}
catch (Exception ex)
{
InfoBoxColor.WriteInfoBox($"Playback failure: {ex.Message}");
failedToPlay = true;
}
finally
{
lyricInstance = null;
rerender = true;
}
}

private static void HandleDraw()
private static string HandleDraw()
{
// Prepare things
var drawn = new StringBuilder();
ConsoleWrapper.CursorVisible = false;
ColorTools.LoadBack();

// First, print the keystrokes
string keystrokes = "[SPACE] Play/Pause - [ESC] Stop - [Q] Exit - [H] Help";
CenteredTextColor.WriteCentered(ConsoleWrapper.WindowHeight - 2, keystrokes);
string keystrokes =
"[SPACE] Play/Pause" +
" - [ESC] Stop" +
" - [Q] Exit" +
" - [H] Help";
drawn.Append(CenteredTextColor.RenderCentered(ConsoleWrapper.WindowHeight - 2, keystrokes));

// Print the separator and the music file info
string separator = new('=', ConsoleWrapper.WindowWidth);
CenteredTextColor.WriteCentered(ConsoleWrapper.WindowHeight - 4, separator);
drawn.Append(CenteredTextColor.RenderCentered(ConsoleWrapper.WindowHeight - 4, separator));

// Write powered by...
drawn.Append(TextWriterWhereColor.RenderWherePlain($"[ Powered by BassBoom ]", 2, ConsoleWrapper.WindowHeight - 4));

// In case we have no songs in the playlist...
if (musicFiles.Count == 0)
{
int height = (ConsoleWrapper.WindowHeight - 10) / 2;
CenteredTextColor.WriteCentered(height, "Press A to insert a single song to the playlist, or S to insert the whole music library.");
return;
drawn.Append(CenteredTextColor.RenderCentered(height, "Press 'A' to insert a single song to the playlist, or 'S' to insert the whole music library."));
return drawn.ToString();
}

// Populate music file info, as necessary
if (populate)
PlayerControls.PopulateMusicFileInfo(musicFiles[currentSong - 1]);
PlayerControls.RenderSongName(musicFiles[currentSong - 1]);
drawn.Append(PlayerControls.RenderSongName(musicFiles[currentSong - 1]));

// Now, print the list of songs.
int startPos = 3;
Expand Down Expand Up @@ -355,7 +414,8 @@ private static void HandleDraw()
new string(' ', ConsoleWrapper.WindowWidth - finalEntry.Length)
);
}
TextWriterColor.WritePlain(playlist.ToString());
drawn.Append(playlist);
return drawn.ToString();
}
}
}
21 changes: 11 additions & 10 deletions BassBoom.Cli/CliBase/PlayerControls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
using System.Text;
using System.Threading;
using Terminaux.Base;
using Terminaux.Colors;
using Terminaux.Inputs.Styles.Infobox;
using Terminaux.Writer.ConsoleWriters;
using Terminaux.Writer.FancyWriters;
Expand Down Expand Up @@ -100,7 +101,8 @@ internal static void Play()
Player.advance = true;
Player.rerender = true;
Player.playerThread.Start();
SpinWait.SpinUntil(() => PlaybackTools.Playing);
SpinWait.SpinUntil(() => PlaybackTools.Playing || Player.failedToPlay);
Player.failedToPlay = false;
}

internal static void Pause()
Expand Down Expand Up @@ -154,7 +156,7 @@ internal static void PromptForAddSong()
PlaybackPositioningTools.SeekToFrame(currentPos);
}
else
InfoBoxColor.WriteInfoBox($"File \"{path}\" doesn't exist.");
InfoBoxColor.WriteInfoBox("File \"{0}\" doesn't exist.", path);
Player.rerender = true;
}

Expand Down Expand Up @@ -200,7 +202,7 @@ internal static bool TryOpenMusicFile(string musicPath)
}
catch (Exception ex)
{
InfoBoxColor.WriteInfoBox("Can't open {0}: {1}", true, vars: new[] { musicPath, ex.Message });
InfoBoxColor.WriteInfoBox("Can't open {0}: {1}", true, musicPath, ex.Message);
}
return false;
}
Expand Down Expand Up @@ -230,7 +232,7 @@ internal static void PopulateMusicFileInfo(string musicPath)
else
{
Player.rerender = true;
InfoBoxColor.WriteInfoBox("Loading BassBoom to open {0}...", false, vars: musicPath);
InfoBoxColor.WriteInfoBox("Loading BassBoom to open {0}...", false, musicPath);
Player.total = AudioInfoTools.GetDuration(true);
Player.totalSpan = AudioInfoTools.GetDurationSpanFromSamples(Player.total);
Player.formatInfo = FormatTools.GetFormatInfo();
Expand All @@ -247,14 +249,13 @@ internal static void PopulateMusicFileInfo(string musicPath)
Player.musicFiles.Add(musicPath);
}

internal static void RenderSongName(string musicPath)
internal static string RenderSongName(string musicPath)
{
// Render the song name
var (musicName, musicArtist, _) = GetMusicNameArtistGenre(musicPath);

// Print the music name
Console.Title = $"BassBoom CLI - Basolia v0.0.3 - Alpha 3 • {musicArtist} - {musicName}";
CenteredTextColor.WriteCentered(1, $"Now playing: {musicArtist} - {musicName}");
return CenteredTextColor.RenderCentered(1, "Now playing: {0} - {1}", ConsoleColors.White, ConsoleColors.Black, musicArtist, musicName);
}

internal static (string musicName, string musicArtist, string musicGenre) GetMusicNameArtistGenre(string musicPath)
Expand Down Expand Up @@ -302,15 +303,15 @@ internal static void OpenLyrics(string musicPath)
string lyricsPath = Path.GetDirectoryName(musicPath) + "/" + Path.GetFileNameWithoutExtension(musicPath) + ".lrc";
try
{
InfoBoxColor.WriteInfoBox("Trying to open lyrics file {0}...", false, vars: lyricsPath);
InfoBoxColor.WriteInfoBox("Trying to open lyrics file {0}...", false, lyricsPath);
if (File.Exists(lyricsPath))
Player.lyricInstance = LyricReader.GetLyrics(lyricsPath);
else
Player.lyricInstance = null;
}
catch (Exception ex)
{
InfoBoxColor.WriteInfoBox("Can't open lyrics file {0}... {1}", vars: new[] { lyricsPath, ex.Message });
InfoBoxColor.WriteInfoBox("Can't open lyrics file {0}... {1}", lyricsPath, ex.Message);
}
}

Expand Down Expand Up @@ -406,7 +407,7 @@ Song info
Comment: {{(!string.IsNullOrEmpty(Player.managedV2.Comment) ? Player.managedV2.Comment : !string.IsNullOrEmpty(Player.managedV1.Comment) ? Player.managedV1.Comment : "")}}
Duration: {{Player.totalSpan}}
Lyrics: {{(Player.lyricInstance is not null ? $"{Player.lyricInstance.Lines.Count} lines" : "No lyrics")}}
Layer info
==========
Expand Down

0 comments on commit d51145e

Please sign in to comment.