diff --git a/crates/tek_tui/src/lib.rs b/crates/tek_tui/src/lib.rs index cef37461..6805652a 100644 --- a/crates/tek_tui/src/lib.rs +++ b/crates/tek_tui/src/lib.rs @@ -23,18 +23,18 @@ submod! { tui_arranger_hor tui_arranger_ver - tui_mixer - tui_mixer_cmd + //tui_mixer // TODO + //tui_mixer_cmd tui_phrase tui_phrase_cmd - tui_plugin - tui_plugin_cmd - tui_plugin_lv2 - tui_plugin_lv2_gui - tui_plugin_vst2 - tui_plugin_vst3 + //tui_plugin // TODO + //tui_plugin_cmd + //tui_plugin_lv2 + //tui_plugin_lv2_gui + //tui_plugin_vst2 + //tui_plugin_vst3 tui_pool tui_pool_cmd @@ -54,4 +54,5 @@ submod! { tui_transport tui_transport_bar tui_transport_cmd + tui_transport_foc } diff --git a/crates/tek_tui/src/tui_arrangement_cmd.rs b/crates/tek_tui/src/tui_arrangement_cmd.rs index e7bb7412..b0be3d83 100644 --- a/crates/tek_tui/src/tui_arrangement_cmd.rs +++ b/crates/tek_tui/src/tui_arrangement_cmd.rs @@ -131,9 +131,16 @@ impl InputToCommand> for ArrangementEditorCommand { impl Command> for ArrangementEditorCommand { fn execute (self, state: &mut ArrangementEditor) -> Perhaps { match self { - Self::Zoom(zoom) => { todo!(); }, - Self::Select(selected) => { state.selected = selected; }, - Self::Edit(command) => return command.execute(state.state).map(Self::Edit), + Self::Zoom(zoom) => { + todo!(); + }, + Self::Select(selected) => { + state.selected = selected; + }, + Self::Edit(command) => { + return command.execute(state.state).map(Self::Edit) + }, } + Ok(None) } } diff --git a/crates/tek_tui/src/tui_arranger.rs b/crates/tek_tui/src/tui_arranger.rs index 1e3d7a6d..7610b34e 100644 --- a/crates/tek_tui/src/tui_arranger.rs +++ b/crates/tek_tui/src/tui_arranger.rs @@ -368,7 +368,7 @@ impl Arrangement { } pub fn scene_add ( &mut self, name: Option<&str>, color: Option - ) -> Usually<&mut Scene> { + ) -> Usually<&mut ArrangementScene> { let clips = vec![None;self.tracks.len()]; let name = name.map(|x|x.to_string()).unwrap_or_else(||self.scene_default_name()); self.scenes.push(Scene::new(name, clips, color)); @@ -482,7 +482,7 @@ impl ArrangementEditorMode { } } } -impl Scene { +impl ArrangementScene { pub fn new ( name: impl AsRef, clips: impl AsRef<[Option>>]>, diff --git a/crates/tek_tui/src/tui_arranger_cmd.rs b/crates/tek_tui/src/tui_arranger_cmd.rs index 2edc2047..10760817 100644 --- a/crates/tek_tui/src/tui_arranger_cmd.rs +++ b/crates/tek_tui/src/tui_arranger_cmd.rs @@ -43,7 +43,7 @@ impl InputToCommand> for ArrangerViewCommand { key!(KeyCode::Right) => Some(Focus(Right)), key!(KeyCode::Enter) => Some(Focus(Enter)), key!(KeyCode::Esc) => Some(Focus(Exit)), - key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)), + //key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)), _ => match state.focused() { ArrangerViewFocus::Transport => state.transport.as_ref() .map(|t|TransportCommand::input_to_command(&*t.read().unwrap(), input) diff --git a/crates/tek_tui/src/tui_arranger_ver.rs b/crates/tek_tui/src/tui_arranger_ver.rs index d7ecfc7f..0b600c12 100644 --- a/crates/tek_tui/src/tui_arranger_ver.rs +++ b/crates/tek_tui/src/tui_arranger_ver.rs @@ -89,14 +89,14 @@ impl<'a> Content for VerticalArranger<'a, Tui> { .push_x(scenes_w) }); // scene titles - let scene_name = |scene, playing: bool, height|row!( + let scene_name = |scene: &ArrangementScene, playing: bool, height|row!( if playing { "▶ " } else { " " }, - TuiStyle::bold((scene as &Scene).name.read().unwrap().as_str(), true), + TuiStyle::bold(scene.name.read().unwrap().as_str(), true), ).fixed_xy(scenes_w, height); // scene clips - let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{ + let scene_clip = |scene: &ArrangementScene, track: usize, w: u16, h: u16|Layers::new(move |add|{ let mut bg = clip_bg; - match (tracks.get(track), (scene as &Scene).clips.get(track)) { + match (tracks.get(track), scene.clips.get(track)) { (Some(track), Some(Some(phrase))) => { let name = &(phrase as &Arc>).read().unwrap().name; let name = format!("{}", name); diff --git a/crates/tek_tui/src/tui_phrase.rs b/crates/tek_tui/src/tui_phrase.rs index 679cc742..98b9d786 100644 --- a/crates/tek_tui/src/tui_phrase.rs +++ b/crates/tek_tui/src/tui_phrase.rs @@ -196,46 +196,6 @@ impl PhraseEditor { } } - pub fn note_cursor_inc (&self) { - let mut axis = self.note_axis.write().unwrap(); - axis.point_dec(1); - if let Some(point) = axis.point { if point < axis.start { axis.start = (point / 2) * 2; } } - } - - pub fn note_cursor_dec (&self) { - let mut axis = self.note_axis.write().unwrap(); - axis.point_inc(1); - if let Some(point) = axis.point { if point > 73 { axis.point = Some(73); } } - } - - pub fn note_page_up (&self) { - let mut axis = self.note_axis.write().unwrap(); - axis.start_dec(3); - axis.point_dec(3); - } - - pub fn note_page_down (&self) { - let mut axis = self.note_axis.write().unwrap(); - axis.start_inc(3); - axis.point_inc(3); - } - - pub fn note_scroll_inc (&self) { - self.note_axis.write().unwrap().start_dec(1); - } - - pub fn note_scroll_dec (&self) { - self.note_axis.write().unwrap().start_inc(1); - } - - pub fn note_length_inc (&mut self) { - self.note_len = next_note_length(self.note_len) - } - - pub fn note_length_dec (&mut self) { - self.note_len = prev_note_length(self.note_len) - } - pub fn time_cursor_advance (&self) { let point = self.time_axis.read().unwrap().point; let length = self.phrase.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1); @@ -243,39 +203,6 @@ impl PhraseEditor { self.time_axis.write().unwrap().point = point.map(forward); } - pub fn time_cursor_inc (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().point_inc(scale); - } - - pub fn time_cursor_dec (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().point_dec(scale); - } - - pub fn time_scroll_inc (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().start_inc(scale); - } - - pub fn time_scroll_dec (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().start_dec(scale); - } - - pub fn time_zoom_in (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().scale = prev_note_length(scale) - } - - pub fn time_zoom_out (&self) { - let scale = self.time_axis.read().unwrap().scale; - self.time_axis.write().unwrap().scale = next_note_length(scale) - } - -} - -impl PhraseEditor { pub fn put (&mut self) { if let (Some(phrase), Some(time), Some(note)) = ( &self.phrase, diff --git a/crates/tek_tui/src/tui_phrase_cmd.rs b/crates/tek_tui/src/tui_phrase_cmd.rs index 5d73bfa6..5715b39e 100644 --- a/crates/tek_tui/src/tui_phrase_cmd.rs +++ b/crates/tek_tui/src/tui_phrase_cmd.rs @@ -14,7 +14,6 @@ pub enum PhraseEditorCommand { TimeCursorSet(usize), TimeScrollSet(usize), TimeZoomSet(usize), - Go(Direction), } impl Handle for PhraseEditor { @@ -24,61 +23,122 @@ impl Handle for PhraseEditor { } impl InputToCommand> for PhraseEditorCommand { - fn input_to_command (_: &PhraseEditor, from: &TuiInput) -> Option { - match from.event() { - key!(KeyCode::Char('`')) => Some(Self::ToggleDirection), - key!(KeyCode::Enter) => Some(Self::EnterEditMode), - key!(KeyCode::Esc) => Some(Self::ExitEditMode), - key!(KeyCode::Char('[')) => Some(Self::NoteLengthDec), - key!(KeyCode::Char(']')) => Some(Self::NoteLengthInc), - key!(KeyCode::Char('a')) => Some(Self::NoteAppend), - key!(KeyCode::Char('s')) => Some(Self::NoteSet), - key!(KeyCode::Char('-')) => Some(Self::TimeZoomOut), - key!(KeyCode::Char('_')) => Some(Self::TimeZoomOut), - key!(KeyCode::Char('=')) => Some(Self::TimeZoomIn), - key!(KeyCode::Char('+')) => Some(Self::TimeZoomIn), - key!(KeyCode::PageUp) => Some(Self::NotePageUp), - key!(KeyCode::PageDown) => Some(Self::NotePageDown), - key!(KeyCode::Up) => Some(Self::GoUp), - key!(KeyCode::Down) => Some(Self::GoDown), - key!(KeyCode::Left) => Some(Self::GoLeft), - key!(KeyCode::Right) => Some(Self::GoRight), - _ => None - } + fn input_to_command (state: &PhraseEditor, from: &TuiInput) -> Option { + use PhraseEditorCommand::*; + Some(match from.event() { + key!(KeyCode::Char('`')) => ToggleDirection, + key!(KeyCode::Enter) => EnterEditMode, + key!(KeyCode::Esc) => ExitEditMode, + key!(KeyCode::Char('[')) => NoteLengthSet(0), + key!(KeyCode::Char(']')) => NoteLengthSet(0), + key!(KeyCode::Char('a')) => NoteAppend, + key!(KeyCode::Char('s')) => NoteSet, + key!(KeyCode::Char('-')) => TimeZoomSet(0), + key!(KeyCode::Char('_')) => TimeZoomSet(0), + key!(KeyCode::Char('=')) => TimeZoomSet(0), + key!(KeyCode::Char('+')) => TimeZoomSet(0), + key!(KeyCode::PageUp) => NoteScrollSet(0), + key!(KeyCode::PageDown) => NoteScrollSet(0), + key!(KeyCode::Up) => match state.entered { + true => NoteCursorSet(0), + false => NoteScrollSet(0), + }, + key!(KeyCode::Down) => match state.entered { + true => NoteCursorSet(0), + false => NoteScrollSet(0), + }, + key!(KeyCode::Left) => match state.entered { + true => TimeCursorSet(0), + false => TimeScrollSet(0), + }, + key!(KeyCode::Right) => match state.entered { + true => TimeCursorSet(0), + false => TimeScrollSet(0), + }, + _ => return None + }) } } impl Command> for PhraseEditorCommand { - fn translate (self, state: &PhraseEditor) -> Self { - use PhraseEditorCommand::*; - match self { - GoUp => match state.entered { true => NoteCursorInc, false => NoteScrollInc, }, - GoDown => match state.entered { true => NoteCursorDec, false => NoteScrollDec, }, - GoLeft => match state.entered { true => TimeCursorDec, false => TimeScrollDec, }, - GoRight => match state.entered { true => TimeCursorInc, false => TimeScrollInc, }, - _ => self - } - } + //fn translate (self, state: &PhraseEditor) -> Self { + //use PhraseEditorCommand::*; + //match self { + //GoUp => match state.entered { true => NoteCursorInc, false => NoteScrollInc, }, + //GoDown => match state.entered { true => NoteCursorDec, false => NoteScrollDec, }, + //GoLeft => match state.entered { true => TimeCursorDec, false => TimeScrollDec, }, + //GoRight => match state.entered { true => TimeCursorInc, false => TimeScrollInc, }, + //_ => self + //} + //} fn execute (self, state: &mut PhraseEditor) -> Perhaps { use PhraseEditorCommand::*; match self.translate(state) { - ToggleDirection => { state.mode = !state.mode; }, - EnterEditMode => { state.entered = true; }, - ExitEditMode => { state.entered = false; }, - TimeZoomOut => { state.time_zoom_out() }, - TimeZoomIn => { state.time_zoom_in() }, - TimeCursorDec => { state.time_cursor_dec() }, - TimeCursorInc => { state.time_cursor_inc() }, - TimeScrollDec => { state.time_scroll_dec() }, - TimeScrollInc => { state.time_scroll_inc() }, - NoteCursorDec => { state.note_cursor_dec() }, - NoteCursorInc => { state.note_cursor_inc() }, - NoteScrollDec => { state.note_scroll_dec() }, - NoteScrollInc => { state.note_scroll_inc() }, - NoteLengthDec => { state.note_length_dec() }, - NoteLengthInc => { state.note_length_inc() }, - NotePageUp => { state.note_page_up() }, - NotePageDown => { state.note_page_down() }, + ToggleDirection => { + state.mode = !state.mode; + }, + EnterEditMode => { + state.entered = true; + }, + ExitEditMode => { + state.entered = false; + }, + TimeZoomOut => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().scale = next_note_length(scale) + }, + TimeZoomIn => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().scale = prev_note_length(scale) + }, + TimeCursorDec => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().point_dec(scale); + }, + TimeCursorInc => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().point_inc(scale); + }, + TimeScrollDec => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().start_dec(scale); + }, + TimeScrollInc => { + let scale = state.time_axis.read().unwrap().scale; + state.time_axis.write().unwrap().start_inc(scale); + }, + NoteCursorDec => { + let mut axis = state.note_axis.write().unwrap(); + axis.point_inc(1); + if let Some(point) = axis.point { if point > 73 { axis.point = Some(73); } } + }, + NoteCursorInc => { + let mut axis = state.note_axis.write().unwrap(); + axis.point_dec(1); + if let Some(point) = axis.point { if point < axis.start { axis.start = (point / 2) * 2; } } + }, + NoteScrollDec => { + state.note_axis.write().unwrap().start_inc(1); + }, + NoteScrollInc => { + state.note_axis.write().unwrap().start_dec(1); + }, + NoteLengthDec => { + state.note_len = prev_note_length(state.note_len) + }, + NoteLengthInc => { + state.note_len = next_note_length(state.note_len) + }, + NotePageUp => { + let mut axis = state.note_axis.write().unwrap(); + axis.start_dec(3); + axis.point_dec(3); + }, + NotePageDown => { + let mut axis = state.note_axis.write().unwrap(); + axis.start_inc(3); + axis.point_inc(3); + }, NoteAppend => { if state.entered { state.put(); diff --git a/crates/tek_tui/src/tui_sequencer_cmd.rs b/crates/tek_tui/src/tui_sequencer_cmd.rs index 2221723b..4ec6c25a 100644 --- a/crates/tek_tui/src/tui_sequencer_cmd.rs +++ b/crates/tek_tui/src/tui_sequencer_cmd.rs @@ -61,7 +61,7 @@ impl InputToCommand> for SequencerViewCommand { key!(KeyCode::Down) => Some(Focus(Down)), key!(KeyCode::Left) => Some(Focus(Left)), key!(KeyCode::Right) => Some(Focus(Right)), - key!(KeyCode::Char(' ')) => Some(Transport(TransportViewCommand::PlayToggle)), + //key!(KeyCode::Char(' ')) => Some(Transport(TransportViewCommand::PlayToggle)), _ => match state.focused() { SequencerFocus::Transport => if let Some(t) = state.transport.as_ref() { TransportViewCommand::input_to_command(&*t.read().unwrap(), input).map(Transport) diff --git a/crates/tek_tui/src/tui_transport.rs b/crates/tek_tui/src/tui_transport.rs index 02487ef3..8b67ea4e 100644 --- a/crates/tek_tui/src/tui_transport.rs +++ b/crates/tek_tui/src/tui_transport.rs @@ -5,10 +5,10 @@ use tek_api::Transport; #[derive(Debug)] pub struct TransportView { _engine: PhantomData, - state: Transport, - focus: TransportViewFocus, - focused: bool, - size: Measure, + pub state: Transport, + pub focus: TransportViewFocus, + pub focused: bool, + pub size: Measure, } /// JACK process callback for transport app diff --git a/crates/tek_tui/src/tui_transport_cmd.rs b/crates/tek_tui/src/tui_transport_cmd.rs index 49b448c4..a63340b6 100644 --- a/crates/tek_tui/src/tui_transport_cmd.rs +++ b/crates/tek_tui/src/tui_transport_cmd.rs @@ -10,41 +10,68 @@ impl Handle for TransportView { } } impl InputToCommand> for TransportViewCommand { - fn input_to_command (_: &TransportView, input: &TuiInput) -> Option { - match input.event() { - key!(KeyCode::Char(' ')) => Some(Self::FocusPrev), - key!(Shift-KeyCode::Char(' ')) => Some(Self::FocusPrev), - key!(KeyCode::Left) => Some(Self::FocusPrev), - key!(KeyCode::Right) => Some(Self::FocusNext), - key!(KeyCode::Char('.')) => Some(match state.focus { - Bpm => SetBpm(state.clock.timebase().bpm.get() + 1.0), - Quant => SetQuant(next_note_length(state.clock.quant.get()as usize)as f64), - Sync => SetSync(next_note_length(state.clock.sync.get()as usize)as f64+1.), - PlayPause => {todo!()}, - Clock => {todo!()} + fn input_to_command (state: &TransportView, input: &TuiInput) -> Option { + use TransportViewFocus as Focus; + use FocusCommand as FocusCmd; + use TransportCommand as Cmd; + Some(match input.event() { + + key!(KeyCode::Left) => Self::Focus(FocusCmd::Prev), + key!(KeyCode::Right) => Self::Focus(FocusCmd::Next), + + key!(KeyCode::Char('.')) => Self::Transport(match state.focus { + Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() + 1.0), + Focus::Quant => Cmd::SetQuant(next_note_length(state.state.clock.quant.get()as usize)as f64), + Focus::Sync => Cmd::SetSync(next_note_length(state.state.clock.sync.get()as usize)as f64+1.), + Focus::PlayPause => {todo!()}, + Focus::Clock => {todo!()} }), - key!(KeyCode::Char(',')) => Some(match state.focus { - Bpm => SetBpm(state.clock.timebase().bpm.get() - 1.0), - Quant => SetQuant(prev_note_length(state.clock.quant.get()as usize)as f64), - Sync => SetSync(prev_note_length(state.clock.sync.get()as usize)as f64+1.), - PlayPause => {todo!()}, - Clock => {todo!()} + key!(KeyCode::Char(',')) => Self::Transport(match state.focus { + Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() - 1.0), + Focus::Quant => Cmd::SetQuant(prev_note_length(state.state.clock.quant.get()as usize)as f64), + Focus::Sync => Cmd::SetSync(prev_note_length(state.state.clock.sync.get()as usize)as f64+1.), + Focus::PlayPause => {todo!()}, + Focus::Clock => {todo!()} }), - key!(KeyCode::Char('>')) => Some(match state.focus { - Bpm => SetBpm(state.clock.timebase().bpm.get() + 0.001), - Quant => SetQuant(next_note_length(state.clock.quant.get()as usize)as f64), - Sync => SetSync(next_note_length(state.clock.sync.get()as usize)as f64+1.), - PlayPause => {todo!()}, - Clock => {todo!()} + key!(KeyCode::Char('>')) => Self::Transport(match state.focus { + Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() + 0.001), + Focus::Quant => Cmd::SetQuant(next_note_length(state.state.clock.quant.get()as usize)as f64), + Focus::Sync => Cmd::SetSync(next_note_length(state.state.clock.sync.get()as usize)as f64+1.), + Focus::PlayPause => {todo!()}, + Focus::Clock => {todo!()} }), - key!(KeyCode::Char('<')) => Some(match state.focus { - Bpm => SetBpm(state.clock.timebase().bpm.get() - 0.001), - Quant => SetQuant(prev_note_length(state.clock.quant.get()as usize)as f64), - Sync => SetSync(prev_note_length(state.clock.sync.get()as usize)as f64+1.), - PlayPause => {todo!()}, - Clock => {todo!()} + key!(KeyCode::Char('<')) => Self::Transport(match state.focus { + Focus::Bpm => Cmd::SetBpm(state.state.clock.timebase().bpm.get() - 0.001), + Focus::Quant => Cmd::SetQuant(prev_note_length(state.state.clock.quant.get()as usize)as f64), + Focus::Sync => Cmd::SetSync(prev_note_length(state.state.clock.sync.get()as usize)as f64+1.), + Focus::PlayPause => {todo!()}, + Focus::Clock => {todo!()} }), - _ => None - } + + _ => return None + }) + } +} + +impl Command> for TransportViewCommand { + fn execute (self, state: &mut TransportView) -> Perhaps { + Ok(match self { + Self::Focus(command) => { + use FocusCommand::*; + match command { + Next => { todo!() }, + Prev => { todo!() }, + } + }, + Self::Transport(command) => { + use TransportCommand::*; + match command { + SetBpm(bpm) => SetBpm(state.state.clock.timebase().bpm.set(bpm)), + SetQuant(quant) => SetQuant(state.state.clock.quant.set(quant)), + SetSync(sync) => SetSync(state.state.clock.sync.set(sync)), + _ => { todo!() } + } + }, + }) } }