From 364d617d37af1aa4fe9a63b8da3bb576c61b391d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 12 Jan 2025 01:48:43 +0100 Subject: [PATCH] wip: EdnKeymap --- input/src/edn_cmd.rs | 50 ++++++++++---------- midi/edn/midi_keys.edn | 23 ++++++++++ midi/edn/pool_keys.edn | 1 + midi/src/midi_keys.edn | 22 --------- tek/src/arranger.rs | 101 +++++++++++++++++++++++++++++++++++------ tek/src/control.rs | 82 ++++----------------------------- 6 files changed, 144 insertions(+), 135 deletions(-) create mode 100644 midi/edn/midi_keys.edn create mode 100644 midi/edn/pool_keys.edn delete mode 100644 midi/src/midi_keys.edn diff --git a/input/src/edn_cmd.rs b/input/src/edn_cmd.rs index ea485a3b..0cb70726 100644 --- a/input/src/edn_cmd.rs +++ b/input/src/edn_cmd.rs @@ -1,30 +1,32 @@ use crate::*; +use EdnItem::*; use std::marker::PhantomData; -pub trait EdnControlData {} - -/// Renders from EDN source and context. -#[derive(Default)] -pub enum EdnControls> { - #[default] - Inert, - _Unused(PhantomData), - Ok(T, EdnItem), - Err(String) -} - -impl> EdnControls { - pub fn from_source (state: T, source: &str) -> Self { - match EdnItem::read_one(&source) { - Ok((layout, _)) => Self::Ok(state, layout), - Err(error) => Self::Err(format!("{error}")) - } - } - pub fn from_items (state: T, items: &[EdnItem<&str>]) -> Self { - Self::Ok(state, EdnItem::Exp(items.iter().map(|i|(*i).clone()).collect())) - } -} - +/// Turns an EDN symbol sequence into a command enum variant. pub trait EdnCommand: Command { fn from_edn <'a> (state: &C, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self; } + +pub trait EdnInput: Input { + fn matches (&self, token: &str) -> bool; +} + +pub struct EdnKeymap(pub Vec>); + +impl EdnKeymap { + pub fn command , E: EdnCommand, I: EdnInput> (&self, state: &C, input: &I) -> Option { + for item in self.0.iter() { + if let Exp(items) = item { + match items.as_slice() { + [Key(a), b, c @ ..] => if input.matches(a.as_str()) { + return Some(E::from_edn(state, &b.to_ref(), c)) + }, + _ => unreachable!() + } + } else { + unreachable!() + } + } + None + } +} diff --git a/midi/edn/midi_keys.edn b/midi/edn/midi_keys.edn new file mode 100644 index 00000000..ac461cb0 --- /dev/null +++ b/midi/edn/midi_keys.edn @@ -0,0 +1,23 @@ +(@enter note/put) +(@del note/del) +(@"," note/duration/dec) +(@"." note/duration/inc) +(@"+" note/scale/inc) +(@"-" note/scale/dec) +(@up note/cursor/inc) +(@down note/cursor/dec) + +(@left time/cursor/dec) +(@right time/cursor/inc) +(@"z" time/zoom/lock) +(@"=" time/zoom/in) +(@"-" time/zoom/out) + +;(@ctrl-k (midi/kbd/toggle)) +;(@space (clock/toggle)) +;(@shift-space (clock/toggle-start)) +;(@u (undo)) +;(@shift-u (redo)) +;(@tab (compact/toggle)) +;(@q (player/enqueue :clip)) +;(@0 (player/enqueue :stop))) diff --git a/midi/edn/pool_keys.edn b/midi/edn/pool_keys.edn new file mode 100644 index 00000000..08d1b928 --- /dev/null +++ b/midi/edn/pool_keys.edn @@ -0,0 +1 @@ +;TODO diff --git a/midi/src/midi_keys.edn b/midi/src/midi_keys.edn deleted file mode 100644 index baf6979e..00000000 --- a/midi/src/midi_keys.edn +++ /dev/null @@ -1,22 +0,0 @@ -(@up (note/cursor/inc)) -(@down (note/cursor/dec)) -(@left (time/cursor/dec)) -(@right (time/cursor/inc)) -(@z (time/zoom/lock)) -(@= (time/zoom/in)) -(@- (time/zoom/out)) -(@+ (note/scale/inc)) -(@- (note/scale/dec)) -(@enter (note/put)) -(@del (note/del)) -(@, (note/duration/dec)) -(@. (note/duration/inc)) - -;(@ctrl-k (midi/kbd/toggle)) -;(@space (clock/toggle)) -;(@shift-space (clock/toggle-start)) -;(@u (undo)) -;(@shift-u (redo)) -;(@tab (compact/toggle)) -;(@q (player/enqueue :clip)) -;(@0 (player/enqueue :stop))) diff --git a/tek/src/arranger.rs b/tek/src/arranger.rs index 17fbb306..8b3a1daa 100644 --- a/tek/src/arranger.rs +++ b/tek/src/arranger.rs @@ -1,23 +1,78 @@ use crate::*; +use EdnItem::*; use ClockCommand::{Play, Pause}; use self::ArrangerCommand as Cmd; pub const TRACK_MIN_WIDTH: usize = 9; -impl Arrangement for App { - fn tracks (&self) -> &Vec { &self.tracks } - fn tracks_mut (&mut self) -> &mut Vec { &mut self.tracks } - fn scenes (&self) -> &Vec { &self.scenes } - fn scenes_mut (&mut self) -> &mut Vec { &mut self.scenes } - fn selected (&self) -> &ArrangerSelection { &self.selected } - fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected } +command!(|self: ClipCommand, state: App|match self { _ => todo!("clip command") }); +command!(|self: SceneCommand, state: App|match self { _ => todo!("scene command") }); +command!(|self: TrackCommand, state: App|match self { _ => todo!("track command") }); +#[derive(Clone, Debug)] pub enum ClipCommand { + Get(usize, usize), + Put(usize, usize, Option>>), + Enqueue(usize, usize), + Edit(Option>>), + SetLoop(usize, usize, bool), + SetColor(usize, usize, ItemPalette), +} +impl EdnCommand for ClipCommand { + fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { + match (head, tail) { + (Key("get"), [a, b ]) => Self::Get(0, 0), + (Key("put"), [a, b, c ]) => Self::Put(0, 0, None), + (Key("enqueue"), [a, b ]) => Self::Enqueue(0, 0), + (Key("edit"), [a ]) => Self::Edit(None), + (Key("loop"), [a, b, c ]) => Self::SetLoop(0, 0, true), + (Key("color"), [a, b, c ]) => Self::SetColor(0, 0, ItemPalette::random()), + _ => panic!(), + } + } +} +#[derive(Clone, Debug)] pub enum SceneCommand { + Add, + Del(usize), + Swap(usize, usize), + SetSize(usize), + SetZoom(usize), + SetColor(usize, ItemPalette), + Enqueue(usize), +} +impl EdnCommand for SceneCommand { + fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { + match (head, tail) { + (Key("add"), [ ]) => Self::Add, + (Key("del"), [a ]) => Self::Del(0), + (Key("swap"), [a, b ]) => Self::Swap(0, 0), + (Key("size"), [a ]) => Self::SetSize(0), + (Key("zoom"), [a, ]) => Self::SetZoom(0), + (Key("color"), [a, b, ]) => Self::SetColor(0, ItemPalette::random()), + (Key("enqueue"), [a, ]) => Self::Enqueue(0), + _ => panic!(), + } + } +} +#[derive(Clone, Debug)] pub enum TrackCommand { + Add, + Del(usize), + Stop(usize), + Swap(usize, usize), + SetSize(usize), + SetZoom(usize), + SetColor(usize, ItemPalette), +} +impl EdnCommand for TrackCommand { + fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { + match (head, tail) { + (Key("add"), [ ]) => Self::Add, + (Key("del"), [a ]) => Self::Del(0), + (Key("stop"), [a ]) => Self::Stop(0), + (Key("swap"), [a, b ]) => Self::Swap(0, 0), + (Key("size"), [a ]) => Self::SetSize(0), + (Key("zoom"), [a, ]) => Self::SetZoom(0), + (Key("color"), [a, b, ]) => Self::SetColor(0, ItemPalette::random()), + _ => panic!(), + } + } } -//impl Arrangement for Arranger { - //fn tracks (&self) -> &Vec { &self.tracks } - //fn tracks_mut (&mut self) -> &mut Vec { &mut self.tracks } - //fn scenes (&self) -> &Vec { &self.scenes } - //fn scenes_mut (&mut self) -> &mut Vec { &mut self.scenes } - //fn selected (&self) -> &ArrangerSelection { &self.selected } - //fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected } -//} pub trait Arrangement: HasClock + HasJack { fn tracks (&self) -> &Vec; fn tracks_mut (&mut self) -> &mut Vec; @@ -283,3 +338,19 @@ impl ArrangerSelection { }).into() } } +impl Arrangement for App { + fn tracks (&self) -> &Vec { &self.tracks } + fn tracks_mut (&mut self) -> &mut Vec { &mut self.tracks } + fn scenes (&self) -> &Vec { &self.scenes } + fn scenes_mut (&mut self) -> &mut Vec { &mut self.scenes } + fn selected (&self) -> &ArrangerSelection { &self.selected } + fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected } +} +//impl Arrangement for Arranger { + //fn tracks (&self) -> &Vec { &self.tracks } + //fn tracks_mut (&mut self) -> &mut Vec { &mut self.tracks } + //fn scenes (&self) -> &Vec { &self.scenes } + //fn scenes_mut (&mut self) -> &mut Vec { &mut self.scenes } + //fn selected (&self) -> &ArrangerSelection { &self.selected } + //fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected } +//} diff --git a/tek/src/control.rs b/tek/src/control.rs index 49a7268d..10f077c8 100644 --- a/tek/src/control.rs +++ b/tek/src/control.rs @@ -44,10 +44,14 @@ impl EdnCommand for AppCommand { (Key("select"), [a]) => Self::Select(ArrangerSelection::Mix), (Key("zoom"), [a]) => Self::Zoom(0), - (Key("clock"), [a, b @ ..]) => Self::Clock(ClockCommand::from_edn(state, &a.to_ref(), b)), - (Key("track"), [a, b @ ..]) => Self::Track(TrackCommand::from_edn(state, &a.to_ref(), b)), - (Key("scene"), [a, b @ ..]) => Self::Scene(SceneCommand::from_edn(state, &a.to_ref(), b)), - (Key("clip"), [a, b @ ..]) => Self::Clip(ClipCommand::from_edn(state, &a.to_ref(), b)), + (Key("clock"), [a, b @ ..]) => Self::Clock( + ClockCommand::from_edn(state, &a.to_ref(), b)), + (Key("track"), [a, b @ ..]) => Self::Track( + TrackCommand::from_edn(state, &a.to_ref(), b)), + (Key("scene"), [a, b @ ..]) => Self::Scene( + SceneCommand::from_edn(state, &a.to_ref(), b)), + (Key("clip"), [a, b @ ..]) => Self::Clip( + ClipCommand::from_edn(state, &a.to_ref(), b)), (Key("pool"), [a, b @ ..]) if let Some(pool) = state.pool.as_ref() => Self::Pool(PoolCommand::from_edn(pool, &a.to_ref(), b)), @@ -147,76 +151,6 @@ command!(|self: AppCommand, state: App|match self { None }, }); -#[derive(Clone, Debug)] pub enum ClipCommand { - Get(usize, usize), - Put(usize, usize, Option>>), - Enqueue(usize, usize), - Edit(Option>>), - SetLoop(usize, usize, bool), - SetColor(usize, usize, ItemPalette), -} -impl EdnCommand for ClipCommand { - fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { - match (head, tail) { - (Key("get"), [a, b ]) => Self::Get(0, 0), - (Key("put"), [a, b, c ]) => Self::Put(0, 0, None), - (Key("enqueue"), [a, b ]) => Self::Enqueue(0, 0), - (Key("edit"), [a ]) => Self::Edit(None), - (Key("loop"), [a, b, c ]) => Self::SetLoop(0, 0, true), - (Key("color"), [a, b, c ]) => Self::SetColor(0, 0, ItemPalette::random()), - _ => panic!(), - } - } -} -command!(|self: ClipCommand, state: App|match self { _ => todo!("clip command") }); -#[derive(Clone, Debug)] pub enum SceneCommand { - Add, - Del(usize), - Swap(usize, usize), - SetSize(usize), - SetZoom(usize), - SetColor(usize, ItemPalette), - Enqueue(usize), -} -impl EdnCommand for SceneCommand { - fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { - match (head, tail) { - (Key("add"), [ ]) => Self::Add, - (Key("del"), [a ]) => Self::Del(0), - (Key("swap"), [a, b ]) => Self::Swap(0, 0), - (Key("size"), [a ]) => Self::SetSize(0), - (Key("zoom"), [a, ]) => Self::SetZoom(0), - (Key("color"), [a, b, ]) => Self::SetColor(0, ItemPalette::random()), - (Key("enqueue"), [a, ]) => Self::Enqueue(0), - _ => panic!(), - } - } -} -command!(|self: SceneCommand, state: App|match self { _ => todo!("scene command") }); -#[derive(Clone, Debug)] pub enum TrackCommand { - Add, - Del(usize), - Stop(usize), - Swap(usize, usize), - SetSize(usize), - SetZoom(usize), - SetColor(usize, ItemPalette), -} -impl EdnCommand for TrackCommand { - fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { - match (head, tail) { - (Key("add"), [ ]) => Self::Add, - (Key("del"), [a ]) => Self::Del(0), - (Key("stop"), [a ]) => Self::Stop(0), - (Key("swap"), [a, b ]) => Self::Swap(0, 0), - (Key("size"), [a ]) => Self::SetSize(0), - (Key("zoom"), [a, ]) => Self::SetZoom(0), - (Key("color"), [a, b, ]) => Self::SetColor(0, ItemPalette::random()), - _ => panic!(), - } - } -} -command!(|self: TrackCommand, state: App|match self { _ => todo!("track command") }); #[derive(Clone, Debug)] pub enum SequencerCommand { Compact(bool), History(isize),