From 7a4fa1692b0a8ede5d4ff1bc33f252a6d2712702 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 2 Jan 2025 13:04:57 +0100 Subject: [PATCH] transport -> clock --- src/arranger.rs | 4 +-- src/{time.rs => clock.rs} | 15 +++++------ src/{transport.rs => clock/clock_tui.rs} | 10 ++++---- src/{time => clock}/microsecond.rs | 0 src/{time => clock}/moment.rs | 0 src/{time => clock}/perf.rs | 0 src/{time => clock}/pulse.rs | 0 src/{time => clock}/sample_count.rs | 0 src/{time => clock}/sample_rate.rs | 0 src/{time => clock}/timebase.rs | 0 src/{time => clock}/unit.rs | 0 src/groovebox.rs | 1 + src/lib.rs | 3 +-- src/midi.rs | 8 +++--- src/sequencer.rs | 32 ++++++++++++------------ 15 files changed, 37 insertions(+), 36 deletions(-) rename src/{time.rs => clock.rs} (96%) rename src/{transport.rs => clock/clock_tui.rs} (96%) rename src/{time => clock}/microsecond.rs (100%) rename src/{time => clock}/moment.rs (100%) rename src/{time => clock}/perf.rs (100%) rename src/{time => clock}/pulse.rs (100%) rename src/{time => clock}/sample_count.rs (100%) rename src/{time => clock}/sample_rate.rs (100%) rename src/{time => clock}/timebase.rs (100%) rename src/{time => clock}/unit.rs (100%) diff --git a/src/arranger.rs b/src/arranger.rs index 803ae95a..1200fe0c 100644 --- a/src/arranger.rs +++ b/src/arranger.rs @@ -11,7 +11,7 @@ mod arranger_h; /// Root view for standalone `tek_arranger` pub struct ArrangerTui { jack: Arc>, - pub clock: ClockModel, + pub clock: Clock, pub phrases: PoolModel, pub tracks: Vec, pub scenes: Vec, @@ -69,7 +69,7 @@ impl ArrangerTui { } } from_jack!(|jack| ArrangerTui { - let clock = ClockModel::from(jack); + let clock = Clock::from(jack); let phrase = Arc::new(RwLock::new(MidiClip::new( "New", true, 4 * clock.timebase.ppq.get() as usize, None, Some(ItemColor::random().into()) diff --git a/src/time.rs b/src/clock.rs similarity index 96% rename from src/time.rs rename to src/clock.rs index a8fd4112..70caf676 100644 --- a/src/time.rs +++ b/src/clock.rs @@ -1,5 +1,6 @@ use crate::*; +pub mod clock_tui; pub use self::clock_tui::*; pub mod microsecond; pub(crate) use self::microsecond::*; pub mod moment; pub(crate) use self::moment::*; pub mod perf; pub(crate) use self::perf::*; @@ -10,13 +11,13 @@ pub mod timebase; pub(crate) use self::timebase::*; pub mod unit; pub(crate) use self::unit::*; pub trait HasClock: Send + Sync { - fn clock (&self) -> &ClockModel; + fn clock (&self) -> &Clock; } #[macro_export] macro_rules! has_clock { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { impl $(<$($L),*$($T $(: $U)?),*>)? HasClock for $Struct $(<$($L),*$($T),*>)? { - fn clock (&$self) -> &ClockModel { $cb } + fn clock (&$self) -> &Clock { $cb } } } } @@ -61,7 +62,7 @@ impl Command for ClockCommand { } #[derive(Clone)] -pub struct ClockModel { +pub struct Clock { /// JACK transport handle. pub transport: Arc, /// Global temporal resolution (shared by [Moment] fields) @@ -82,7 +83,7 @@ pub struct ClockModel { pub chunk: Arc, } -from!(|jack: &Arc>| ClockModel = { +from!(|jack: &Arc>| Clock = { let jack = jack.read().unwrap(); let chunk = jack.client().buffer_size(); let transport = jack.client().transport(); @@ -100,9 +101,9 @@ from!(|jack: &Arc>| ClockModel = { } }); -impl std::fmt::Debug for ClockModel { +impl std::fmt::Debug for Clock { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { - f.debug_struct("ClockModel") + f.debug_struct("Clock") .field("timebase", &self.timebase) .field("chunk", &self.chunk) .field("quant", &self.quant) @@ -114,7 +115,7 @@ impl std::fmt::Debug for ClockModel { } } -impl ClockModel { +impl Clock { pub fn timebase (&self) -> &Arc { &self.timebase } diff --git a/src/transport.rs b/src/clock/clock_tui.rs similarity index 96% rename from src/transport.rs rename to src/clock/clock_tui.rs index c91429e9..6ad770ce 100644 --- a/src/transport.rs +++ b/src/clock/clock_tui.rs @@ -6,14 +6,14 @@ use KeyCode::{Enter, Left, Right, Char}; /// Transport clock app. pub struct TransportTui { pub jack: Arc>, - pub clock: ClockModel, + pub clock: Clock, pub size: Measure, pub cursor: (usize, usize), pub color: ItemPalette, } from_jack!(|jack|TransportTui Self { jack: jack.clone(), - clock: ClockModel::from(jack), + clock: Clock::from(jack), size: Measure::new(), cursor: (0, 0), color: ItemPalette::random(), @@ -23,7 +23,7 @@ audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope handle!(|self: TransportTui, from|TransportCommand::execute_with_state(self, from)); render!(Tui: (self: TransportTui) => TransportView(&self.clock)); -pub struct TransportView<'a>(pub &'a ClockModel); +pub struct TransportView<'a>(pub &'a Clock); render!(Tui: (self: TransportView<'a>) => row!( BeatStats::new(self.0), " ", PlayPause(self.0.is_rolling()), " ", @@ -48,7 +48,7 @@ impl std::fmt::Debug for TransportTui { pub struct BeatStats { bpm: String, beat: String, time: String, } impl BeatStats { - fn new (clock: &ClockModel) -> Self { + fn new (clock: &Clock) -> Self { let (beat, time) = clock.started.read().unwrap().as_ref().map(|started|{ let current_usec = clock.global.usec.get() - started.usec.get(); ( @@ -65,7 +65,7 @@ render!(Tui: (self: BeatStats) => col!( pub struct OutputStats { sample_rate: String, buffer_size: String, latency: String, } impl OutputStats { - fn new (clock: &ClockModel) -> Self { + fn new (clock: &Clock) -> Self { let rate = clock.timebase.sr.get(); let chunk = clock.chunk.load(Relaxed); Self { diff --git a/src/time/microsecond.rs b/src/clock/microsecond.rs similarity index 100% rename from src/time/microsecond.rs rename to src/clock/microsecond.rs diff --git a/src/time/moment.rs b/src/clock/moment.rs similarity index 100% rename from src/time/moment.rs rename to src/clock/moment.rs diff --git a/src/time/perf.rs b/src/clock/perf.rs similarity index 100% rename from src/time/perf.rs rename to src/clock/perf.rs diff --git a/src/time/pulse.rs b/src/clock/pulse.rs similarity index 100% rename from src/time/pulse.rs rename to src/clock/pulse.rs diff --git a/src/time/sample_count.rs b/src/clock/sample_count.rs similarity index 100% rename from src/time/sample_count.rs rename to src/clock/sample_count.rs diff --git a/src/time/sample_rate.rs b/src/clock/sample_rate.rs similarity index 100% rename from src/time/sample_rate.rs rename to src/clock/sample_rate.rs diff --git a/src/time/timebase.rs b/src/clock/timebase.rs similarity index 100% rename from src/time/timebase.rs rename to src/clock/timebase.rs diff --git a/src/time/unit.rs b/src/clock/unit.rs similarity index 100% rename from src/time/unit.rs rename to src/clock/unit.rs diff --git a/src/groovebox.rs b/src/groovebox.rs index af42e397..6217a0d1 100644 --- a/src/groovebox.rs +++ b/src/groovebox.rs @@ -153,6 +153,7 @@ render!(Tui: (self: Groovebox) => { ) )}); +// TODO move this to sampler struct GrooveboxSamples<'a>(&'a Groovebox); render!(Tui: (self: GrooveboxSamples<'a>) => { let note_lo = self.0.editor.note_lo().load(Relaxed); diff --git a/src/lib.rs b/src/lib.rs index 0e08679d..56441411 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ pub(crate) use std::time::Duration; pub mod arranger; pub use self::arranger::*; pub mod border; pub use self::border::*; +pub mod clock; pub use self::clock::*; pub mod color; pub use self::color::*; pub mod command; pub use self::command::*; pub mod event; pub use self::event::*; @@ -64,8 +65,6 @@ pub mod sequencer; pub use self::sequencer::*; pub mod status; pub use self::status::*; pub mod style; pub use self::style::*; pub mod theme; pub use self::theme::*; -pub mod time; pub use self::time::*; -pub mod transport; pub use self::transport::*; pub use ::atomic_float; pub(crate) use atomic_float::*; diff --git a/src/midi.rs b/src/midi.rs index 624235ce..3ec99d15 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -102,7 +102,7 @@ pub trait HasPlayer { /// Contains state for playing a phrase pub struct MidiPlayer { /// State of clock and playhead - pub(crate) clock: ClockModel, + pub(crate) clock: Clock, /// Start time and phrase being played pub(crate) play_phrase: Option<(Moment, Option>>)>, /// Start time and next phrase @@ -135,7 +135,7 @@ impl MidiPlayer { ) -> Usually { let name = name.as_ref(); Ok(Self { - clock: ClockModel::from(jack), + clock: Clock::from(jack), play_phrase: None, next_phrase: None, recording: false, @@ -166,7 +166,7 @@ impl std::fmt::Debug for MidiPlayer { .finish() } } -from!(|clock: &ClockModel| MidiPlayer = Self { +from!(|clock: &Clock| MidiPlayer = Self { clock: clock.clone(), midi_ins: vec![], midi_outs: vec![], @@ -180,7 +180,7 @@ from!(|clock: &ClockModel| MidiPlayer = Self { notes_in: RwLock::new([false;128]).into(), notes_out: RwLock::new([false;128]).into(), }); -from!(|state: (&ClockModel, &Arc>)|MidiPlayer = { +from!(|state: (&Clock, &Arc>)|MidiPlayer = { let (clock, phrase) = state; let mut model = Self::from(clock); model.play_phrase = Some((Moment::zero(&clock.timebase), Some(phrase.clone()))); diff --git a/src/sequencer.rs b/src/sequencer.rs index d70eea2a..4a830965 100644 --- a/src/sequencer.rs +++ b/src/sequencer.rs @@ -1,7 +1,7 @@ use crate::*; use ClockCommand::{Play, Pause}; use KeyCode::{Tab, Char}; -use SequencerCommand::*; +use SequencerCommand as Cmd; use PhraseCommand::*; use PhrasePoolCommand::*; /// Root view for standalone `tek_sequencer`. @@ -9,7 +9,7 @@ pub struct SequencerTui { _jack: Arc>, pub transport: bool, pub selectors: bool, - pub clock: ClockModel, + pub clock: Clock, pub phrases: PoolModel, pub player: MidiPlayer, pub editor: MidiEditor, @@ -20,7 +20,7 @@ pub struct SequencerTui { pub perf: PerfModel, } from_jack!(|jack|SequencerTui { - let clock = ClockModel::from(jack); + let clock = Clock::from(jack); let phrase = Arc::new(RwLock::new(MidiClip::new( "New", true, 4 * clock.timebase.ppq.get() as usize, None, Some(ItemColor::random().into()) @@ -102,28 +102,28 @@ input_to_command!(SequencerCommand: |state: SequencerTui, input|match input // TODO: k: toggle on-screen keyboard key_pat!(Ctrl-Char('k')) => { todo!("keyboard") }, // Transport: Play/pause - key_pat!(Char(' ')) => Clock( + key_pat!(Char(' ')) => Cmd::Clock( if state.clock().is_stopped() { Play(None) } else { Pause(None) } ), // Transport: Play from start or rewind to start - key_pat!(Shift-Char(' ')) => Clock( + key_pat!(Shift-Char(' ')) => Cmd::Clock( if state.clock().is_stopped() { Play(Some(0)) } else { Pause(Some(0)) } ), // u: undo - key_pat!(Char('u')) => History(-1), + key_pat!(Char('u')) => Cmd::History(-1), // Shift-U: redo - key_pat!(Char('U')) => History( 1), + key_pat!(Char('U')) => Cmd::History( 1), // Tab: Toggle visibility of phrase pool column - key_pat!(Tab) => Pool(PoolCommand::Show(!state.phrases.visible)), + key_pat!(Tab) => Cmd::Pool(PoolCommand::Show(!state.phrases.visible)), // q: Enqueue currently edited phrase - key_pat!(Char('q')) => Enqueue(Some(state.phrases.phrase().clone())), + key_pat!(Char('q')) => Cmd::Enqueue(Some(state.phrases.phrase().clone())), // 0: Enqueue phrase 0 (stop all) - key_pat!(Char('0')) => Enqueue(Some(state.phrases.phrases()[0].clone())), + key_pat!(Char('0')) => Cmd::Enqueue(Some(state.phrases.phrases()[0].clone())), // e: Toggle between editing currently playing or other phrase key_pat!(Char('e')) => if let Some((_, Some(playing))) = state.player.play_phrase() { let editing = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone()); let selected = state.phrases.phrase().clone(); - Editor(Show(Some(if Some(selected.read().unwrap().clone()) != editing { + Cmd::Editor(Show(Some(if Some(selected.read().unwrap().clone()) != editing { selected } else { playing.clone() @@ -134,9 +134,9 @@ input_to_command!(SequencerCommand: |state: SequencerTui, input|match input // For the rest, use the default keybindings of the components. // The ones defined above supersede them. _ => if let Some(command) = PhraseCommand::input_to_command(&state.editor, input) { - Editor(command) + Cmd::Editor(command) } else if let Some(command) = PoolCommand::input_to_command(&state.phrases, input) { - Pool(command) + Cmd::Pool(command) } else { return None } @@ -145,7 +145,7 @@ command!(|self: SequencerCommand, state: SequencerTui|match self { Self::Pool(cmd) => { let mut default = |cmd: PoolCommand|cmd .execute(&mut state.phrases) - .map(|x|x.map(Pool)); + .map(|x|x.map(Cmd::Pool)); match cmd { // autoselect: automatically load selected phrase in editor PoolCommand::Select(_) => { @@ -163,12 +163,12 @@ command!(|self: SequencerCommand, state: SequencerTui|match self { } }, Self::Editor(cmd) => { - let default = ||cmd.execute(&mut state.editor).map(|x|x.map(Editor)); + let default = ||cmd.execute(&mut state.editor).map(|x|x.map(Cmd::Editor)); match cmd { _ => default()? } }, - Self::Clock(cmd) => cmd.execute(state)?.map(Clock), + Self::Clock(cmd) => cmd.execute(state)?.map(Cmd::Clock), Self::Enqueue(phrase) => { state.player.enqueue_next(phrase.as_ref()); None