From e7e57cea1e64fc888a038ce067ee7f8a82ecf7b1 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 13 Nov 2024 19:49:52 +0100 Subject: [PATCH] wip: refactor pt.22: api traits in snd --- crates/tek_api/src/arrange.rs | 44 +++++++++++++++++++---------- crates/tek_api/src/pool.rs | 24 ++++++++++++---- crates/tek_api/src/sequencer.rs | 19 +++++++++---- crates/tek_api/src/transport_cmd.rs | 18 ++++++------ crates/tek_snd/src/lib.rs | 4 +-- crates/tek_snd/src/snd_arrange.rs | 12 ++++++-- crates/tek_snd/src/snd_sequencer.rs | 20 ++++--------- crates/tek_snd/src/snd_transport.rs | 26 ++++++++--------- 8 files changed, 100 insertions(+), 67 deletions(-) diff --git a/crates/tek_api/src/arrange.rs b/crates/tek_api/src/arrange.rs index 53b28ac5..65e89f85 100644 --- a/crates/tek_api/src/arrange.rs +++ b/crates/tek_api/src/arrange.rs @@ -2,9 +2,10 @@ use crate::*; pub trait ArrangerModelApi: JackModelApi + ClockModelApi { fn name (&self) -> &Arc>; - fn phrases (&self) -> &Arc>; + fn tracks (&self) -> &Vec; fn tracks_mut (&mut self) -> &mut Vec; + fn scenes (&self) -> &Vec; fn scenes_mut (&mut self) -> &mut Vec; @@ -54,13 +55,31 @@ pub trait ArrangerModelApi: JackModelApi + ClockModelApi { impl JackModelApi for ArrangerModel { fn jack (&self) -> &Arc> { - &self.jack + &self.transport.jack() } } impl ClockModelApi for ArrangerModel { fn clock (&self) -> &Arc { - &self.clock + &self.transport.clock() + } +} + +impl TransportModelApi for ArrangerModel { + fn transport (&self) -> &jack::Transport { + &self.transport.transport() + } + fn metronome (&self) -> bool { + self.transport.metronome() + } +} + +impl PhrasePoolModelApi for ArrangerModel { + fn phrases (&self) -> &Vec>> { + &self.phrases + } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases } } @@ -68,9 +87,6 @@ impl ArrangerModelApi for ArrangerModel { fn name (&self) -> &Arc> { &self.name } - fn phrases (&self) -> &Arc> { - &self.phrases - } fn tracks (&self) -> &Vec { &self.tracks } @@ -87,18 +103,16 @@ impl ArrangerModelApi for ArrangerModel { #[derive(Debug)] pub struct ArrangerModel { - /// JACK client handle (needs to not be dropped for standalone mode to work). - jack: Arc>, - /// Global timebase - clock: Arc, - /// Name of arranger - name: Arc>, + /// State of the JACK transport. + transport: TransportModel, /// Collection of phrases. - phrases: Arc>, + phrases: Vec>>, /// Collection of tracks. - tracks: Vec, + tracks: Vec, /// Collection of scenes. - scenes: Vec, + scenes: Vec, + /// Name of arranger + name: Arc>, } #[derive(Debug)] diff --git a/crates/tek_api/src/pool.rs b/crates/tek_api/src/pool.rs index 211aef62..22cb7b2d 100644 --- a/crates/tek_api/src/pool.rs +++ b/crates/tek_api/src/pool.rs @@ -1,8 +1,22 @@ use crate::*; +pub trait PhrasePoolModelApi { + fn phrases (&self) -> &Vec>>; + fn phrases_mut (&mut self) -> &mut Vec>>; +} + +impl PhrasePoolModelApi for PhrasePoolModel { + fn phrases (&self) -> &Vec>> { + &self.phrases + } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases + } +} + /// Contains all phrases in a project #[derive(Debug)] -pub struct PhrasePool { +pub struct PhrasePoolModel { /// Phrases in the pool pub phrases: Vec>>, } @@ -20,8 +34,8 @@ pub enum PhrasePoolCommand { SetLength(usize, usize), } -impl Command for PhrasePoolCommand { - fn execute (self, state: &mut PhrasePool) -> Perhaps { +impl Command for PhrasePoolCommand { + fn execute (self, model: &mut PhrasePoolModel) -> Perhaps { match self { Self::Add(index) => { //Self::Append => { view.append_new(None, None) }, @@ -29,8 +43,8 @@ impl Command for PhrasePoolCommand { }, Self::Delete(index) => { //if view.phrase > 0 { - //view.state.phrases.remove(view.phrase); - //view.phrase = view.phrase.min(view.state.phrases.len().saturating_sub(1)); + //view.model.phrases.remove(view.phrase); + //view.phrase = view.phrase.min(view.model.phrases.len().saturating_sub(1)); //} }, Self::Duplicate(index) => { diff --git a/crates/tek_api/src/sequencer.rs b/crates/tek_api/src/sequencer.rs index 2f0df83e..794be359 100644 --- a/crates/tek_api/src/sequencer.rs +++ b/crates/tek_api/src/sequencer.rs @@ -1,8 +1,8 @@ use crate::*; -pub trait SequencerModelApi: JackModelApi + ClockModelApi { - fn phrases (&self) -> &PhrasePool; +pub trait SequencerModelApi: JackModelApi + ClockModelApi + TransportModelApi { fn player (&self) -> &MIDIPlayer; + fn player_mut (&mut self) -> &mut MIDIPlayer; } impl JackModelApi for SequencerModel { @@ -26,20 +26,29 @@ impl TransportModelApi for SequencerModel { } } -impl SequencerModelApi for SequencerModel { - fn phrases (&self) -> &PhrasePool { +impl PhrasePoolModelApi for SequencerModel { + fn phrases (&self) -> &Vec>> { &self.phrases } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases + } +} + +impl SequencerModelApi for SequencerModel { fn player (&self) -> &MIDIPlayer { &self.player } + fn player_mut (&mut self) -> &mut MIDIPlayer { + &mut self.player + } } pub struct SequencerModel { /// State of the JACK transport. transport: TransportModel, /// State of the phrase pool. - phrases: PhrasePool, + phrases: Vec>>, /// State of the phrase player. player: MIDIPlayer, } diff --git a/crates/tek_api/src/transport_cmd.rs b/crates/tek_api/src/transport_cmd.rs index 3981bbc6..d4b1bdc7 100644 --- a/crates/tek_api/src/transport_cmd.rs +++ b/crates/tek_api/src/transport_cmd.rs @@ -12,18 +12,18 @@ pub enum TransportCommand { SetSync(f64), } -impl Command for TransportCommand { - fn execute (self, state: &mut Transport) -> Perhaps { +impl Command for TransportCommand { + fn execute (self, state: &mut T) -> Perhaps { use TransportCommand::*; - match self.translate(&state) { + match self { Play(start) => {todo!()}, Pause(start) => {todo!()}, - SeekUsec(usec) => {state.clock.current.update_from_usec(usec);}, - SeekSample(sample) => {state.clock.current.update_from_sample(sample);}, - SeekPulse(pulse) => {state.clock.current.update_from_pulse(pulse);}, - SetBpm(bpm) => {return Ok(Some(Self::SetBpm(state.clock.timebase().bpm.set(bpm))))}, - SetQuant(quant) => {return Ok(Some(Self::SetQuant(state.clock.quant.set(quant))))}, - SetSync(sync) => {return Ok(Some(Self::SetSync(state.clock.sync.set(sync))))}, + SeekUsec(usec) => {state.clock().current.update_from_usec(usec);}, + SeekSample(sample) => {state.clock().current.update_from_sample(sample);}, + SeekPulse(pulse) => {state.clock().current.update_from_pulse(pulse);}, + SetBpm(bpm) => {return Ok(Some(Self::SetBpm(state.clock().timebase().bpm.set(bpm))))}, + SetQuant(quant) => {return Ok(Some(Self::SetQuant(state.clock().quant.set(quant))))}, + SetSync(sync) => {return Ok(Some(Self::SetSync(state.clock().sync.set(sync))))}, _ => { unreachable!() } } Ok(None) diff --git a/crates/tek_snd/src/lib.rs b/crates/tek_snd/src/lib.rs index 0a64c9a1..2be477ae 100644 --- a/crates/tek_snd/src/lib.rs +++ b/crates/tek_snd/src/lib.rs @@ -1,5 +1,5 @@ -pub use tek_core::{*, jack::{*, Transport as JackTransport}}; -pub use tek_api::{*, Transport}; +pub use tek_core::{*, jack::*}; +pub use tek_api::*; pub(crate) use tek_core::midly::{*, live::LiveEvent, num::u7}; submod! { diff --git a/crates/tek_snd/src/snd_arrange.rs b/crates/tek_snd/src/snd_arrange.rs index c1f6763a..90d9829f 100644 --- a/crates/tek_snd/src/snd_arrange.rs +++ b/crates/tek_snd/src/snd_arrange.rs @@ -1,8 +1,16 @@ use crate::*; -impl Audio for T { +impl Audio for ArrangerModel { + fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { + ArrangerRefAudio(self).process(client, scope) + } +} + +pub struct ArrangerRefAudio<'a, T: ArrangerModelApi + Send + Sync>(&'a mut T); + +impl<'a, T: ArrangerModelApi + Send + Sync> Audio for ArrangerRefAudio<'a, T> { #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - for track in self.tracks_mut().iter_mut() { + for track in self.0.tracks_mut().iter_mut() { if MIDIPlayerAudio::from(&mut track.player).process(client, scope) == Control::Quit { return Control::Quit } diff --git a/crates/tek_snd/src/snd_sequencer.rs b/crates/tek_snd/src/snd_sequencer.rs index 576ef2b2..f4d85c11 100644 --- a/crates/tek_snd/src/snd_sequencer.rs +++ b/crates/tek_snd/src/snd_sequencer.rs @@ -1,27 +1,19 @@ use crate::*; -pub struct SequencerAudio(pub Arc>, pub Arc>); - -/// JACK process callback for sequencer app -impl<'a> Audio for SequencerAudio { +impl Audio for SequencerModel { fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - SequencerRefAudio( - &mut*self.0.write().unwrap(), - &mut*self.1.write().unwrap() - ).process(client, scope) + SequencerRefAudio(self).process(client, scope) } } +pub struct SequencerRefAudio<'a, T: SequencerModelApi + Send + Sync>(&'a mut T); -pub struct SequencerRefAudio<'a>(pub &'a mut Transport, pub &'a mut MIDIPlayer); - -/// JACK process callback for sequencer embed -impl<'a> Audio for SequencerRefAudio<'a> { - fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { +impl<'a, T: SequencerModelApi + Send + Sync> Audio for SequencerRefAudio<'a, T> { + #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { if TransportRefAudio(&mut*self.0).process(client, scope) == Control::Quit { return Control::Quit } - if MIDIPlayerAudio::from(&mut*self.1).process(client, scope) == Control::Quit { + if MIDIPlayerAudio::from(&mut*self.0.player_mut()).process(client, scope) == Control::Quit { return Control::Quit } Control::Continue diff --git a/crates/tek_snd/src/snd_transport.rs b/crates/tek_snd/src/snd_transport.rs index a20d8b7c..9c49240d 100644 --- a/crates/tek_snd/src/snd_transport.rs +++ b/crates/tek_snd/src/snd_transport.rs @@ -1,27 +1,23 @@ use crate::*; -pub struct TransportAudio(pub Arc>); - -impl Audio for TransportAudio { +impl Audio for TransportModel { fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - TransportRefAudio( - &mut*self.0.write().unwrap() - ).process(client, scope) + TransportRefAudio(self).process(client, scope) } } -pub struct TransportRefAudio<'a>(pub &'a mut Transport); +pub struct TransportRefAudio<'a, T: TransportModelApi + Send + Sync>(pub(crate) &'a mut T); -impl<'a> Audio for TransportRefAudio<'a> { - fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { - let ref state = self.0; +impl<'a, T: TransportModelApi + Send + Sync> Audio for TransportRefAudio<'a, T> { + #[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { + let state = &mut self.0; 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; - let transport = state.transport.query().unwrap(); - state.clock.current.sample.set(transport.pos.frame() as f64); - let mut playing = state.clock.playing.write().unwrap(); - let mut started = state.clock.started.write().unwrap(); + let transport = state.transport().query().unwrap(); + state.clock().current.sample.set(transport.pos.frame() as f64); + let mut playing = state.clock().playing.write().unwrap(); + let mut started = state.clock().started.write().unwrap(); if *playing != Some(transport.state) { match transport.state { TransportState::Rolling => { @@ -37,7 +33,7 @@ impl<'a> Audio for TransportRefAudio<'a> { if *playing == Some(TransportState::Stopped) { *started = None; } - state.clock.current.update_from_usec(match *started { + state.clock().current.update_from_usec(match *started { Some((_, usecs)) => current_usecs as f64 - usecs as f64, None => 0. });