From 39dc6b803eba6bf24b48c3cbcd037751edfea55d Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 26 Apr 2025 01:00:40 +0300 Subject: [PATCH] more appmode logic --- Cargo.lock | 10 ++--- crates/app/edn/groovebox_keys.edn | 9 ++++ crates/app/edn/sequencer_keys.edn | 8 ++++ crates/app/src/api.rs | 53 ---------------------- crates/app/src/keys.rs | 73 +++++++++++++++++++++++++++++++ crates/app/src/lib.rs | 1 + crates/app/src/model.rs | 32 ++++++++++++++ crates/cli/tek.rs | 56 +++++------------------- 8 files changed, 138 insertions(+), 104 deletions(-) create mode 100644 crates/app/edn/groovebox_keys.edn create mode 100644 crates/app/edn/sequencer_keys.edn create mode 100644 crates/app/src/keys.rs diff --git a/Cargo.lock b/Cargo.lock index fc37a383..5efbb450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1600,7 +1600,7 @@ dependencies = [ [[package]] name = "tengri" -version = "0.10.0" +version = "0.11.0" dependencies = [ "tengri_dsl", "tengri_input", @@ -1610,7 +1610,7 @@ dependencies = [ [[package]] name = "tengri_dsl" -version = "0.10.0" +version = "0.11.0" dependencies = [ "itertools 0.14.0", "konst", @@ -1619,21 +1619,21 @@ dependencies = [ [[package]] name = "tengri_input" -version = "0.10.0" +version = "0.11.0" dependencies = [ "tengri_dsl", ] [[package]] name = "tengri_output" -version = "0.10.0" +version = "0.11.0" dependencies = [ "tengri_dsl", ] [[package]] name = "tengri_tui" -version = "0.10.0" +version = "0.11.0" dependencies = [ "atomic_float", "better-panic", diff --git a/crates/app/edn/groovebox_keys.edn b/crates/app/edn/groovebox_keys.edn new file mode 100644 index 00000000..d03d652e --- /dev/null +++ b/crates/app/edn/groovebox_keys.edn @@ -0,0 +1,9 @@ +(@u undo 1) +(@shift-u redo 1) +(@space clock toggle) +(@shift-space clock toggle 0) +(@c color) +(@q launch) +(@shift-I input add) +(@shift-O output add) +(@r record/begin :sample) diff --git a/crates/app/edn/sequencer_keys.edn b/crates/app/edn/sequencer_keys.edn new file mode 100644 index 00000000..462e7ff4 --- /dev/null +++ b/crates/app/edn/sequencer_keys.edn @@ -0,0 +1,8 @@ +(@u undo 1) +(@shift-u redo 1) +(@space clock toggle) +(@shift-space clock toggle 0) +(@c color) +(@q launch) +(@shift-I input add) +(@shift-O output add) diff --git a/crates/app/src/api.rs b/crates/app/src/api.rs index f87b70f5..d95c92f3 100644 --- a/crates/app/src/api.rs +++ b/crates/app/src/api.rs @@ -542,56 +542,3 @@ impose!([app: Tek] { } }); - -handle!(TuiIn: |self: Tek, input|if let Some(handler) = self.handler { - handler(self, input) -} else { - Ok(None) -}); - -pub fn handle_arranger (app: &mut Tek, input: &TuiIn) -> Perhaps { - - // If editing, editor keys take priority - if app.is_editing() { - if app.editor.handle(input)? == Some(true) { - return Ok(Some(true)) - } - } - - // Handle from root keymap - if let Some(command) = SourceIter(include_str!("../edn/arranger_keys.edn")) - .command::<_, TekCommand, _>(app, input) - { - if let Some(undo) = command.execute(app)? { app.history.push(undo); } - return Ok(Some(true)) - } - - // Handle from selection-dependent keymaps - if let Some(command) = match app.selected() { - Selection::Clip(_, _) => SourceIter(include_str!("../edn/arranger_keys_clip.edn")), - Selection::Track(_) => SourceIter(include_str!("../edn/arranger_keys_track.edn")), - Selection::Scene(_) => SourceIter(include_str!("../edn/arranger_keys_scene.edn")), - Selection::Mix => SourceIter(include_str!("../edn/arranger_keys_mix.edn")), - }.command::<_, TekCommand, _>(app, input) { - if let Some(undo) = command.execute(app)? { - app.history.push(undo); - } - return Ok(Some(true)) - } - - Ok(None) - -} - -pub fn handle_sampler (app: &mut Tek, input: &TuiIn) -> Perhaps { - let sampler = app.tracks[0].sampler_mut(0).expect("no sampler"); - if let Some(command) = SourceIter(include_str!("../edn/sampler_keys.edn")) - .command::<_, SamplerCommand, _>(sampler, input) - { - if let Some(undo) = command.execute(sampler)? { - //app.history.push(undo); // TODO UNDO - } - return Ok(Some(true)) - } - Ok(None) -} diff --git a/crates/app/src/keys.rs b/crates/app/src/keys.rs new file mode 100644 index 00000000..753ca059 --- /dev/null +++ b/crates/app/src/keys.rs @@ -0,0 +1,73 @@ +use crate::*; + +handle!(TuiIn: |self: Tek, input|if let Some(handler) = self.handler { + handler(self, input) +} else { + Ok(None) +}); + +pub fn handle_arranger (app: &mut Tek, input: &TuiIn) -> Perhaps { + // If editing, editor keys take priority + if app.is_editing() { + if app.editor.handle(input)? == Some(true) { + return Ok(Some(true)) + } + } + // Handle from root keymap + if let Some(command) = SourceIter(include_str!("../edn/arranger_keys.edn")) + .command::<_, TekCommand, _>(app, input) + { + if let Some(undo) = command.execute(app)? { app.history.push(undo); } + return Ok(Some(true)) + } + // Handle from selection-dependent keymaps + if let Some(command) = match app.selected() { + Selection::Clip(_, _) => SourceIter(include_str!("../edn/arranger_keys_clip.edn")), + Selection::Track(_) => SourceIter(include_str!("../edn/arranger_keys_track.edn")), + Selection::Scene(_) => SourceIter(include_str!("../edn/arranger_keys_scene.edn")), + Selection::Mix => SourceIter(include_str!("../edn/arranger_keys_mix.edn")), + }.command::<_, TekCommand, _>(app, input) { + if let Some(undo) = command.execute(app)? { + app.history.push(undo); + } + return Ok(Some(true)) + } + Ok(None) +} + +pub fn handle_sequencer (app: &mut Tek, input: &TuiIn) -> Perhaps { + if let Some(command) = SourceIter(include_str!("../edn/sequencer_keys.edn")) + .command::<_, TekCommand, _>(app, input) + { + if let Some(undo) = command.execute(app)? { + app.history.push(undo); + } + return Ok(Some(true)) + } + Ok(None) +} + +pub fn handle_groovebox (app: &mut Tek, input: &TuiIn) -> Perhaps { + if let Some(command) = SourceIter(include_str!("../edn/groovebox_keys.edn")) + .command::<_, TekCommand, _>(app, input) + { + if let Some(undo) = command.execute(app)? { + app.history.push(undo); + } + return Ok(Some(true)) + } + Ok(None) +} + +pub fn handle_sampler (app: &mut Tek, input: &TuiIn) -> Perhaps { + let sampler = app.tracks[0].sampler_mut(0).expect("no sampler"); + if let Some(command) = SourceIter(include_str!("../edn/sampler_keys.edn")) + .command::<_, SamplerCommand, _>(sampler, input) + { + if let Some(undo) = command.execute(sampler)? { + //app.history.push(undo); // TODO UNDO + } + return Ok(Some(true)) + } + Ok(None) +} diff --git a/crates/app/src/lib.rs b/crates/app/src/lib.rs index fdad3826..4032b47c 100644 --- a/crates/app/src/lib.rs +++ b/crates/app/src/lib.rs @@ -41,6 +41,7 @@ mod audio; pub use self::audio::*; mod device; pub use self::device::*; mod model; pub use self::model::*; mod view; pub use self::view::*; +mod keys; pub use self::keys::*; #[cfg(test)] #[test] fn test_model () { let mut tek = Tek::default(); diff --git a/crates/app/src/model.rs b/crates/app/src/model.rs index f93a157c..8a876d9f 100644 --- a/crates/app/src/model.rs +++ b/crates/app/src/model.rs @@ -363,6 +363,38 @@ has_player!(|self: Track|self.player); impl Track { pub const MIN_WIDTH: usize = 9; + /// Create a new track containing a sequencer. + pub fn new_sequencer () -> Self { + let mut track = Self::default(); + track.devices.push(Device::Sequencer(MidiPlayer::default())); + track + } + /// Create a new track containing a sequencer and sampler. + pub fn new_groovebox ( + jack: &Jack, + midi_from: &[PortConnect], + audio_from: &[&[PortConnect];2], + audio_to: &[&[PortConnect];2], + ) -> Usually { + let mut track = Self::new_sequencer(); + track.devices.push(Device::Sampler( + Sampler::new(jack, &"sampler", midi_from, audio_from, audio_to)? + )); + Ok(track) + } + /// Create a new track containing a sampler. + pub fn new_sampler ( + jack: &Jack, + midi_from: &[PortConnect], + audio_from: &[&[PortConnect];2], + audio_to: &[&[PortConnect];2], + ) -> Usually { + let mut track = Self::default(); + track.devices.push(Device::Sampler( + Sampler::new(jack, &"sampler", midi_from, audio_from, audio_to)? + )); + Ok(track) + } pub fn width_inc (&mut self) { self.width += 1; } diff --git a/crates/cli/tek.rs b/crates/cli/tek.rs index ac00d7b5..1c514893 100644 --- a/crates/cli/tek.rs +++ b/crates/cli/tek.rs @@ -100,7 +100,9 @@ impl Cli { midi_outs.push(port); } let mut app = Tek { - jack: jack.clone(), + jack: jack.clone(), + color: ItemPalette::random(), + clock: Clock::new(jack, self.bpm)?, view: SourceIter(match mode { Mode::Clock => include_str!("./edn/transport.edn"), Mode::Sequencer => include_str!("./edn/sequencer.edn"), @@ -126,60 +128,22 @@ impl Cli { Mode::Sequencer | Mode::Groovebox | Mode::Arranger {..} => vec![vec![];65536], _ => todo!("{mode:?}"), }, - color: ItemPalette::random(), - clock: Clock::new(jack, self.bpm)?, - handler: Some(match mode { - Mode::Sampler => handle_sampler, - _ => handle_arranger, + Mode::Sequencer => handle_sequencer, + Mode::Groovebox => handle_groovebox, + Mode::Sampler => handle_sampler, + _ => handle_arranger, }), - tracks: match mode { - Mode::Sequencer => vec![ - Track { - devices: vec![ - Device::Sequencer( - MidiPlayer::default() - ), - ], - ..Track::default() - }, + Track::new_sequencer() ], - Mode::Groovebox => vec![ - Track { - devices: vec![ - Device::Sequencer( - MidiPlayer::default() - ), - Device::Sampler(Sampler::new( - jack, - &"sampler", - midi_froms.as_slice(), - audio_froms, - audio_tos - )?) - ], - ..Track::default() - } + Track::new_groovebox(jack, midi_froms.as_slice(), audio_froms, audio_tos)? ], - Mode::Sampler => vec![ - Track { - devices: vec![ - Device::Sampler(Sampler::new( - jack, - &"sampler", - midi_froms.as_slice(), - audio_froms, - audio_tos - )?) - ], - ..Track::default() - } + Track::new_sampler(jack, midi_froms.as_slice(), audio_froms, audio_tos)? ], - _ => vec![] }, scenes,