refactor(transport): make widgets focusable

This commit is contained in:
🪞👃🪞 2024-09-01 20:29:15 +03:00
parent 2106a7c044
commit b8ac83b019
9 changed files with 204 additions and 132 deletions

View file

@ -4,9 +4,6 @@ use crate::*;
pub struct TransportToolbar {
/// Enable metronome?
pub metronome: bool,
pub focused: bool,
pub entered: bool,
pub selected: TransportFocus,
/// Current sample rate, tempo, and PPQ.
pub timebase: Arc<Timebase>,
/// JACK client handle (needs to not be dropped for standalone mode to work).
@ -14,28 +11,66 @@ pub struct TransportToolbar {
/// JACK transport handle.
pub transport: Option<Transport>,
/// Quantization factor
pub quant: usize,
/// Global sync quant
pub sync: usize,
/// Current transport state
pub playing: Option<TransportState>,
/// Current position according to transport
pub playhead: usize,
/// Global frame and usec at which playback started
pub started: Option<(usize, usize)>,
pub focused: bool,
pub focus: usize,
pub playing: TransportPlayPauseButton,
pub bpm: TransportBPM,
pub quant: TransportQuantize,
pub sync: TransportSync,
pub clock: TransportClock,
}
focusable!(TransportToolbar);
focus!(TransportToolbar (focus) : 5 => [
playing, bpm, quant, sync, clock
]);
process!(TransportToolbar |self, _client, scope| {
self.update(&scope);
Control::Continue
});
pub struct TransportPlayPauseButton {
pub value: Option<TransportState>,
pub focused: bool
}
focusable!(TransportPlayPauseButton);
pub struct TransportBPM {
pub value: f64,
pub focused: bool
}
focusable!(TransportBPM);
pub struct TransportQuantize {
pub value: usize,
pub focused: bool
}
focusable!(TransportQuantize);
pub struct TransportSync {
pub value: usize,
pub focused: bool
}
focusable!(TransportSync);
pub struct TransportClock {
pub frame: usize,
pub pulse: usize,
pub ppq: usize,
pub usecs: usize,
pub focused: bool,
}
focusable!(TransportClock);
impl TransportToolbar {
pub fn standalone () -> Usually<Arc<RwLock<Self>>> {
let mut transport = Self::new(None);
transport.focused = true;
transport.entered = true;
let jack = JackClient::Inactive(
Client::new("tek_transport", ClientOptions::NO_START_SERVER)?.0
);
@ -55,24 +90,44 @@ impl TransportToolbar {
pub fn new (transport: Option<Transport>) -> Self {
let timebase = Arc::new(Timebase::default());
Self {
selected: TransportFocus::BPM,
metronome: false,
focused: false,
entered: false,
playhead: 0,
playing: Some(TransportState::Stopped),
focus: 0,
started: None,
quant: 24,
sync: timebase.ppq() as usize * 4,
jack: None,
transport,
playing: TransportPlayPauseButton {
value: Some(TransportState::Stopped),
focused: true
},
bpm: TransportBPM {
value: timebase.bpm(),
focused: false
},
quant: TransportQuantize {
value: 24,
focused: false
},
sync: TransportSync {
value: timebase.ppq() as usize * 4,
focused: false
},
clock: TransportClock {
frame: 0,
pulse: 0,
ppq: 0,
usecs: 0,
focused: false
},
timebase,
}
}
pub fn toggle_play (&mut self) -> Usually<()> {
let transport = self.transport.as_ref().unwrap();
self.playing = match self.playing.expect("1st frame has not been processed yet") {
self.playing.value = match self.playing.value.expect("1st frame has not been processed yet") {
TransportState::Stopped => {
transport.start()?;
Some(TransportState::Starting)
@ -95,9 +150,9 @@ impl TransportToolbar {
} = 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;
self.clock.frame = transport.pos.frame() as usize;
let mut reset = false;
if self.playing != Some(transport.state) {
if self.playing.value != Some(transport.state) {
match transport.state {
TransportState::Rolling => {
self.started = Some((
@ -112,7 +167,7 @@ impl TransportToolbar {
_ => {}
}
}
self.playing = Some(transport.state);
self.playing.value = Some(transport.state);
(
reset,
current_frames as usize,
@ -132,11 +187,11 @@ impl TransportToolbar {
}
pub fn pulse (&self) -> usize {
self.timebase.frame_to_pulse(self.playhead as f64) as usize
self.timebase.frame_to_pulse(self.clock.frame as f64) as usize
}
pub fn usecs (&self) -> usize {
self.timebase.frame_to_usec(self.playhead as f64) as usize
self.timebase.frame_to_usec(self.clock.frame as f64) as usize
}
}