mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: EdnKeymap
This commit is contained in:
parent
8dcf73c18c
commit
364d617d37
6 changed files with 144 additions and 135 deletions
|
|
@ -1,30 +1,32 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use EdnItem::*;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait EdnControlData<E: Input> {}
|
/// Turns an EDN symbol sequence into a command enum variant.
|
||||||
|
|
||||||
/// Renders from EDN source and context.
|
|
||||||
#[derive(Default)]
|
|
||||||
pub enum EdnControls<E: Input, T: EdnControlData<E>> {
|
|
||||||
#[default]
|
|
||||||
Inert,
|
|
||||||
_Unused(PhantomData<E>),
|
|
||||||
Ok(T, EdnItem<String>),
|
|
||||||
Err(String)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Input, T: EdnControlData<E>> EdnControls<E, T> {
|
|
||||||
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()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait EdnCommand<C>: Command<C> {
|
pub trait EdnCommand<C>: Command<C> {
|
||||||
fn from_edn <'a> (state: &C, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self;
|
fn from_edn <'a> (state: &C, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait EdnInput: Input {
|
||||||
|
fn matches (&self, token: &str) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EdnKeymap(pub Vec<EdnItem<String>>);
|
||||||
|
|
||||||
|
impl EdnKeymap {
|
||||||
|
pub fn command <C, D: Command<C>, E: EdnCommand<C>, I: EdnInput> (&self, state: &C, input: &I) -> Option<E> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
23
midi/edn/midi_keys.edn
Normal file
23
midi/edn/midi_keys.edn
Normal file
|
|
@ -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)))
|
||||||
1
midi/edn/pool_keys.edn
Normal file
1
midi/edn/pool_keys.edn
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
;TODO
|
||||||
|
|
@ -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)))
|
|
||||||
|
|
@ -1,23 +1,78 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
use EdnItem::*;
|
||||||
use ClockCommand::{Play, Pause};
|
use ClockCommand::{Play, Pause};
|
||||||
use self::ArrangerCommand as Cmd;
|
use self::ArrangerCommand as Cmd;
|
||||||
pub const TRACK_MIN_WIDTH: usize = 9;
|
pub const TRACK_MIN_WIDTH: usize = 9;
|
||||||
impl Arrangement for App {
|
command!(|self: ClipCommand, state: App|match self { _ => todo!("clip command") });
|
||||||
fn tracks (&self) -> &Vec<ArrangerTrack> { &self.tracks }
|
command!(|self: SceneCommand, state: App|match self { _ => todo!("scene command") });
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> { &mut self.tracks }
|
command!(|self: TrackCommand, state: App|match self { _ => todo!("track command") });
|
||||||
fn scenes (&self) -> &Vec<ArrangerScene> { &self.scenes }
|
#[derive(Clone, Debug)] pub enum ClipCommand {
|
||||||
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> { &mut self.scenes }
|
Get(usize, usize),
|
||||||
fn selected (&self) -> &ArrangerSelection { &self.selected }
|
Put(usize, usize, Option<Arc<RwLock<MidiClip>>>),
|
||||||
fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected }
|
Enqueue(usize, usize),
|
||||||
|
Edit(Option<Arc<RwLock<MidiClip>>>),
|
||||||
|
SetLoop(usize, usize, bool),
|
||||||
|
SetColor(usize, usize, ItemPalette),
|
||||||
|
}
|
||||||
|
impl EdnCommand<App> for ClipCommand {
|
||||||
|
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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<App> for SceneCommand {
|
||||||
|
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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<App> for TrackCommand {
|
||||||
|
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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<ArrangerTrack> { &self.tracks }
|
|
||||||
//fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> { &mut self.tracks }
|
|
||||||
//fn scenes (&self) -> &Vec<ArrangerScene> { &self.scenes }
|
|
||||||
//fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> { &mut self.scenes }
|
|
||||||
//fn selected (&self) -> &ArrangerSelection { &self.selected }
|
|
||||||
//fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected }
|
|
||||||
//}
|
|
||||||
pub trait Arrangement: HasClock + HasJack {
|
pub trait Arrangement: HasClock + HasJack {
|
||||||
fn tracks (&self) -> &Vec<ArrangerTrack>;
|
fn tracks (&self) -> &Vec<ArrangerTrack>;
|
||||||
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack>;
|
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack>;
|
||||||
|
|
@ -283,3 +338,19 @@ impl ArrangerSelection {
|
||||||
}).into()
|
}).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Arrangement for App {
|
||||||
|
fn tracks (&self) -> &Vec<ArrangerTrack> { &self.tracks }
|
||||||
|
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> { &mut self.tracks }
|
||||||
|
fn scenes (&self) -> &Vec<ArrangerScene> { &self.scenes }
|
||||||
|
fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> { &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<ArrangerTrack> { &self.tracks }
|
||||||
|
//fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> { &mut self.tracks }
|
||||||
|
//fn scenes (&self) -> &Vec<ArrangerScene> { &self.scenes }
|
||||||
|
//fn scenes_mut (&mut self) -> &mut Vec<ArrangerScene> { &mut self.scenes }
|
||||||
|
//fn selected (&self) -> &ArrangerSelection { &self.selected }
|
||||||
|
//fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected }
|
||||||
|
//}
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,14 @@ impl EdnCommand<App> for AppCommand {
|
||||||
(Key("select"), [a]) => Self::Select(ArrangerSelection::Mix),
|
(Key("select"), [a]) => Self::Select(ArrangerSelection::Mix),
|
||||||
(Key("zoom"), [a]) => Self::Zoom(0),
|
(Key("zoom"), [a]) => Self::Zoom(0),
|
||||||
|
|
||||||
(Key("clock"), [a, b @ ..]) => Self::Clock(ClockCommand::from_edn(state, &a.to_ref(), b)),
|
(Key("clock"), [a, b @ ..]) => Self::Clock(
|
||||||
(Key("track"), [a, b @ ..]) => Self::Track(TrackCommand::from_edn(state, &a.to_ref(), b)),
|
ClockCommand::from_edn(state, &a.to_ref(), b)),
|
||||||
(Key("scene"), [a, b @ ..]) => Self::Scene(SceneCommand::from_edn(state, &a.to_ref(), b)),
|
(Key("track"), [a, b @ ..]) => Self::Track(
|
||||||
(Key("clip"), [a, b @ ..]) => Self::Clip(ClipCommand::from_edn(state, &a.to_ref(), b)),
|
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() =>
|
(Key("pool"), [a, b @ ..]) if let Some(pool) = state.pool.as_ref() =>
|
||||||
Self::Pool(PoolCommand::from_edn(pool, &a.to_ref(), b)),
|
Self::Pool(PoolCommand::from_edn(pool, &a.to_ref(), b)),
|
||||||
|
|
@ -147,76 +151,6 @@ command!(|self: AppCommand, state: App|match self {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
#[derive(Clone, Debug)] pub enum ClipCommand {
|
|
||||||
Get(usize, usize),
|
|
||||||
Put(usize, usize, Option<Arc<RwLock<MidiClip>>>),
|
|
||||||
Enqueue(usize, usize),
|
|
||||||
Edit(Option<Arc<RwLock<MidiClip>>>),
|
|
||||||
SetLoop(usize, usize, bool),
|
|
||||||
SetColor(usize, usize, ItemPalette),
|
|
||||||
}
|
|
||||||
impl EdnCommand<App> for ClipCommand {
|
|
||||||
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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<App> for SceneCommand {
|
|
||||||
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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<App> for TrackCommand {
|
|
||||||
fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem<String>]) -> 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 {
|
#[derive(Clone, Debug)] pub enum SequencerCommand {
|
||||||
Compact(bool),
|
Compact(bool),
|
||||||
History(isize),
|
History(isize),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue