diff --git a/src/main.rs b/src/main.rs index b867276..1816ee8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ -use std::cell::Cell; +use std::collections::VecDeque; use std::fs::File; -use std::io::stdout; +use std::io::{stdout, Write}; use std::path::{Path, PathBuf}; use std::process::exit; use std::sync::mpsc::{Receiver, Sender}; @@ -12,13 +12,13 @@ use clap::{Parser, Subcommand}; use cpal::traits::{DeviceTrait, StreamTrait}; use cpal::{self, traits::HostTrait}; use cpal::{OutputCallbackInfo, StreamConfig}; -use crossterm::cursor::{Hide, MoveTo, MoveToColumn, MoveToNextLine, Show}; +use crossterm::cursor::{Hide, MoveTo, MoveToColumn, MoveToNextLine, MoveToRow, Show}; use crossterm::event::{Event, KeyCode, KeyModifiers, MediaKeyCode}; -use crossterm::execute; use crossterm::style::{Print, PrintStyledContent, Stylize}; use crossterm::terminal::{ - disable_raw_mode, enable_raw_mode, size, Clear, ClearType, EnterAlternateScreen, ScrollUp, + disable_raw_mode, enable_raw_mode, size, Clear, ClearType, EnterAlternateScreen, }; +use crossterm::{execute, queue}; use minimp3::Decoder; use rand::{seq::SliceRandom, thread_rng}; use serde::{Deserialize, Serialize}; @@ -204,8 +204,9 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { let mut stdout = stdout(); execute!(stdout, Hide, EnterAlternateScreen).unwrap(); - let (mut _terminal_columns, terminal_rows) = size().unwrap(); - let terminal_rows = Arc::new(Cell::new(terminal_rows)); + let (terminal_columns, terminal_rows) = size().unwrap(); + let terminal_rows = Arc::new(FairMutex::new(terminal_rows)); + let terminal_columns = Arc::new(FairMutex::new(terminal_columns)); let (input_tx, input_rx): (Sender, Receiver) = mpsc::channel(); @@ -257,6 +258,8 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { let mp3_channels = Arc::clone(&mp3_channels); let pending_movement = Arc::clone(&pending_movement); let sample_rate = Arc::clone(&sample_rate); + let terminal_columns = Arc::clone(&terminal_columns); + let terminal_rows = Arc::clone(&terminal_rows); let playback_speed = Arc::clone(&playback_speed); device .build_output_stream( @@ -317,6 +320,27 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { } *idx += *playback_speed.read().unwrap() * mp3_channels; + + { + let mut stdout = std::io::stdout().lock(); + + let status = format!( + "{} / {} {:.1}%", + *idx, + buf.len(), + 100f64 * *idx as f64 / buf.len() as f64 + ); + let padding = + " ".repeat(*terminal_columns.lock() as usize - status.len()); + + execute!( + stdout, + MoveTo(0, *terminal_rows.lock()), + Print(status), + Print(padding) + ) + .unwrap(); + } } }, |err| { @@ -346,8 +370,7 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { execute!( stdout, - MoveToNextLine(1), - MoveToColumn(0), + MoveTo(0, 2), Print("šŸ”Š"), Print(path.as_ref().unwrap().display()) ) @@ -383,13 +406,7 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { } } } else { - execute!( - stdout, - MoveToNextLine(1), - MoveToColumn(0), - Print("\tšŸ—ƒ Annotations Found") - ) - .unwrap(); + execute!(stdout, MoveTo(0, 2), Print("\tšŸ—ƒ Annotations Found")).unwrap(); } } else { quit(); @@ -438,22 +455,39 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { ) .unwrap(); - // The number of log lines we've written in total - let mut log_line = 0usize; + let mut log_lines: VecDeque = VecDeque::with_capacity(*terminal_rows.lock() as usize); // Add a line to the log area let mut log = { + let terminal_columns = Arc::clone(&terminal_columns); let terminal_rows = Arc::clone(&terminal_rows); move |s: &str| { - log_line += 1; + log_lines.push_back(s.to_string()); - if log_line > terminal_rows.get() as usize { - execute!(stdout, ScrollUp(1)).unwrap(); - } else { - execute!(stdout, MoveToNextLine(1)).unwrap(); + while log_lines.len() > *terminal_rows.lock() as usize - 10 { + log_lines.pop_front().unwrap(); } - execute!(stdout, MoveToColumn(0), Print(s)).unwrap(); + let mut stdout = stdout.lock(); + + queue!(stdout, MoveToRow(5)).unwrap(); + + for line in log_lines.iter() { + let right_pad_len = *terminal_columns.lock() as usize - line.len(); + + let padding = " ".repeat(right_pad_len); + + queue!( + stdout, + MoveToColumn(0), + Print(line), + Print(padding), + MoveToNextLine(1) + ) + .unwrap(); + } + + stdout.flush().unwrap(); } }; @@ -552,8 +586,8 @@ fn annotate(mut path: Vec, initial_buffer_size: usize) { quit(); } Command::ResizeTerminal(columns, rows) => { - _terminal_columns = columns; - terminal_rows.set(rows); + *terminal_columns.lock() = columns; + *terminal_rows.lock() = rows; } Command::TogglePlaybackSpeed => { let next = match *playback_speed.read().unwrap() {