diff --git a/Cargo.lock b/Cargo.lock index 818ce2c4..1238a4d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,6 +1446,9 @@ dependencies = [ [[package]] name = "tek_input" version = "0.2.0" +dependencies = [ + "tek_edn", +] [[package]] name = "tek_jack" diff --git a/input/Cargo.toml b/input/Cargo.toml index 7373ceb3..76504c2a 100644 --- a/input/Cargo.toml +++ b/input/Cargo.toml @@ -4,3 +4,4 @@ edition = "2021" version = "0.2.0" [dependencies] +tek_edn = { path = "../edn" } diff --git a/input/src/edn_cmd.rs b/input/src/edn_cmd.rs new file mode 100644 index 00000000..ea485a3b --- /dev/null +++ b/input/src/edn_cmd.rs @@ -0,0 +1,30 @@ +use crate::*; +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())) + } +} + +pub trait EdnCommand: Command { + fn from_edn <'a> (state: &C, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self; +} diff --git a/input/src/lib.rs b/input/src/lib.rs index 6800ab87..c96dfe48 100644 --- a/input/src/lib.rs +++ b/input/src/lib.rs @@ -5,7 +5,9 @@ mod input; pub use self::input::*; mod handle; pub use self::handle::*; mod command; pub use self::command::*; mod event_map; pub use self::event_map::*; +mod edn_cmd; pub use self::edn_cmd::*; +pub(crate) use ::tek_edn::EdnItem; /// Standard error trait. pub(crate) use std::error::Error; /// Standard result type. diff --git a/tek/src/audio.rs b/tek/src/audio.rs index b3b98eff..0ad1613c 100644 --- a/tek/src/audio.rs +++ b/tek/src/audio.rs @@ -101,6 +101,30 @@ audio!(|self: App, client, scope|{ Control::Continue }); +/// Hosts the JACK callback for a collection of tracks +pub struct TracksAudio<'a>( + // Track collection + pub &'a mut [ArrangerTrack], + /// Note buffer + pub &'a mut Vec, + /// Note chunk buffer + pub &'a mut Vec>>, +); + +impl Audio for TracksAudio<'_> { + #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { + let model = &mut self.0; + let note_buffer = &mut self.1; + let output_buffer = &mut self.2; + for track in model.iter_mut() { + if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit { + return Control::Quit + } + } + Control::Continue + } +} + //audio!(|self: Sequencer, client, scope|{ //// Start profiling cycle //let t0 = self.perf.get_t0(); @@ -206,27 +230,3 @@ audio!(|self: App, client, scope|{ //self.perf.update(t0, scope); //return Control::Continue //}); - -/// Hosts the JACK callback for a collection of tracks -pub struct TracksAudio<'a>( - // Track collection - pub &'a mut [ArrangerTrack], - /// Note buffer - pub &'a mut Vec, - /// Note chunk buffer - pub &'a mut Vec>>, -); - -impl Audio for TracksAudio<'_> { - #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - let model = &mut self.0; - let note_buffer = &mut self.1; - let output_buffer = &mut self.2; - for track in model.iter_mut() { - if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit { - return Control::Quit - } - } - Control::Continue - } -} diff --git a/tek/src/control.rs b/tek/src/control.rs index 7d5cb1a2..5b096d90 100644 --- a/tek/src/control.rs +++ b/tek/src/control.rs @@ -31,126 +31,43 @@ handle!(TuiIn: |self: App, input| Ok(None)); Track(TrackCommand), Zoom(usize), } -impl AppCommand { - pub fn from_edn <'a> (head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { +impl EdnCommand for AppCommand { + fn from_edn <'a> (state: &App, head: &EdnItem<&str>, tail: &'a [EdnItem]) -> Self { match (head, tail) { - (Key("clear"), [ ]) => Self::Clear, - (Key("clip"), [a, b @ ..]) => Self::Clip(ClipCommand::from_edn(&a.to_ref(), b)), - (Key("clock"), [a, b @ ..]) => Self::Clock(ClockCommand::from_edn(&a.to_ref(), b)), - (Key("color"), [a ]) => Self::Color(ItemPalette::default()), - (Key("compact"), [a ]) => Self::Compact(true), - (Key("editor"), [a, b @ ..]) => Self::Editor(MidiEditCommand::from_edn(&a.to_ref(), b)), - (Key("enqueue"), [a ]) => Self::Enqueue(None), - (Key("history"), [a ]) => Self::History(0), - (Key("pool"), [a, b @ ..]) => Self::Pool(PoolCommand::from_edn(&a.to_ref(), b)), - (Key("sampler"), [a, b @ ..]) => Self::Sampler(SamplerCommand::from_edn(&a.to_ref(), b)), - (Key("scene"), [a, b @ ..]) => Self::Scene(SceneCommand::from_edn(&a.to_ref(), b)), - (Key("select"), [a ]) => Self::Select(ArrangerSelection::Mix), - (Key("stop-all"), [ ]) => Self::StopAll, - (Key("track"), [a, b @ ..]) => Self::Track(TrackCommand::from_edn(&a.to_ref(), b)), - (Key("zoom"), [a ]) => Self::Zoom(0), + (Key("clear"), [ ]) => + Self::Clear, + (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("color"), [a ]) => + Self::Color(ItemPalette::default()), + (Key("compact"), [a ]) => + Self::Compact(true), + (Key("editor"), [a, b @ ..]) => + Self::Editor(MidiEditCommand::from_edn(state, &a.to_ref(), b)), + (Key("enqueue"), [a ]) => + Self::Enqueue(None), + (Key("history"), [a ]) => + Self::History(0), + (Key("pool"), [a, b @ ..]) => + Self::Pool(PoolCommand::from_edn(state, &a.to_ref(), b)), + (Key("sampler"), [a, b @ ..]) => + Self::Sampler(SamplerCommand::from_edn(state, &a.to_ref(), b)), + (Key("scene"), [a, b @ ..]) => + Self::Scene(SceneCommand::from_edn(state, &a.to_ref(), b)), + (Key("select"), [a ]) => + Self::Select(ArrangerSelection::Mix), + (Key("stop-all"), [ ]) => + Self::StopAll, + (Key("track"), [a, b @ ..]) => + Self::Track(TrackCommand::from_edn(state, &a.to_ref(), b)), + (Key("zoom"), [a ]) => + Self::Zoom(0), _ => panic!(), } } } -#[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 ClipCommand { - pub fn from_edn <'a> (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 SceneCommand { - pub fn from_edn <'a> (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 TrackCommand { - pub fn from_edn <'a> (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!(), - } - } -} -#[derive(Clone, Debug)] pub enum SequencerCommand { - Compact(bool), - History(isize), - Clock(ClockCommand), - Pool(PoolCommand), - Editor(MidiEditCommand), - Enqueue(Option>>), -} -#[derive(Clone, Debug)] pub enum GrooveboxCommand { - Compact(bool), - History(isize), - Clock(ClockCommand), - Pool(PoolCommand), - Editor(MidiEditCommand), - Enqueue(Option>>), - Sampler(SamplerCommand), -} -#[derive(Clone, Debug)] pub enum ArrangerCommand { - History(isize), - Color(ItemPalette), - Clock(ClockCommand), - Scene(SceneCommand), - Track(TrackCommand), - Clip(ClipCommand), - Select(ArrangerSelection), - Zoom(usize), - Pool(PoolCommand), - Editor(MidiEditCommand), - StopAll, - Clear, -} command!(|self: AppCommand, state: App|match self { Self::Clear => { todo!() }, Self::Zoom(_) => { todo!(); }, @@ -238,6 +155,107 @@ 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), + Clock(ClockCommand), + Pool(PoolCommand), + Editor(MidiEditCommand), + Enqueue(Option>>), +} +#[derive(Clone, Debug)] pub enum GrooveboxCommand { + Compact(bool), + History(isize), + Clock(ClockCommand), + Pool(PoolCommand), + Editor(MidiEditCommand), + Enqueue(Option>>), + Sampler(SamplerCommand), +} +#[derive(Clone, Debug)] pub enum ArrangerCommand { + History(isize), + Color(ItemPalette), + Clock(ClockCommand), + Scene(SceneCommand), + Track(TrackCommand), + Clip(ClipCommand), + Select(ArrangerSelection), + Zoom(usize), + Pool(PoolCommand), + Editor(MidiEditCommand), + StopAll, + Clear, +} //command!(|self: SequencerCommand, state: Sequencer|match self { //Self::Clock(cmd) => cmd.delegate(state, Self::Clock)?, diff --git a/tui/src/tui_edn_keymap.rs b/tui/src/tui_edn_keymap.rs index 21fd7f79..e69de29b 100644 --- a/tui/src/tui_edn_keymap.rs +++ b/tui/src/tui_edn_keymap.rs @@ -1,26 +0,0 @@ -use crate::*; -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())) - } -}