From 8fb5417c222798303f8d1b8e2b5b1a9034823ed6 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 26 Oct 2024 20:46:07 +0300 Subject: [PATCH] move formatting onto time traits --- crates/tek_core/src/time.rs | 27 +++++++++++++++++++++-- crates/tek_sequencer/src/arranger_tui.rs | 20 +++++++++-------- crates/tek_sequencer/src/transport.rs | 11 +++++---- crates/tek_sequencer/src/transport_tui.rs | 13 +++-------- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index cf6d8479..c871803c 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -2,10 +2,10 @@ use crate::*; use std::iter::Iterator; /// Any numeric type that represents time -pub trait TimeUnit: PartialEq + Copy + Display +pub trait TimeUnit: Copy + Display + PartialOrd + PartialEq + Add + Mul + Div + Rem {} -impl TimeUnit for T where T: PartialEq + Copy + Display +impl TimeUnit for T where T: Copy + Display + PartialOrd + PartialEq + Add + Mul + Div + Rem {} @@ -121,6 +121,18 @@ pub trait PulsesPerQuaver { { self.sr() / self.pulses_per_second() } + + #[inline] fn format_beats (&self, pulse: U) -> String where U: TimeInteger { + let ppq = self.ppq(); + let (beats, pulses) = if ppq > U::from(0) { + (pulse / ppq, pulse % ppq) + } else { + (U::from(0), U::from(0)) + }; + let bars = (beats / U::from(4)) + U::from(1); + let beats = (beats % U::from(4)) + U::from(1); + format!("{bars}.{beats}.{pulses:02}") + } } pub trait FramePosition { @@ -131,11 +143,22 @@ pub trait FramePosition { pub trait PulsePosition { fn pulse (&self) -> U; fn set_pulse (&self, pulse: U); + #[inline] fn format_current_pulse (&self) -> String + where Self: PulsesPerQuaver, U: TimeInteger + { + self.format_beats(self.pulse()) + } } pub trait UsecPosition { fn usec (&self) -> U; fn set_usec (&self, usec: U); + #[inline] fn format_current_usec (&self) -> String where U: From { + let usecs = self.usec(); + let (seconds, msecs) = (usecs / U::from(1000000), usecs / U::from(1000) % U::from(1000)); + let (minutes, seconds) = (seconds / U::from(60), seconds % U::from(60)); + format!("{minutes}:{seconds:02}:{msecs:03}") + } } pub trait LaunchSync { diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 6070d95a..bb81efb4 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -165,18 +165,20 @@ impl<'a> Content for VerticalArranger<'a, Tui> { // track titles let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{ - let name = track.name.read().unwrap(); - let max_w = w.saturating_sub(1).min(name.len()).max(2); - let name = format!("▎{}", &name[0..max_w]); - let time1 = track.player.phrase.as_ref() - .map(|_|track.player.frames_since_start()) + let name = track.name.read().unwrap(); + let max_w = w.saturating_sub(1).min(name.len()).max(2); + let name = format!("▎{}", &name[0..max_w]); + let player = &track.player; + let clock = &player.clock; + let time1 = player.phrase.as_ref() + .map(|_|player.frames_since_start()) .flatten() .map(|t|format!("▎{t:>}")) .unwrap_or(String::from("▎")); - let time2 = track.player.next_phrase.as_ref() - .map(|(t, _)|format!("▎{:>}", - track.player.clock.samples_to_pulse(t.load(Ordering::Relaxed) as f64) - )) + let time2 = player.next_phrase.as_ref() + .map(|(t, _)|format!("▎{:>}", clock.format_beats( + clock.samples_to_pulse(t.load(Ordering::Relaxed) as f64) as usize + ))) .unwrap_or(String::from("▎")); col!(name, time1, time2) .min_xy(w as u16, title_h) diff --git a/crates/tek_sequencer/src/transport.rs b/crates/tek_sequencer/src/transport.rs index 7c1eb9a6..04d256cc 100644 --- a/crates/tek_sequencer/src/transport.rs +++ b/crates/tek_sequencer/src/transport.rs @@ -51,6 +51,11 @@ impl PulsesPerQuaver for TransportTime { #[inline] fn ppq (&self) -> f64 { self.timebase.ppq() } #[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); } } +impl PulsesPerQuaver for TransportTime { + const DEFAULT_PPQ: usize = Timebase::DEFAULT_PPQ as usize; + #[inline] fn ppq (&self) -> usize { self.timebase.ppq() as usize } + #[inline] fn set_ppq (&self, ppq: usize) { self.timebase.set_ppq(ppq as f64); } +} impl FramePosition for TransportTime { #[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) } #[inline] fn set_sample (&self, sample: usize) { self.sample.store(sample, Ordering::Relaxed); } @@ -100,12 +105,6 @@ impl TransportToolbar { } } } - pub fn bpm (&self) -> usize { self.clock.bpm() as usize } - pub fn ppq (&self) -> usize { self.clock.ppq() as usize } - pub fn pulse (&self) -> usize { self.clock.samples_to_pulse(self.clock.sample()as f64) as usize } - pub fn usecs (&self) -> usize { self.clock.samples_to_usec(self.clock.sample() as f64) as usize } - pub fn quant (&self) -> usize { self.clock.quant() } - pub fn sync (&self) -> usize { self.clock.sync() } pub fn toggle_play (&mut self) -> Usually<()> { let transport = self.transport.as_ref().unwrap(); let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet"); diff --git a/crates/tek_sequencer/src/transport_tui.rs b/crates/tek_sequencer/src/transport_tui.rs index eca580f0..10c71226 100644 --- a/crates/tek_sequencer/src/transport_tui.rs +++ b/crates/tek_sequencer/src/transport_tui.rs @@ -29,20 +29,13 @@ impl Content for TransportToolbar { //"QUANT ", ppq_to_name(self.quant as usize) //})), self.focus.wrap(self.focused, TransportToolbarFocus::Sync, &Outset::X(1u16, row! { - "SYNC ", pulses_to_name(self.sync() as usize) + "SYNC ", pulses_to_name(self.clock.sync() as usize) })) ).align_w().fill_x(), self.focus.wrap(self.focused, TransportToolbarFocus::Clock, &{ - let pulse = self.clock.pulse(); - let ppq = self.clock.ppq() as usize; - let usecs = self.clock.usec(); - let (beats, pulses) = if ppq > 0 { (pulse / ppq, pulse % ppq) } else { (0, 0) }; - let (bars, beats) = ((beats / 4) + 1, (beats % 4) + 1); - let (seconds, msecs) = (usecs / 1000000, usecs / 1000 % 1000); - let (minutes, seconds) = (seconds / 60, seconds % 60); - let time1 = format!("{bars}.{beats}.{pulses:02}"); - let time2 = format!("{minutes}:{seconds:02}:{msecs:03}"); + let time1 = self.clock.format_current_pulse(); + let time2 = self.clock.format_current_usec(); row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1) }).align_e().fill_x(),