use crate::*; pub trait TransportModelApi: JackModelApi + ClockModelApi { fn transport (&self) -> &jack::Transport; fn metronome (&self) -> bool; } impl JackModelApi for TransportModel { fn jack (&self) -> &Arc> { &self.jack } } impl ClockModelApi for TransportModel { fn clock (&self) -> &Arc { &self.clock } } impl TransportModelApi for TransportModel { fn transport (&self) -> &jack::Transport { &self.transport } fn metronome (&self) -> bool { self.metronome } } pub struct TransportModel { jack: Arc>, /// Current sample rate, tempo, and PPQ. clock: Arc, /// JACK transport handle. transport: jack::Transport, /// Enable metronome? metronome: bool, } impl Debug for TransportModel { fn fmt (&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> { f.debug_struct("transport") .field("jack", &self.jack) .field("transport", &"(JACK transport)") .field("clock", &self.clock) .field("metronome", &self.metronome) .finish() } } impl TransportModel { pub fn toggle_play (&mut self) -> Usually<()> { let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet"); let playing = match playing { TransportState::Stopped => { self.transport.start()?; Some(TransportState::Starting) }, _ => { self.transport.stop()?; self.transport.locate(0)?; Some(TransportState::Stopped) }, }; *self.clock.playing.write().unwrap() = playing; Ok(()) } } #[derive(Debug, Copy, Clone, PartialEq)] pub enum TransportCommand { Play(Option), Pause(Option), SeekUsec(f64), SeekSample(f64), SeekPulse(f64), SetBpm(f64), SetQuant(f64), SetSync(f64), } impl Command for TransportCommand { fn execute (self, state: &mut T) -> Perhaps { use TransportCommand::*; 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))))}, _ => { unreachable!() } } Ok(None) } }