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;
|
use std::iter::Iterator;
|
||||||
|
|
||||||
/// Any numeric type that represents time
|
/// 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>
|
+ Add<Self, Output=Self> + Mul<Self, Output=Self>
|
||||||
+ Div<Self, Output=Self> + Rem<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>
|
+ Add<Self, Output=Self> + Mul<Self, Output=Self>
|
||||||
+ Div<Self, Output=Self> + Rem<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()
|
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> {
|
pub trait FramePosition<U: TimeUnit> {
|
||||||
|
|
@ -131,11 +143,22 @@ pub trait FramePosition<U: TimeUnit> {
|
||||||
pub trait PulsePosition<U: TimeUnit> {
|
pub trait PulsePosition<U: TimeUnit> {
|
||||||
fn pulse (&self) -> U;
|
fn pulse (&self) -> U;
|
||||||
fn set_pulse (&self, pulse: 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> {
|
pub trait UsecPosition<U: TimeUnit> {
|
||||||
fn usec (&self) -> U;
|
fn usec (&self) -> U;
|
||||||
fn set_usec (&self, usec: 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> {
|
pub trait LaunchSync<U: TimeUnit> {
|
||||||
|
|
|
||||||
|
|
@ -165,18 +165,20 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
|
|
||||||
// track titles
|
// track titles
|
||||||
let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{
|
let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{
|
||||||
let name = track.name.read().unwrap();
|
let name = track.name.read().unwrap();
|
||||||
let max_w = w.saturating_sub(1).min(name.len()).max(2);
|
let max_w = w.saturating_sub(1).min(name.len()).max(2);
|
||||||
let name = format!("▎{}", &name[0..max_w]);
|
let name = format!("▎{}", &name[0..max_w]);
|
||||||
let time1 = track.player.phrase.as_ref()
|
let player = &track.player;
|
||||||
.map(|_|track.player.frames_since_start())
|
let clock = &player.clock;
|
||||||
|
let time1 = player.phrase.as_ref()
|
||||||
|
.map(|_|player.frames_since_start())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|t|format!("▎{t:>}"))
|
.map(|t|format!("▎{t:>}"))
|
||||||
.unwrap_or(String::from("▎"));
|
.unwrap_or(String::from("▎"));
|
||||||
let time2 = track.player.next_phrase.as_ref()
|
let time2 = player.next_phrase.as_ref()
|
||||||
.map(|(t, _)|format!("▎{:>}",
|
.map(|(t, _)|format!("▎{:>}", clock.format_beats(
|
||||||
track.player.clock.samples_to_pulse(t.load(Ordering::Relaxed) as f64)
|
clock.samples_to_pulse(t.load(Ordering::Relaxed) as f64) as usize
|
||||||
))
|
)))
|
||||||
.unwrap_or(String::from("▎"));
|
.unwrap_or(String::from("▎"));
|
||||||
col!(name, time1, time2)
|
col!(name, time1, time2)
|
||||||
.min_xy(w as u16, title_h)
|
.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 ppq (&self) -> f64 { self.timebase.ppq() }
|
||||||
#[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(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 {
|
impl FramePosition<usize> for TransportTime {
|
||||||
#[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) }
|
#[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) }
|
||||||
#[inline] fn set_sample (&self, sample: usize) { self.sample.store(sample, 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<()> {
|
pub fn toggle_play (&mut self) -> Usually<()> {
|
||||||
let transport = self.transport.as_ref().unwrap();
|
let transport = self.transport.as_ref().unwrap();
|
||||||
let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet");
|
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)
|
//"QUANT ", ppq_to_name(self.quant as usize)
|
||||||
//})),
|
//})),
|
||||||
self.focus.wrap(self.focused, TransportToolbarFocus::Sync, &Outset::X(1u16, row! {
|
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(),
|
).align_w().fill_x(),
|
||||||
|
|
||||||
self.focus.wrap(self.focused, TransportToolbarFocus::Clock, &{
|
self.focus.wrap(self.focused, TransportToolbarFocus::Clock, &{
|
||||||
let pulse = self.clock.pulse();
|
let time1 = self.clock.format_current_pulse();
|
||||||
let ppq = self.clock.ppq() as usize;
|
let time2 = self.clock.format_current_usec();
|
||||||
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}");
|
|
||||||
row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1)
|
row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1)
|
||||||
}).align_e().fill_x(),
|
}).align_e().fill_x(),
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue