mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
move formatting onto time traits
This commit is contained in:
parent
f26609ed62
commit
8fb5417c22
4 changed files with 44 additions and 27 deletions
|
|
@ -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<Self, Output=Self> + Mul<Self, Output=Self>
|
||||
+ Div<Self, Output=Self> + Rem<Self, Output=Self> {}
|
||||
impl<T> TimeUnit for T where T: PartialEq + Copy + Display
|
||||
impl<T> TimeUnit for T where T: Copy + Display + PartialOrd + PartialEq
|
||||
+ Add<Self, Output=Self> + Mul<Self, Output=Self>
|
||||
+ Div<Self, Output=Self> + Rem<Self, Output=Self> {}
|
||||
|
||||
|
|
@ -121,6 +121,18 @@ pub trait PulsesPerQuaver<U: TimeUnit> {
|
|||
{
|
||||
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<U: TimeUnit> {
|
||||
|
|
@ -131,11 +143,22 @@ pub trait FramePosition<U: TimeUnit> {
|
|||
pub trait PulsePosition<U: TimeUnit> {
|
||||
fn pulse (&self) -> U;
|
||||
fn set_pulse (&self, pulse: U);
|
||||
#[inline] fn format_current_pulse (&self) -> String
|
||||
where Self: PulsesPerQuaver<U>, U: TimeInteger
|
||||
{
|
||||
self.format_beats(self.pulse())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UsecPosition<U: TimeUnit> {
|
||||
fn usec (&self) -> U;
|
||||
fn set_usec (&self, usec: U);
|
||||
#[inline] fn format_current_usec (&self) -> String where U: From<usize> {
|
||||
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<U: TimeUnit> {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ impl PulsesPerQuaver<f64> for TransportTime {
|
|||
#[inline] fn ppq (&self) -> f64 { self.timebase.ppq() }
|
||||
#[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); }
|
||||
}
|
||||
impl PulsesPerQuaver<usize> 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<usize> 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<E: Engine> TransportToolbar<E> {
|
|||
}
|
||||
}
|
||||
}
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -29,20 +29,13 @@ impl Content for TransportToolbar<Tui> {
|
|||
//"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(),
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue