mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
update event handling for sequencer
This commit is contained in:
parent
7186ec3979
commit
44b94d2b1a
3 changed files with 21 additions and 24 deletions
|
|
@ -3,9 +3,6 @@ name = "tek"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
lto = true
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#no_deadlocks = "1.3.2"
|
#no_deadlocks = "1.3.2"
|
||||||
#vst3 = "0.1.0"
|
#vst3 = "0.1.0"
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ pub struct SequencerTui {
|
||||||
pub(crate) player: PhrasePlayerModel,
|
pub(crate) player: PhrasePlayerModel,
|
||||||
pub(crate) editor: PhraseEditorModel,
|
pub(crate) editor: PhraseEditorModel,
|
||||||
pub(crate) size: Measure<Tui>,
|
pub(crate) size: Measure<Tui>,
|
||||||
pub(crate) show_pool: bool,
|
|
||||||
pub(crate) status: bool,
|
pub(crate) status: bool,
|
||||||
pub(crate) note_buf: Vec<u8>,
|
pub(crate) note_buf: Vec<u8>,
|
||||||
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
pub(crate) midi_buf: Vec<Vec<Vec<u8>>>,
|
||||||
|
|
@ -33,7 +32,6 @@ from_jack!(|jack|SequencerTui {
|
||||||
midi_buf: vec![vec![];65536],
|
midi_buf: vec![vec![];65536],
|
||||||
note_buf: vec![],
|
note_buf: vec![],
|
||||||
perf: PerfModel::default(),
|
perf: PerfModel::default(),
|
||||||
show_pool: true,
|
|
||||||
status: true,
|
status: true,
|
||||||
clock,
|
clock,
|
||||||
}
|
}
|
||||||
|
|
@ -41,7 +39,7 @@ from_jack!(|jack|SequencerTui {
|
||||||
render!(<Tui>|self: SequencerTui|{
|
render!(<Tui>|self: SequencerTui|{
|
||||||
let w = self.size.w();
|
let w = self.size.w();
|
||||||
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
|
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
|
||||||
let pool_w = if self.show_pool { phrase_w } else { 0 };
|
let pool_w = if self.phrases.visible { phrase_w } else { 0 };
|
||||||
let pool = Fill::h(Align::e(PoolView(&self.phrases)));
|
let pool = Fill::h(Align::e(PoolView(&self.phrases)));
|
||||||
let with_pool = move|x|Tui::split_w(false, pool_w, pool, x);
|
let with_pool = move|x|Tui::split_w(false, pool_w, pool, x);
|
||||||
let status = SequencerStatus::from(self);
|
let status = SequencerStatus::from(self);
|
||||||
|
|
@ -83,13 +81,15 @@ has_phrases!(|self:SequencerTui|self.phrases.phrases);
|
||||||
has_editor!(|self:SequencerTui|self.editor);
|
has_editor!(|self:SequencerTui|self.editor);
|
||||||
handle!(<Tui>|self:SequencerTui,input|SequencerCommand::execute_with_state(self, input));
|
handle!(<Tui>|self:SequencerTui,input|SequencerCommand::execute_with_state(self, input));
|
||||||
#[derive(Clone, Debug)] pub enum SequencerCommand {
|
#[derive(Clone, Debug)] pub enum SequencerCommand {
|
||||||
|
History(isize),
|
||||||
Clock(ClockCommand),
|
Clock(ClockCommand),
|
||||||
Phrases(PhrasesCommand),
|
Phrases(PhrasesCommand),
|
||||||
Editor(PhraseCommand),
|
Editor(PhraseCommand),
|
||||||
Enqueue(Option<Arc<RwLock<Phrase>>>),
|
Enqueue(Option<Arc<RwLock<Phrase>>>),
|
||||||
ShowPool(bool),
|
|
||||||
}
|
}
|
||||||
input_to_command!(SequencerCommand: <Tui>|state:SequencerTui,input|match input.event() {
|
input_to_command!(SequencerCommand: <Tui>|state: SequencerTui, input|match input.event() {
|
||||||
|
// TODO: k: toggle on-screen keyboard
|
||||||
|
key_pat!(Ctrl-Char('k')) => { todo!("keyboard") },
|
||||||
// Transport: Play/pause
|
// Transport: Play/pause
|
||||||
key_pat!(Char(' ')) => Clock(
|
key_pat!(Char(' ')) => Clock(
|
||||||
if state.clock().is_stopped() { Play(None) } else { Pause(None) }
|
if state.clock().is_stopped() { Play(None) } else { Pause(None) }
|
||||||
|
|
@ -98,14 +98,12 @@ input_to_command!(SequencerCommand: <Tui>|state:SequencerTui,input|match input.e
|
||||||
key_pat!(Shift-Char(' ')) => Clock(
|
key_pat!(Shift-Char(' ')) => Clock(
|
||||||
if state.clock().is_stopped() { Play(Some(0)) } else { Pause(Some(0)) }
|
if state.clock().is_stopped() { Play(Some(0)) } else { Pause(Some(0)) }
|
||||||
),
|
),
|
||||||
// TODO: u: undo
|
// u: undo
|
||||||
key_pat!(Char('u')) => { todo!("undo") },
|
key_pat!(Char('u')) => History(-1),
|
||||||
// TODO: Shift-U: redo
|
// Shift-U: redo
|
||||||
key_pat!(Char('U')) => { todo!("redo") },
|
key_pat!(Char('U')) => History( 1),
|
||||||
// TODO: k: toggle on-screen keyboard
|
|
||||||
key_pat!(Ctrl-Char('k')) => { todo!("keyboard") },
|
|
||||||
// Tab: Toggle visibility of phrase pool column
|
// Tab: Toggle visibility of phrase pool column
|
||||||
key_pat!(Tab) => ShowPool(!state.show_pool),
|
key_pat!(Tab) => Phrases(PhrasesCommand::Show(!state.phrases.visible)),
|
||||||
// q: Enqueue currently edited phrase
|
// q: Enqueue currently edited phrase
|
||||||
key_pat!(Char('q')) => Enqueue(Some(state.phrases.phrase().clone())),
|
key_pat!(Char('q')) => Enqueue(Some(state.phrases.phrase().clone())),
|
||||||
// 0: Enqueue phrase 0 (stop all)
|
// 0: Enqueue phrase 0 (stop all)
|
||||||
|
|
@ -164,8 +162,7 @@ command!(|self: SequencerCommand, state: SequencerTui|match self {
|
||||||
state.player.enqueue_next(phrase.as_ref());
|
state.player.enqueue_next(phrase.as_ref());
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
Self::ShowPool(value) => {
|
Self::History(delta) => {
|
||||||
state.show_pool = value;
|
todo!("undo/redo")
|
||||||
None
|
},
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,10 @@ impl Input<Tui> for TuiInput {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventMap<'a, const N: usize, E, T, U>(pub [(E, &'a dyn Fn(T) -> U); N]);
|
pub struct EventMap<'a, const N: usize, E, T, U>(
|
||||||
|
pub [(E, &'a dyn Fn(T) -> U); N],
|
||||||
|
pub Option<&'a dyn Fn(T) -> U>,
|
||||||
|
);
|
||||||
|
|
||||||
impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
||||||
pub fn handle (&self, context: T, event: &E) -> Option<U> {
|
pub fn handle (&self, context: T, event: &E) -> Option<U> {
|
||||||
|
|
@ -74,11 +77,11 @@ impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
||||||
|
|
||||||
#[macro_export] macro_rules! event_map {
|
#[macro_export] macro_rules! event_map {
|
||||||
($events:expr) => {
|
($events:expr) => {
|
||||||
EventMap($events)
|
EventMap($events, None)
|
||||||
|
};
|
||||||
|
($events:expr, $default: expr) => {
|
||||||
|
EventMap($events, $default)
|
||||||
};
|
};
|
||||||
(|$state:ident|{$([$char:expr] = [$handler:expr]),*}) => {
|
|
||||||
EventMap([$((&$char, &|$state|$handler),),*])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export] macro_rules! kexp {
|
#[macro_export] macro_rules! kexp {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue