command system; first for transport

This commit is contained in:
🪞👃🪞 2024-11-06 23:32:10 +01:00
parent 2e96b10fad
commit 524e283075
4 changed files with 230 additions and 46 deletions

View file

@ -1,4 +1,26 @@
use crate::*;
enum SequencerCommand {
FocusNext,
FocusPrev,
FocusUp,
FocusDown,
FocusLeft,
FocusRight,
Transport(TransportCommand),
Phrase(PhrasePoolCommand),
Editor(PhraseEditorCommand),
}
enum PhrasePoolCommand {
}
enum PhraseLengthCommand {
}
enum PhraseEditorCommand {
}
/// Handle top-level events in standalone sequencer.
impl Handle<Tui> for Sequencer<Tui> {
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {

View file

@ -1,55 +1,172 @@
use crate::*;
impl Handle<Tui> for TransportToolbar<Tui> {
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Left) => { self.focus.prev(); },
key!(KeyCode::Right) => { self.focus.next(); },
_ => match self.focus {
TransportToolbarFocus::PlayPause => return self.handle_play_pause(from),
TransportToolbarFocus::Bpm => return self.handle_bpm(from),
TransportToolbarFocus::Quant => return self.handle_quant(from),
TransportToolbarFocus::Sync => return self.handle_sync(from),
TransportToolbarFocus::Clock => {/*todo*/},
}
if let TuiEvent::Input(crossterm::event::Event::Key(event)) = from.event() {
let _undo = self.handle_key(event)?;
return Ok(Some(true))
}
Ok(Some(true))
Ok(None)
}
}
impl TransportToolbar<Tui> {
fn handle_play_pause (&mut self, from: &TuiInput) -> Perhaps<bool> {
match from.event() {
key!(KeyCode::Enter) => self.toggle_play().map(|_|())?,
_ => return Ok(None)
#[derive(Clone)]
pub enum TransportCommand {
FocusNext,
FocusPrev,
PlayFromStart,
TogglePlay,
Increment,
Decrement,
FineIncrement,
FineDecrement,
SeekUsec(f64),
SeekSample(f64),
SeekPulse(f64),
SetBpm(f64),
SetQuant(f64),
SetSync(f64),
}
impl HandleKey<TransportCommand> for TransportToolbar<Tui> {
const HANDLE_KEY_MAP: &'static [(KeyEvent, TransportCommand)] = &[
( key(KeyCode::Char(' ')), TransportCommand::FocusPrev),
(shift(key(KeyCode::Char(' '))), TransportCommand::FocusPrev),
( key(KeyCode::Left), TransportCommand::FocusPrev),
( key(KeyCode::Right), TransportCommand::FocusNext),
( key(KeyCode::Char('.')), TransportCommand::Increment),
( key(KeyCode::Char(',')), TransportCommand::Decrement),
( key(KeyCode::Char('>')), TransportCommand::FineIncrement),
( key(KeyCode::Char('<')), TransportCommand::FineDecrement),
];
}
impl<E: Engine> Command<TransportToolbar<E>> for TransportCommand {
fn run (&self, state: &mut TransportToolbar<E>) -> Perhaps<Self> {
match self {
Self::FocusNext => {
state.focus.next();
},
Self::FocusPrev => {
state.focus.prev();
},
Self::TogglePlay => {
state.toggle_play()?;
},
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*/
},
}
},
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!() }
}
Ok(Some(true))
}
fn handle_bpm (&mut self, from: &TuiInput) -> Perhaps<bool> {
let bpm = self.clock.timebase().bpm.get();
match from.event() {
key!(KeyCode::Char(',')) => { self.clock.timebase().bpm.set(bpm - 1.0); },
key!(KeyCode::Char('.')) => { self.clock.timebase().bpm.set(bpm + 1.0); },
key!(KeyCode::Char('<')) => { self.clock.timebase().bpm.set(bpm - 0.001); },
key!(KeyCode::Char('>')) => { self.clock.timebase().bpm.set(bpm + 0.001); },
_ => return Ok(None)
}
Ok(Some(true))
}
fn handle_quant (&mut self, from: &TuiInput) -> Perhaps<bool> {
let quant = self.clock.quant.get() as usize;
match from.event() {
key!(KeyCode::Char(',')) => { self.clock.quant.set(prev_note_length(quant) as f64); },
key!(KeyCode::Char('.')) => { self.clock.quant.set(next_note_length(quant) as f64); },
_ => return Ok(None)
}
return Ok(Some(true))
}
fn handle_sync (&mut self, from: &TuiInput) -> Perhaps<bool> {
let sync = self.clock.sync.get() as usize;
match from.event() {
key!(KeyCode::Char(',')) => { self.clock.quant.set(prev_note_length(sync) as f64); },
key!(KeyCode::Char('.')) => { self.clock.quant.set(next_note_length(sync) as f64); },
_ => return Ok(None)
}
return Ok(Some(true))
Ok(None)
}
}