diff --git a/crates/tek_core/src/command.rs b/crates/tek_core/src/command.rs index aa9969f2..c64352e6 100644 --- a/crates/tek_core/src/command.rs +++ b/crates/tek_core/src/command.rs @@ -1,7 +1,8 @@ use crate::*; pub trait Command: Sized { - fn run (&self, state: &mut S) -> Perhaps; + fn translate (self, _: &S) -> Self { self } + fn execute (self, state: &mut S) -> Perhaps; } pub trait MatchInput: Sized { fn match_input (state: &S, input: &E::Input) -> Option; diff --git a/crates/tek_core/src/focus.rs b/crates/tek_core/src/focus.rs index 8839d6bd..f0a74607 100644 --- a/crates/tek_core/src/focus.rs +++ b/crates/tek_core/src/focus.rs @@ -1,5 +1,15 @@ use crate::*; +#[derive(Clone, PartialEq)] +pub enum FocusCommand { + Next, + Prev, + Up, + Down, + Left, + Right, +} + pub trait FocusGrid { fn layout (&self) -> &[&[T]]; fn cursor (&self) -> (usize, usize); diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index 4cbbcdcc..e189ec71 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -12,8 +12,10 @@ pub const PPQ: usize = 96; /// This should mean that, even at 192kHz sampling rate, over 1 year of audio /// can be clocked in microseconds with f64 without losing precision. pub trait TimeUnit { - fn get (&self) -> f64;// { self.0.load(Ordering::Relaxed) } - fn set (&self, value: f64);// { self.0.store(value, Ordering::Relaxed) } + /// Returns current value + fn get (&self) -> f64; + /// Sets new value, returns old + fn set (&self, value: f64) -> f64; } /// Implement arithmetic for a unit of time macro_rules! impl_op { @@ -40,7 +42,11 @@ macro_rules! impl_time_unit { ($T:ident) => { impl TimeUnit for $T { fn get (&self) -> f64 { self.0.load(Ordering::Relaxed) } - fn set (&self, value: f64) { self.0.store(value, Ordering::Relaxed) } + fn set (&self, value: f64) -> f64 { + let old = self.get(); + self.0.store(value, Ordering::Relaxed); + old + } } impl_op!($T, Add, add, |a, b|{a + b}); impl_op!($T, Sub, sub, |a, b|{a - b}); diff --git a/crates/tek_sequencer/src/arranger_cmd.rs b/crates/tek_sequencer/src/arranger_cmd.rs index ee3d9f03..6ea39c5f 100644 --- a/crates/tek_sequencer/src/arranger_cmd.rs +++ b/crates/tek_sequencer/src/arranger_cmd.rs @@ -38,27 +38,27 @@ pub enum ArrangementCommand { GoLeft, GoRight, } -impl Command> for ArrangerCommand { - fn run (&self, state: &mut Arranger) -> Perhaps { +impl Command> for ArrangerCommand { + fn execute (self, state: &mut Arranger) -> Perhaps { use ArrangerCommand::*; match self { - FocusNext => { state.focus_next(); }, - FocusPrev => { state.focus_prev(); }, - FocusUp => { state.focus_up(); }, - FocusDown => { state.focus_down(); }, - FocusLeft => { state.focus_left(); }, + FocusNext => { state.focus_next(); }, + FocusPrev => { state.focus_prev(); }, + FocusUp => { state.focus_up(); }, + FocusDown => { state.focus_down(); }, + FocusLeft => { state.focus_left(); }, FocusRight => { state.focus_right(); }, - Transport(command) => if let Some(ref transport) = state.transport { - return command.run(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) + Transport(cmd) => if let Some(ref transport) = state.transport { + return cmd.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) }, - Phrases(command) => { - return command.run(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) + Phrases(cmd) => { + return cmd.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) }, - Editor(command) => { - return command.run(&mut state.editor).map(|x|x.map(Editor)) + Editor(cmd) => { + return cmd.execute(&mut state.editor).map(|x|x.map(Editor)) }, - Arrangement(command) => { - return command.run(&mut state.arrangement).map(|x|x.map(Arrangement)) + Arrangement(cmd) => { + return cmd.execute(&mut state.arrangement).map(|x|x.map(Arrangement)) }, } state.show_phrase(); @@ -66,8 +66,8 @@ impl Command> for ArrangerCommand { Ok(None) } } -impl Command> for ArrangementCommand { - fn run (&self, state: &mut Arrangement) -> Perhaps { +impl Command> for ArrangementCommand { + fn execute (self, state: &mut Arrangement) -> Perhaps { use ArrangementCommand::*; match self { New => todo!(), diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 41139e1d..62520b81 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -125,7 +125,7 @@ impl Content for Arrangement { ArrangementViewMode::Vertical(factor) => add(&VerticalArranger(&self, factor)), }?; let color = if self.focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)}; - add(&TuiStyle::fg("Session", color).push_x(2))?; + add(&TuiStyle::fg("Project", color).push_x(2))?; add(&self.size) }) } @@ -511,21 +511,23 @@ impl<'a> Content for HorizontalArranger<'a, Tui> { /// Handle top-level events in standalone arranger. impl Handle for Arranger { fn handle (&mut self, from: &TuiInput) -> Perhaps { - if let Some(command) = ArrangerCommand::match_input(self, from) { - let _undo = command.run(self)?; - return Ok(Some(true)) - } - Ok(None) + Ok(if let Some(command) = ArrangerCommand::match_input(self, from) { + let _undo = command.execute(self)?; + Some(true) + } else { + None + }) } } /// Handle events for arrangement. impl Handle for Arrangement { fn handle (&mut self, from: &TuiInput) -> Perhaps { - if let Some(command) = ArrangementCommand::match_input(self, from) { - let _undo = command.run(self)?; - return Ok(Some(true)) - } - Ok(None) + Ok(if let Some(command) = ArrangementCommand::match_input(self, from) { + let _undo = command.execute(self)?; + Some(true) + } else { + None + }) } } impl MatchInput> for ArrangerCommand { diff --git a/crates/tek_sequencer/src/sequencer_cmd.rs b/crates/tek_sequencer/src/sequencer_cmd.rs index f0296454..8a0084f0 100644 --- a/crates/tek_sequencer/src/sequencer_cmd.rs +++ b/crates/tek_sequencer/src/sequencer_cmd.rs @@ -2,12 +2,7 @@ use crate::*; #[derive(Clone, PartialEq)] pub enum SequencerCommand { - FocusNext, - FocusPrev, - FocusUp, - FocusDown, - FocusLeft, - FocusRight, + Focus(FocusCommand), Transport(TransportCommand), Phrases(PhrasePoolCommand), Editor(PhraseEditorCommand), @@ -55,89 +50,103 @@ pub enum PhraseEditorCommand { ToggleDirection, EnterEditMode, ExitEditMode, + NoteAppend, + NoteCursorDec, + NoteCursorInc, NoteLengthDec, NoteLengthInc, + NotePageDown, + NotePageUp, + NoteScrollDec, + NoteScrollInc, + NoteSet, + TimeCursorDec, + TimeCursorInc, + TimeScrollDec, + TimeScrollInc, TimeZoomIn, TimeZoomOut, - NoteAppend, - NoteSet, - NotePageUp, - NotePageDown, GoUp, GoDown, GoLeft, GoRight, } impl Command> for SequencerCommand { - fn run (&self, state: &mut Sequencer) -> Perhaps { + fn execute (self, state: &mut Sequencer) -> Perhaps { + use FocusCommand::*; use SequencerCommand::*; match self { - FocusNext => { state.focus_next(); }, - FocusPrev => { state.focus_prev(); }, - FocusUp => { state.focus_up(); }, - FocusDown => { state.focus_down(); }, - FocusLeft => { state.focus_left(); }, - FocusRight => { state.focus_right(); }, + Focus(command) => match command { + Next => { state.focus_next(); }, + Prev => { state.focus_prev(); }, + Up => { state.focus_up(); }, + Down => { state.focus_down(); }, + Left => { state.focus_left(); }, + Right => { state.focus_right(); }, + }, Transport(command) => if let Some(ref transport) = state.transport { - return command.run(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) + return command.execute(&mut*transport.write().unwrap()).map(|x|x.map(Transport)) }, Phrases(command) => { - return command.run(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) + return command.execute(&mut*state.phrases.write().unwrap()).map(|x|x.map(Phrases)) }, Editor(command) => { - return command.run(&mut state.editor).map(|x|x.map(Editor)) + return command.execute(&mut state.editor).map(|x|x.map(Editor)) }, } Ok(None) } } impl Command> for PhrasePoolCommand { - fn run (&self, state: &mut PhrasePool) -> Perhaps { + fn execute (self, state: &mut PhrasePool) -> Perhaps { use PhrasePoolCommand::*; use PhraseRenameCommand as Rename; use PhraseLengthCommand as Length; match self { - Prev => { state.select_prev() }, - Next => { state.select_next() }, - Delete => { state.delete_selected() }, - Append => { state.append_new(None, None) }, - Insert => { state.insert_new(None, None) }, - Duplicate => { state.insert_dup() }, - Edit => { todo!(); } - RandomColor => { state.randomize_color() }, - MoveUp => { state.move_up() }, - MoveDown => { state.move_down() }, Rename(Rename::Begin) => { state.begin_rename() }, - Rename(_) => { unreachable!() }, Length(Length::Begin) => { state.begin_length() }, - Length(_) => { unreachable!() }, - Import => todo!(), - Export => todo!(), + Prev => { state.select_prev() }, + Next => { state.select_next() }, + Delete => { state.delete_selected() }, + Append => { state.append_new(None, None) }, + Insert => { state.insert_new(None, None) }, + Duplicate => { state.insert_dup() }, + RandomColor => { state.randomize_color() }, + MoveUp => { state.move_up() }, + MoveDown => { state.move_down() }, + _ => unreachable!(), } Ok(None) } } impl Command> for PhraseRenameCommand { - fn run (&self, state: &mut PhrasePool) -> Perhaps { + fn translate (self, state: &PhrasePool) -> Self { + use PhraseRenameCommand::*; + if let Some(PhrasePoolMode::Rename(_, ref old_name)) = state.mode { + match self { + Backspace => { + let mut new_name = old_name.clone(); + new_name.pop(); + return Self::Set(new_name) + }, + Append(c) => { + let mut new_name = old_name.clone(); + new_name.push(c); + return Self::Set(new_name) + }, + _ => {} + } + } else if self != Begin { + unreachable!() + } + self + } + fn execute (self, state: &mut PhrasePool) -> Perhaps { use PhraseRenameCommand::*; if let Some(PhrasePoolMode::Rename(phrase, ref mut old_name)) = state.mode { match self { - Begin => { unreachable!(); }, - Backspace => { - let mut phrase = state.phrases[phrase].write().unwrap(); - let old_name = phrase.name.clone(); - phrase.name.pop(); - return Ok(Some(Self::Set(old_name))) - }, - Append(c) => { - let mut phrase = state.phrases[phrase].write().unwrap(); - let old_name = phrase.name.clone(); - phrase.name.push(*c); - return Ok(Some(Self::Set(old_name))) - }, Set(s) => { - let mut phrase = state.phrases[phrase].write().unwrap(); - phrase.name = s.into(); + state.phrases[phrase].write().unwrap().name = s.into(); return Ok(Some(Self::Set(old_name.clone()))) }, Confirm => { @@ -148,10 +157,11 @@ impl Command> for PhraseRenameCommand { Cancel => { let mut phrase = state.phrases[phrase].write().unwrap(); phrase.name = old_name.clone(); - } + }, + _ => unreachable!() }; Ok(None) - } else if *self == Begin { + } else if self == Begin { todo!() } else { unreachable!() @@ -159,41 +169,48 @@ impl Command> for PhraseRenameCommand { } } impl Command> for PhraseLengthCommand { - fn run (&self, state: &mut PhrasePool) -> Perhaps { + fn translate (self, state: &PhrasePool) -> Self { + use PhraseLengthCommand::*; + if let Some(PhrasePoolMode::Length(_, length, _)) = state.mode { + match self { + Confirm => { return Self::Set(length) }, + _ => self + } + } else if self == Begin { + todo!() + } else { + unreachable!() + } + } + fn execute (self, state: &mut PhrasePool) -> Perhaps { + use PhraseLengthFocus::*; use PhraseLengthCommand::*; if let Some(PhrasePoolMode::Length(phrase, ref mut length, ref mut focus)) = state.mode { match self { - Begin => { unreachable!(); }, Cancel => { state.mode = None; }, - Confirm => { return Self::Set(*length).run(state) }, Prev => { focus.prev() }, Next => { focus.next() }, - Inc => { - use PhraseLengthFocus::*; - match focus { - Bar => { *length += 4 * PPQ }, - Beat => { *length += PPQ }, - Tick => { *length += 1 }, - } + Inc => match focus { + Bar => { *length += 4 * PPQ }, + Beat => { *length += PPQ }, + Tick => { *length += 1 }, }, - Dec => { - use PhraseLengthFocus::*; - match focus { - Bar => { *length = length.saturating_sub(4 * PPQ) }, - Beat => { *length = length.saturating_sub(PPQ) }, - Tick => { *length = length.saturating_sub(1) }, - } + Dec => match focus { + Bar => { *length = length.saturating_sub(4 * PPQ) }, + Beat => { *length = length.saturating_sub(PPQ) }, + Tick => { *length = length.saturating_sub(1) }, }, Set(length) => { let mut phrase = state.phrases[phrase].write().unwrap(); let old_length = phrase.length; - phrase.length = *length; + phrase.length = length; state.mode = None; return Ok(Some(Self::Set(old_length))) }, + _ => unreachable!() } Ok(None) - } else if *self == Begin { + } else if self == Begin { todo!() } else { unreachable!() @@ -201,9 +218,19 @@ impl Command> for PhraseLengthCommand { } } impl Command> for PhraseEditorCommand { - fn run (&self, state: &mut PhraseEditor) -> Perhaps { + fn translate (self, state: &PhraseEditor) -> Self { use PhraseEditorCommand::*; match self { + GoUp => match state.entered { true => NoteCursorInc, false => NoteScrollInc, }, + GoDown => match state.entered { true => NoteCursorDec, false => NoteScrollDec, }, + GoLeft => match state.entered { true => TimeCursorDec, false => TimeScrollDec, }, + GoRight => match state.entered { true => TimeCursorInc, false => TimeScrollInc, }, + _ => self + } + } + fn execute (self, state: &mut PhraseEditor) -> Perhaps { + use PhraseEditorCommand::*; + match self.translate(state) { ToggleDirection => { state.mode = !state.mode; }, EnterEditMode => { state.entered = true; }, ExitEditMode => { state.entered = false; }, @@ -218,22 +245,7 @@ impl Command> for PhraseEditorCommand { state.time_cursor_advance(); }, NoteSet => if state.entered { state.put(); }, - GoUp => match state.entered { - true => state.note_cursor_inc(), - false => state.note_scroll_inc(), - }, - GoDown => match state.entered { - true => state.note_cursor_dec(), - false => state.note_scroll_dec(), - }, - GoLeft => match state.entered { - true => state.time_cursor_dec(), - false => state.time_scroll_dec(), - }, - GoRight => match state.entered { - true => state.time_cursor_inc(), - false => state.time_scroll_inc(), - }, + _ => unreachable!() } Ok(None) } diff --git a/crates/tek_sequencer/src/sequencer_tui.rs b/crates/tek_sequencer/src/sequencer_tui.rs index bb7aa9d5..6c912e7d 100644 --- a/crates/tek_sequencer/src/sequencer_tui.rs +++ b/crates/tek_sequencer/src/sequencer_tui.rs @@ -13,7 +13,7 @@ impl Content for Sequencer { impl Handle for Sequencer { fn handle (&mut self, from: &TuiInput) -> Perhaps { if let Some(command) = SequencerCommand::match_input(self, from) { - let _undo = command.run(self)?; + let _undo = command.execute(self)?; return Ok(Some(true)) } Ok(None) @@ -21,27 +21,30 @@ impl Handle for Sequencer { } impl MatchInput> for SequencerCommand { fn match_input (state: &Sequencer, input: &TuiInput) -> Option { + use SequencerCommand::*; + use FocusCommand::*; match input.event() { - key!(KeyCode::Tab) => Some(Self::FocusNext), - key!(Shift-KeyCode::Tab) => Some(Self::FocusPrev), - key!(KeyCode::BackTab) => Some(Self::FocusPrev), - key!(Shift-KeyCode::BackTab) => Some(Self::FocusPrev), - key!(KeyCode::Up) => Some(Self::FocusUp), - key!(KeyCode::Down) => Some(Self::FocusDown), - key!(KeyCode::Left) => Some(Self::FocusLeft), - key!(KeyCode::Right) => Some(Self::FocusRight), - key!(KeyCode::Char(' ')) => Some(Self::Transport(TransportCommand::PlayToggle)), + key!(KeyCode::Tab) => Some(Focus(Next)), + key!(Shift-KeyCode::Tab) => Some(Focus(Prev)), + key!(KeyCode::BackTab) => Some(Focus(Prev)), + key!(Shift-KeyCode::BackTab) => Some(Focus(Prev)), + key!(KeyCode::Up) => Some(Focus(Up)), + key!(KeyCode::Down) => Some(Focus(Down)), + key!(KeyCode::Left) => Some(Focus(Left)), + key!(KeyCode::Right) => Some(Focus(Right)), + key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)), _ => match state.focused() { - SequencerFocus::Transport => state.transport.as_ref() - .map(|t|TransportCommand::match_input(&*t.read().unwrap(), input) - .map(Self::Transport)) - .flatten(), + SequencerFocus::Transport => if let Some(t) = state.transport.as_ref() { + TransportCommand::match_input(&*t.read().unwrap(), input).map(Transport) + } else { + None + }, SequencerFocus::PhrasePool => PhrasePoolCommand::match_input(&*state.phrases.read().unwrap(), input) - .map(Self::Phrases), + .map(Phrases), SequencerFocus::PhraseEditor => PhraseEditorCommand::match_input(&state.editor, input) - .map(Self::Editor), + .map(Editor), } } } @@ -84,7 +87,7 @@ impl Content for PhrasePool { impl Handle for PhrasePool { fn handle (&mut self, from: &TuiInput) -> Perhaps { if let Some(command) = PhrasePoolCommand::match_input(self, from) { - let _undo = command.run(self)?; + let _undo = command.execute(self)?; return Ok(Some(true)) } Ok(None) @@ -282,7 +285,7 @@ impl Content for PhraseEditor { ); } let lower_right = format!( - "{}x{}", + "{{{}x{}}}", self.width.load(Ordering::Relaxed), self.height.load(Ordering::Relaxed), ); @@ -436,7 +439,7 @@ pub(crate) fn keys_vert () -> Buffer { impl Handle for PhraseEditor { fn handle (&mut self, from: &TuiInput) -> Perhaps { if let Some(command) = PhraseEditorCommand::match_input(self, from) { - let _undo = command.run(self)?; + let _undo = command.execute(self)?; return Ok(Some(true)) } Ok(None) diff --git a/crates/tek_sequencer/src/transport_cmd.rs b/crates/tek_sequencer/src/transport_cmd.rs index d77c8092..b5470a60 100644 --- a/crates/tek_sequencer/src/transport_cmd.rs +++ b/crates/tek_sequencer/src/transport_cmd.rs @@ -1,5 +1,5 @@ use crate::*; -#[derive(Clone, PartialEq)] +#[derive(Copy, Clone, PartialEq)] pub enum TransportCommand { FocusNext, FocusPrev, @@ -19,130 +19,84 @@ pub enum TransportCommand { SetSync(f64), } impl Command> for TransportCommand { - fn run (&self, state: &mut TransportToolbar) -> Perhaps { + fn translate (self, state: &TransportToolbar) -> Self { + use TransportCommand::*; + use TransportToolbarFocus::*; match self { - Self::FocusNext => { - state.focus.next(); + Increment => match state.focus { + Bpm => + {return SetBpm(state.clock.timebase().bpm.get() + 1.0) }, + Quant => + {return SetQuant(next_note_length(state.clock.quant.get()as usize)as f64)}, + Sync => + {return SetSync(next_note_length(state.clock.sync.get()as usize)as f64+1.)}, + PlayPause => + {/*todo seek*/}, + Clock => + {/*todo seek*/}, }, - Self::FocusPrev => { - state.focus.prev(); + FineIncrement => match state.focus { + Bpm => + {return SetBpm(state.clock.timebase().bpm.get() + 0.001)}, + Quant => + {return Increment}, + Sync => + {return Increment}, + PlayPause => + {/*todo seek*/}, + Clock => + {/*todo seek*/}, }, - Self::PlayToggle => { - state.toggle_play()?; + Decrement => match state.focus { + Bpm => + {return SetBpm(state.clock.timebase().bpm.get() - 1.0)}, + Quant => + {return SetQuant(prev_note_length(state.clock.quant.get()as usize)as f64)}, + Sync => + {return SetSync(prev_note_length(state.clock.sync.get()as usize)as f64)}, + PlayPause => + {/*todo seek*/}, + Clock => + {/*todo seek*/}, }, - Self::Increment => { - match state.focus { - TransportToolbarFocus::Bpm => { - let bpm = state.clock.timebase().bpm.get(); - return Self::SetBpm(bpm + 1.0).run(state) - }, - TransportToolbarFocus::Quant => { - let quant = state.clock.quant.get() as usize; - let quant = next_note_length(quant) as f64; - return Self::SetQuant(quant).run(state) - }, - TransportToolbarFocus::Sync => { - let sync = state.clock.sync.get() as usize; - let sync = next_note_length(sync) as f64; - return Self::SetSync(sync + 1.0).run(state) - }, - TransportToolbarFocus::PlayPause => { - /*todo seek*/ - }, - TransportToolbarFocus::Clock => { - /*todo seek*/ - }, - } + FineDecrement => match state.focus { + Bpm => + {return SetBpm(state.clock.timebase().bpm.get() - 0.001)}, + Quant => + {return Decrement}, + Sync => + {return Decrement}, + PlayPause => + {/*todo seek*/}, + Clock => + {/*todo seek*/}, }, - Self::FineIncrement => { - match state.focus { - TransportToolbarFocus::Bpm => { - let bpm = state.clock.timebase().bpm.get(); - return Self::SetBpm(bpm + 0.001).run(state) - }, - TransportToolbarFocus::Quant => { - return Self::Increment.run(state) - }, - TransportToolbarFocus::Sync => { - return Self::Increment.run(state) - }, - TransportToolbarFocus::PlayPause => { - /*todo seek*/ - }, - TransportToolbarFocus::Clock => { - /*todo seek*/ - }, - } - }, - Self::Decrement => { - match state.focus { - TransportToolbarFocus::Bpm => { - let bpm = state.clock.timebase().bpm.get(); - return Self::SetBpm(bpm - 1.0).run(state) - }, - TransportToolbarFocus::Quant => { - let quant = state.clock.quant.get() as usize; - let quant = prev_note_length(quant) as f64; - return Self::SetQuant(quant).run(state) - }, - TransportToolbarFocus::Sync => { - let sync = state.clock.sync.get() as usize; - let sync = prev_note_length(sync) as f64; - return Self::SetSync(sync).run(state) - }, - TransportToolbarFocus::PlayPause => { - /*todo seek*/ - }, - TransportToolbarFocus::Clock => { - /*todo seek*/ - }, - } - }, - Self::FineDecrement => { - match state.focus { - TransportToolbarFocus::Bpm => { - let bpm = state.clock.timebase().bpm.get(); - return Self::SetBpm(bpm - 0.001).run(state) - }, - TransportToolbarFocus::Quant => { - return Self::Decrement.run(state) - }, - TransportToolbarFocus::Sync => { - return Self::Decrement.run(state) - }, - TransportToolbarFocus::PlayPause => { - /*todo seek*/ - }, - TransportToolbarFocus::Clock => { - /*todo seek*/ - }, - } - }, - Self::SeekUsec(usec) => { - state.clock.current.update_from_usec(*usec); - }, - Self::SeekSample(sample) => { - state.clock.current.update_from_sample(*sample); - }, - Self::SeekPulse(pulse) => { - state.clock.current.update_from_pulse(*pulse); - }, - Self::SetBpm(bpm) => { - let old_bpm = state.clock.timebase().bpm.get(); - state.clock.timebase().bpm.set(*bpm); - return Ok(Some(Self::SetBpm(old_bpm))) - }, - Self::SetQuant(quant) => { - let old_quant = state.clock.quant.get(); - state.clock.quant.set(*quant); - return Ok(Some(Self::SetQuant(old_quant))) - }, - Self::SetSync(sync) => { - let old_sync = state.clock.sync.get(); - state.clock.sync.set(*sync); - return Ok(Some(Self::SetSync(old_sync))) - }, - _ => { unimplemented!() } + _ => {} + }; + return self + } + fn execute (self, state: &mut TransportToolbar) -> Perhaps { + use TransportCommand::*; + match self.translate(&state) { + FocusNext => + { state.focus.next(); }, + FocusPrev => + { state.focus.prev(); }, + PlayToggle => + { state.toggle_play()?; }, + 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) } diff --git a/crates/tek_sequencer/src/transport_tui.rs b/crates/tek_sequencer/src/transport_tui.rs index 0d17c7fb..d9f72b68 100644 --- a/crates/tek_sequencer/src/transport_tui.rs +++ b/crates/tek_sequencer/src/transport_tui.rs @@ -48,7 +48,7 @@ impl TransportToolbarFocus { impl Handle for TransportToolbar { fn handle (&mut self, from: &TuiInput) -> Perhaps { if let Some(command) = TransportCommand::match_input(self, from) { - let _undo = command.run(self)?; + let _undo = command.execute(self)?; return Ok(Some(true)) } Ok(None)