diff --git a/Cargo.toml b/Cargo.toml index 86fba5b..7753b6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ ordered-float = { version = "3.9.0", features = ["serde"] } # tui crossterm = "0.26.1" -ratatui = { version = "0.22.0", features = ["all-widgets"] } +ratatui = { version = "0.23.0", features = ["all-widgets"] } image = { version = "0.24.7", default-features = false, features = [ "png", "jpeg", diff --git a/src/decoder.rs b/src/decoder.rs index 8d44974..99accfa 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -193,7 +193,11 @@ where standard_tags.insert( StandardTagKey::ReplayGainTrackGain, - Value::Float((gain + peak) as f64 / 2.0), + Value::Float(gain as f64), + ); + standard_tags.insert( + StandardTagKey::ReplayGainTrackPeak, + Value::Float(peak as f64), ); } diff --git a/src/main.rs b/src/main.rs index 2ee37cf..fec8b96 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use std::{ }; use cache::Cache; -use log::{trace, warn, LevelFilter}; +use log::{info, trace, warn, LevelFilter}; use player::Player; use simplelog::{CombinedLogger, WriteLogger}; @@ -84,8 +84,12 @@ fn main() { }); let mut cache = if *config != old_config { - trace!("config changed, rebuilding"); - Cache::build_from_config(&config) + info!("config changed, rebuilding"); + let cache = Cache::build_from_config(&config); + cache + .save(&config) + .unwrap_or_else(|e| warn!("Failed to save cache {e:?}")); + cache } else { cache }; diff --git a/src/player.rs b/src/player.rs index b50b19e..6883ceb 100644 --- a/src/player.rs +++ b/src/player.rs @@ -2,7 +2,7 @@ use cpal::{ traits::{DeviceTrait, HostTrait, StreamTrait}, Device, OutputCallbackInfo, StreamConfig, }; -use log::{debug, error, trace, warn}; +use log::{debug, error, info, trace, warn}; use souvlaki::{MediaControlEvent, MediaControls, MediaMetadata, MediaPlayback, PlatformConfig}; use symphonia::core::{ audio::SignalSpec, @@ -207,10 +207,11 @@ impl Player { let (command_tx, command_rx) = std::sync::mpsc::sync_channel::(1); + let buffer_size = signal_spec.rate * 2; let stream_config = StreamConfig { channels: signal_spec.channels.count() as u16, sample_rate: cpal::SampleRate(signal_spec.rate), - buffer_size: cpal::BufferSize::Fixed(signal_spec.rate * 2), + buffer_size: cpal::BufferSize::Fixed(buffer_size), }; trace!("play: stream_config: {:?}", stream_config); @@ -218,6 +219,7 @@ impl Player { let arc2 = arc.clone(); let arc3 = arc.clone(); + let signal_spec = signal_spec.clone(); let thread = std::thread::spawn(move || { trace!("locking player"); let player = arc.lock().expect("Failed to lock player"); @@ -236,6 +238,14 @@ impl Player { Err(e) => { debug!("Failed to receive sample, sender disconnected {:?}", e); + let duration = Duration::from_secs_f32( + buffer_size as f32 + / (signal_spec.channels.bits() * signal_spec.rate) + as f32, + ); + info!("Sleeping for {:?} to finish song", duration); + std::thread::sleep(duration); + { trace!("locking player"); let mut player = @@ -264,7 +274,10 @@ impl Player { .. }) = player.current.as_mut() { - *duration = Duration::from_secs_f32(n as f32 / (2.0 * 48_000.0)); + *duration = Duration::from_secs_f32( + n as f32 + / (signal_spec.channels.bits() * signal_spec.rate) as f32, + ); } } diff --git a/src/tui/status.rs b/src/tui/status.rs index 2287f15..eb97e82 100644 --- a/src/tui/status.rs +++ b/src/tui/status.rs @@ -39,31 +39,43 @@ impl Tui for Status { trace!("locking player"); let playing = Paragraph::new( - if let Some((song, _)) = self.player.lock().unwrap().current() { + if let Some((song, path)) = self.player.lock().unwrap().current() { let title = song .standard_tags .get(&StandardTagKey::TrackTitle) .map(|s| s.to_string()) + .or(path + .components() + .last() + .map(|s| s.as_os_str().to_string_lossy().to_string())) .unwrap_or(UNKNOWN_STRING.to_string()); + let artist = song .standard_tags .get(&StandardTagKey::Artist) - .map(|s| s.to_string()) - .unwrap_or(UNKNOWN_STRING.to_string()); + .map(|s| s.to_string()); - Line::from(vec![ - Span::from(" "), - Span::from(artist) - .fg(Color::LightYellow) - .add_modifier(ratatui::style::Modifier::BOLD), - Span::from(" - ").fg(Color::White), + let mut elems = vec![Span::from(" ")]; + + if let Some(artist) = artist { + elems.push( + Span::from(artist) + .fg(Color::LightYellow) + .add_modifier(ratatui::style::Modifier::BOLD), + ); + elems.push(Span::from(" - ").fg(Color::White)); + } + + elems.extend([ Span::from(title) .fg(Color::LightYellow) .add_modifier(ratatui::style::Modifier::BOLD), Span::from(format!(" ({})", format_duration(song.duration))) .fg(Color::LightGreen), Span::from(" "), - ]) + ]); + + Line::from(elems) } else { Line::from(vec![ Span::from(" - ").add_modifier(ratatui::style::Modifier::BOLD)