tek/crates/tek_api/src/transport.rs

97 lines
2.9 KiB
Rust

use crate::*;
pub trait TransportModelApi: JackModelApi + ClockModelApi {
fn transport (&self) -> &jack::Transport;
fn metronome (&self) -> bool;
}
impl JackModelApi for TransportModel {
fn jack (&self) -> &Arc<RwLock<JackClient>> {
&self.jack
}
}
impl ClockModelApi for TransportModel {
fn clock (&self) -> &Arc<Clock> {
&self.clock
}
}
impl TransportModelApi for TransportModel {
fn transport (&self) -> &jack::Transport {
&self.transport
}
fn metronome (&self) -> bool {
self.metronome
}
}
pub struct TransportModel {
jack: Arc<RwLock<JackClient>>,
/// Current sample rate, tempo, and PPQ.
clock: Arc<Clock>,
/// 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<usize>),
Pause(Option<usize>),
SeekUsec(f64),
SeekSample(f64),
SeekPulse(f64),
SetBpm(f64),
SetQuant(f64),
SetSync(f64),
}
impl<T: TransportModelApi> Command<T> for TransportCommand {
fn execute (self, state: &mut T) -> Perhaps<Self> {
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)
}
}