use crate::core::*; pub struct TransportToolbar { pub metronome: bool, pub mode: bool, pub focused: bool, pub entered: bool, /// Current sample rate, tempo, and PPQ. pub timebase: Arc, /// JACK transport handle. transport: Option, /// Quantization factor pub quant: usize, /// Current transport state pub playing: Option, /// Current position according to transport playhead: usize, /// Global frame and usec at which playback started pub started: Option<(usize, usize)>, } impl TransportToolbar { pub fn new (transport: Option) -> Self { Self { transport, metronome: false, mode: false, focused: false, entered: false, timebase: Arc::new(Timebase::default()), playhead: 0, playing: Some(TransportState::Stopped), started: None, quant: 24, } } pub fn toggle_play (&mut self) -> Usually<()> { self.playing = match self.playing.expect("1st frame has not been processed yet") { TransportState::Stopped => { self.transport.as_ref().unwrap().start()?; Some(TransportState::Starting) }, _ => { self.transport.as_ref().unwrap().stop()?; self.transport.as_ref().unwrap().locate(0)?; Some(TransportState::Stopped) }, }; Ok(()) } pub fn update (&mut self, scope: &ProcessScope) -> (bool, usize, usize, usize, usize, f64) { let CycleTimes { current_frames, current_usecs, next_usecs, period_usecs } = scope.cycle_times().unwrap(); let chunk_size = scope.n_frames() as usize; let transport = self.transport.as_ref().unwrap().query().unwrap(); self.playhead = transport.pos.frame() as usize; let mut reset = false; if self.playing != Some(transport.state) { match transport.state { TransportState::Rolling => { self.started = Some(( current_frames as usize, current_usecs as usize, )); }, TransportState::Stopped => { self.started = None; reset = true; }, _ => {} } } self.playing = Some(transport.state); ( reset, current_frames as usize, chunk_size as usize, current_usecs as usize, next_usecs as usize, period_usecs as f64 ) } pub fn bpm (&self) -> usize { self.timebase.bpm() as usize } pub fn ppq (&self) -> usize { self.timebase.ppq() as usize } pub fn pulse (&self) -> usize { self.timebase.frame_to_pulse(self.playhead as f64) as usize } pub fn usecs (&self) -> usize { self.timebase.frame_to_usec(self.playhead as f64) as usize } }