mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
97 lines
2.9 KiB
Rust
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)
|
|
}
|
|
}
|