From 32cb6e70d3607f92dede13d6e42972f9131119a4 Mon Sep 17 00:00:00 2001 From: Henrik Friedrichsen Date: Thu, 8 Apr 2021 22:13:07 +0200 Subject: [PATCH] Show tracks + duration of album, playlist, queue Stats are in the top right Fixes #475 --- src/main.rs | 1 + src/traits.rs | 8 ++++++++ src/ui/album.rs | 11 +++++++++++ src/ui/layout.rs | 5 +++++ src/ui/playlist.rs | 14 ++++++++++++++ src/ui/queue.rs | 23 +++++++++++++++++++++++ src/utils.rs | 21 +++++++++++++++++++++ 7 files changed, 83 insertions(+) create mode 100644 src/utils.rs diff --git a/src/main.rs b/src/main.rs index 4260b65..f95d5ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -69,6 +69,7 @@ mod theme; mod track; mod traits; mod ui; +mod utils; #[cfg(feature = "mpris")] mod mpris; diff --git a/src/traits.rs b/src/traits.rs index 3ee1d83..b31c5e2 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -55,6 +55,10 @@ pub trait ViewExt: View { "".into() } + fn title_sub(&self) -> String { + "".into() + } + fn on_leave(&self) {} fn on_command(&mut self, _s: &mut Cursive, _cmd: &Command) -> Result { @@ -67,6 +71,10 @@ impl ViewExt for NamedView { self.with_view(|v| v.title()).unwrap_or_default() } + fn title_sub(&self) -> String { + self.with_view(|v| v.title_sub()).unwrap_or_default() + } + fn on_leave(&self) { self.with_view(|v| v.on_leave()); } diff --git a/src/ui/album.rs b/src/ui/album.rs index baccb49..349cbc8 100644 --- a/src/ui/album.rs +++ b/src/ui/album.rs @@ -66,6 +66,17 @@ impl ViewExt for AlbumView { format!("{} ({})", self.album.title, self.album.year) } + fn title_sub(&self) -> String { + if let Some(tracks) = &self.album.tracks { + let duration_secs: u64 = tracks.iter().map(|t| t.duration as u64 / 1000).sum(); + let duration = std::time::Duration::from_secs(duration_secs); + let duration_str = crate::utils::format_duration(&duration); + format!("{} tracks, {}", tracks.len(), duration_str) + } else { + "".to_string() + } + } + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { self.tabs.on_command(s, cmd) } diff --git a/src/ui/layout.rs b/src/ui/layout.rs index bdd683b..8a45197 100644 --- a/src/ui/layout.rs +++ b/src/ui/layout.rs @@ -219,6 +219,11 @@ impl View for Layout { printer.print((offset, 0), &view.title()); }); + printer.with_color(ColorStyle::secondary(), |printer| { + let offset = HAlign::Right.get_offset(view.title_sub().width(), printer.size.x); + printer.print((offset, 0), &view.title_sub()); + }); + // screen content let printer = &printer .offset((0, 1)) diff --git a/src/ui/playlist.rs b/src/ui/playlist.rs index c213b9b..30c39cb 100644 --- a/src/ui/playlist.rs +++ b/src/ui/playlist.rs @@ -62,6 +62,20 @@ impl ViewExt for PlaylistView { self.playlist.name.clone() } + fn title_sub(&self) -> String { + if let Some(tracks) = self.playlist.tracks.as_ref() { + let duration_secs = tracks.iter().map(|p| p.duration as u64 / 1000).sum(); + let duration = std::time::Duration::from_secs(duration_secs); + format!( + "{} tracks, {}", + tracks.len(), + crate::utils::format_duration(&duration) + ) + } else { + "".to_string() + } + } + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { if let Command::Delete = cmd { let pos = self.list.get_selected_index(); diff --git a/src/ui/queue.rs b/src/ui/queue.rs index c919895..002f935 100644 --- a/src/ui/queue.rs +++ b/src/ui/queue.rs @@ -93,6 +93,29 @@ impl ViewExt for QueueView { "Queue".to_string() } + fn title_sub(&self) -> String { + let track_count = self.queue.len(); + let duration_secs: u64 = self + .queue + .queue + .read() + .unwrap() + .iter() + .map(|p| p.duration() as u64 / 1000) + .sum(); + + if duration_secs > 0 { + let duration = std::time::Duration::from_secs(duration_secs); + format!( + "{} tracks, {}", + track_count, + crate::utils::format_duration(&duration) + ) + } else { + "".to_string() + } + } + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { match cmd { Command::Play => { diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..692afe9 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,21 @@ +/// Returns a human readable String of a Duration +/// +/// Example: `3h 12m 53s` +pub fn format_duration(d: &std::time::Duration) -> String { + let mut s = String::new(); + let mut append_unit = |value, unit| { + if value > 0 { + s.push_str(&format!("{}{}", value, unit)); + } + }; + + let seconds = d.as_secs() % 60; + let minutes = (d.as_secs() / 60) % 60; + let hours = (d.as_secs() / 60) / 60; + + append_unit(hours, "h "); + append_unit(minutes, "m "); + append_unit(seconds, "s "); + + s.trim_end().to_string() +}