diff --git a/Justfile b/Justfile index 4223d64b..c657edd1 100644 --- a/Justfile +++ b/Justfile @@ -60,6 +60,15 @@ arranger-release-ext: groovebox: reset cargo run --bin tek_groovebox +groovebox-ext: + reset + cargo run --bin tek_groovebox -- -n tek \ + -i "Midi-Bridge:nanoKEY Studio 1:(capture_0) nanoKEY Studio nanoKEY Studio _" \ + -o "Midi-Bridge:Komplete Audio 6 0:(playback_0) Komplete Audio 6 MIDI 1" \ + -l "Komplete Audio 6 Pro:capture_AUX1" \ + -r "Komplete Audio 6 Pro:capture_AUX1" \ + -L "Komplete Audio 6 Pro:playback_AUX1" \ + -R "Komplete Audio 6 Pro:playback_AUX1" groovebox-release: reset cargo run --release --bin tek_groovebox diff --git a/crates/tek/src/groovebox.rs b/crates/tek/src/groovebox.rs index 2070a41a..a9bec7c6 100644 --- a/crates/tek/src/groovebox.rs +++ b/crates/tek/src/groovebox.rs @@ -60,7 +60,7 @@ render!(|self:GrooveboxTui|{ let w = self.size.w(); let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 }; let pool_w = if self.pool.visible { phrase_w } else { 0 }; - let sampler_w = 24; + let sampler_w = 11; Fill::wh(lay!([ &self.size, Fill::wh(Align::s(Fixed::h(2, GrooveboxStatus::from(self)))), @@ -80,11 +80,17 @@ render!(|self:GrooveboxTui|{ MidiEditStatus(&self.editor), Tui::split_w(false, pool_w, Tui::pull_y(1, Fill::h(Align::e(PoolView(&self.pool)))), - col!([ - &format!("L/{:>+10.3}", self.sampler.input_meter[0]), - &format!("R/{:>+10.3}", self.sampler.input_meter[1]), - Fill::wh(&self.editor) - ]) + Tui::split_e(false, sampler_w, Fill::wh(col!([ + &format!("L/{:>+9.3}", self.sampler.input_meter[0]), + &format!("R/{:>+9.3}", self.sampler.input_meter[1]), + Fill::wh(col!(note in (self.editor.note_lo().load(Relaxed)..=self.editor.note_hi()).rev() => { + if self.sampler.mapped.contains_key(&u7::from(note as u8)) { + todo!() + } else { + Tui::fg(TuiTheme::g(96), format!("{note:3} (none)")) + } + })), + ])), Fill::h(&self.editor)) ) ), ]), @@ -126,6 +132,10 @@ input_to_command!(GrooveboxCommand: |state: GrooveboxTui, input|match input // 0: Enqueue phrase 0 (stop all) key_pat!(Char('0')) => Enqueue(Some(state.pool.phrases()[0].clone())), + key_pat!(Shift-Char('R')) => Sampler( + SamplerCommand::Record(u7::from(state.editor.note_point() as u8)) + ), + // e: Toggle between editing currently playing or other phrase key_pat!(Char('e')) => if let Some((_, Some(playing))) = state.player.play_phrase() { let editing = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone()); diff --git a/crates/tek/src/sampler/sampler_control.rs b/crates/tek/src/sampler/sampler_control.rs index 0a8d9c63..63107481 100644 --- a/crates/tek/src/sampler/sampler_control.rs +++ b/crates/tek/src/sampler/sampler_control.rs @@ -8,10 +8,11 @@ pub enum SamplerCommand { SelectNote(usize), SelectField(usize), SetName(String), - SetNote(u7, Arc>), + SetNote(u7, Option>>), SetGain(f32), NoteOn(u7, u7), - NoteOff(u7) + NoteOff(u7), + Record(u7), } input_to_command!(SamplerCommand: |state: SamplerTui, input|match state.mode { @@ -62,5 +63,10 @@ command!(|self:SamplerCommand,state:SamplerTui|match self { state.set_note_point(index); Some(Self::SelectNote(old)) }, + Self::Record(index) => { + let old = state.state.mapped.get(&index).cloned(); + + Some(Self::SetNote(index, old)) + }, _ => todo!() }); diff --git a/crates/tek/src/space.rs b/crates/tek/src/space.rs index 7b6a624b..5629081b 100644 --- a/crates/tek/src/space.rs +++ b/crates/tek/src/space.rs @@ -189,3 +189,48 @@ impl Area for [N;4] { #[inline] fn w (&self) -> N { self[2] } #[inline] fn h (&self) -> N { self[3] } } + +#[macro_export] macro_rules! col { + ([$($expr:expr),* $(,)?]) => { + Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + (![$($expr:expr),* $(,)?]) => { + Stack::down(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Stack::down($expr) + }; + ($pat:pat in $collection:expr => $item:expr) => { + Stack::down(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) + }; +} + +#[macro_export] macro_rules! col_up { + ([$($expr:expr),* $(,)?]) => { + Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + (![$($expr:expr),* $(,)?]) => { + Stack::up(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Stack::up(expr) + }; + ($pat:pat in $collection:expr => $item:expr) => { + Stack::up(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) + }; +} + +#[macro_export] macro_rules! row { + ([$($expr:expr),* $(,)?]) => { + Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + (![$($expr:expr),* $(,)?]) => { + Stack::right(|add|{ $(add(&$expr)?;)* Ok(()) }) + }; + ($expr:expr) => { + Stack::right($expr) + }; + ($pat:pat in $collection:expr => $item:expr) => { + Stack::right(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) + }; +} diff --git a/crates/tek/src/space/stack.rs b/crates/tek/src/space/stack.rs index a48f5a5a..40a5142c 100644 --- a/crates/tek/src/space/stack.rs +++ b/crates/tek/src/space/stack.rs @@ -1,51 +1,6 @@ use crate::*; use Direction::*; -#[macro_export] macro_rules! col { - ([$($expr:expr),* $(,)?]) => { - Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::down(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::down($expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::down(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - -#[macro_export] macro_rules! col_up { - ([$($expr:expr),* $(,)?]) => { - Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::up(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::up(expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::up(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - -#[macro_export] macro_rules! row { - ([$($expr:expr),* $(,)?]) => { - Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - (![$($expr:expr),* $(,)?]) => { - Stack::right(|add|{ $(add(&$expr)?;)* Ok(()) }) - }; - ($expr:expr) => { - Stack::right($expr) - }; - ($pat:pat in $collection:expr => $item:expr) => { - Stack::right(move|add|{ for $pat in $collection { add(&$item)?; } Ok(()) }) - }; -} - pub struct Stack< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render)->Usually<()>)->Usually<()>