diff --git a/crates/tek_api/src/api_clock.rs b/crates/tek_api/src/api_clock.rs index 103497ac..59602706 100644 --- a/crates/tek_api/src/api_clock.rs +++ b/crates/tek_api/src/api_clock.rs @@ -47,17 +47,23 @@ pub struct ClockModel { pub quant: Arc, /// Launch quantization factor pub sync: Arc, + /// Size of buffer in samples + pub chunk: Arc, } -impl From<&Arc> for ClockModel { - fn from (transport: &Arc) -> Self { +impl From<&Arc>> for ClockModel { + fn from (jack: &Arc>) -> Self { + let jack = jack.read().unwrap(); + let chunk = jack.client().buffer_size(); + let transport = jack.client().transport(); Self { playing: RwLock::new(None).into(), started: RwLock::new(None).into(), current: Instant::default().into(), quant: Arc::new(24.into()), sync: Arc::new(384.into()), - transport: transport.clone(), + transport: Arc::new(transport), + chunk: Arc::new((chunk as usize).into()), } } } @@ -137,11 +143,18 @@ pub struct ClockAudio<'a, T: HasClock>(pub &'a mut T); impl<'a, T: HasClock> Audio for ClockAudio<'a, T> { #[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { let state = self.0.clock(); - let times = scope.cycle_times().unwrap(); - let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times; - let _chunk_size = scope.n_frames() as usize; + + // Update chunk size + state.chunk.store(scope.n_frames() as usize, Ordering::Relaxed); + + // Query transport state let transport = state.transport.query().unwrap(); + + // FIXME duplicated state.current.sample.set(transport.pos.frame() as f64); + + // Update play/pause state and starting point + let CycleTimes { current_frames, current_usecs, .. } = scope.cycle_times().unwrap(); let mut playing = state.playing.write().unwrap(); let mut started = state.started.write().unwrap(); if *playing != Some(transport.state) { @@ -159,10 +172,13 @@ impl<'a, T: HasClock> Audio for ClockAudio<'a, T> { if *playing == Some(TransportState::Stopped) { *started = None; } + + // FIXME duplicated state.current.update_from_usec(match *started { Some((_, usecs)) => current_usecs as f64 - usecs as f64, None => 0. }); + Control::Continue } } diff --git a/crates/tek_tui/src/tui_app_arranger.rs b/crates/tek_tui/src/tui_app_arranger.rs index 2e634a59..9a03f00e 100644 --- a/crates/tek_tui/src/tui_app_arranger.rs +++ b/crates/tek_tui/src/tui_app_arranger.rs @@ -30,7 +30,7 @@ impl TryFrom<&Arc>> for ArrangerTui { fn try_from (jack: &Arc>) -> Usually { Ok(Self { jack: jack.clone(), - clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())), + clock: ClockModel::from(jack), phrases: PhraseListModel::default(), editor: PhraseEditorModel::default(), selected: ArrangerSelection::Clip(0, 0), diff --git a/crates/tek_tui/src/tui_app_sequencer.rs b/crates/tek_tui/src/tui_app_sequencer.rs index a7680395..93cb4a52 100644 --- a/crates/tek_tui/src/tui_app_sequencer.rs +++ b/crates/tek_tui/src/tui_app_sequencer.rs @@ -20,7 +20,7 @@ pub struct SequencerTui { impl TryFrom<&Arc>> for SequencerTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { - let clock = ClockModel::from(&Arc::new(jack.read().unwrap().transport())); + let clock = ClockModel::from(jack); Ok(Self { jack: jack.clone(), phrases: PhraseListModel::default(), @@ -111,7 +111,7 @@ impl_focus!(SequencerTui SequencerFocus [ pub struct SequencerStatusBar { pub(crate) cpu: Option, pub(crate) size: String, - pub(crate) sr: String, + pub(crate) res: String, pub(crate) mode: &'static str, pub(crate) help: &'static [(&'static str, &'static str, &'static str)] } @@ -130,10 +130,13 @@ impl From<&SequencerTui> for SequencerStatusBar { fn from (state: &SequencerTui) -> Self { use SequencerFocus::*; use TransportFocus::*; + let samples = state.clock.chunk.load(Ordering::Relaxed); + let rate = state.clock.current.timebase.sr.get() as f64; + let buffer = samples as f64 / rate; Self { - cpu: state.perf.percentage().map(|cpu|format!(" {cpu:.01}% ")), - size: format!(" {}x{} ", state.size.w(), state.size.h()), - sr: format!(" {}Hz ", state.clock.current.timebase.sr.get()), + cpu: state.perf.percentage().map(|cpu|format!("│{cpu:.01}%")), + size: format!("{}x{}│", state.size.w(), state.size.h()), + res: format!("│{}s│{:.1}kHz│{:.1}ms│", samples, rate / 1000., buffer * 1000.), mode: match state.focused() { Transport(focus) => match focus { PlayPause => " PLAY/PAUSE ", diff --git a/crates/tek_tui/src/tui_app_transport.rs b/crates/tek_tui/src/tui_app_transport.rs index b02dc468..2c5ee090 100644 --- a/crates/tek_tui/src/tui_app_transport.rs +++ b/crates/tek_tui/src/tui_app_transport.rs @@ -25,7 +25,7 @@ impl TryFrom<&Arc>> for TransportTui { fn try_from (jack: &Arc>) -> Usually { Ok(Self { jack: jack.clone(), - clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())), + clock: ClockModel::from(jack), size: Measure::new(), cursor: (0, 0), focus: FocusState::Entered(TransportFocus::PlayPause) diff --git a/crates/tek_tui/src/tui_view_sequencer.rs b/crates/tek_tui/src/tui_view_sequencer.rs index 5b44c5de..c9e15a3d 100644 --- a/crates/tek_tui/src/tui_view_sequencer.rs +++ b/crates/tek_tui/src/tui_view_sequencer.rs @@ -34,7 +34,7 @@ impl Content for SequencerStatusBar { widget(&self.mode).bg(orange).fg(black).bold(true), row!( widget(&self.cpu).fg(orange), - widget(&self.sr).fg(orange), + widget(&self.res).fg(orange), widget(&self.size).fg(orange), ).align_se().fill_x() )