From 76da19d9c6600395d348e39654f16955e5fd74ac Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 21 Nov 2024 00:25:54 +0100 Subject: [PATCH] wip(p61,e38) --- crates/tek_api/src/api_player.rs | 10 ++-- crates/tek_api/src/api_track.rs | 2 +- crates/tek_core/src/space.rs | 34 ++++++++---- crates/tek_tui/src/tui_command.rs | 38 +++++++------ crates/tek_tui/src/tui_content.rs | 2 +- crates/tek_tui/src/tui_control.rs | 89 ++++++++++++++++--------------- crates/tek_tui/src/tui_focus.rs | 34 ++++++------ crates/tek_tui/src/tui_impls.rs | 1 + crates/tek_tui/src/tui_init.rs | 40 +++++++------- crates/tek_tui/src/tui_input.rs | 38 ++++++------- crates/tek_tui/src/tui_model.rs | 13 +++++ crates/tek_tui/src/tui_view.rs | 12 ++--- 12 files changed, 172 insertions(+), 141 deletions(-) diff --git a/crates/tek_api/src/api_player.rs b/crates/tek_api/src/api_player.rs index 3d847705..4320d839 100644 --- a/crates/tek_api/src/api_player.rs +++ b/crates/tek_api/src/api_player.rs @@ -1,11 +1,11 @@ use crate::*; pub trait HasPlayer: JackApi { - fn player (&self) -> &impl PlayerApi; - fn player_mut (&mut self) -> &mut impl PlayerApi; + fn player (&self) -> &impl MidiPlayerApi; + fn player_mut (&mut self) -> &mut impl MidiPlayerApi; } -pub trait PlayerApi: MidiInputApi + MidiOutputApi + Send + Sync {} +pub trait MidiPlayerApi: MidiInputApi + MidiOutputApi + Send + Sync {} pub trait HasPhrase: PlayheadApi { fn reset (&self) -> bool; @@ -293,7 +293,7 @@ pub fn update_keys (keys: &mut[bool;128], message: &MidiMessage) { } /// Hosts the JACK callback for a single MIDI player -pub struct PlayerAudio<'a, T: PlayerApi>( +pub struct PlayerAudio<'a, T: MidiPlayerApi>( /// Player pub &'a mut T, /// Note buffer @@ -303,7 +303,7 @@ pub struct PlayerAudio<'a, T: PlayerApi>( ); /// JACK process callback for a sequencer's phrase player/recorder. -impl<'a, T: PlayerApi> Audio for PlayerAudio<'a, T> { +impl<'a, T: MidiPlayerApi> Audio for PlayerAudio<'a, T> { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { let model = &mut self.0; let note_buf = &mut self.1; diff --git a/crates/tek_api/src/api_track.rs b/crates/tek_api/src/api_track.rs index 2845ed3a..60dd4a2c 100644 --- a/crates/tek_api/src/api_track.rs +++ b/crates/tek_api/src/api_track.rs @@ -33,7 +33,7 @@ pub enum ArrangerTrackCommand { SetZoom(usize), } -pub trait ArrangerTrackApi: PlayerApi + Send + Sync + Sized { +pub trait ArrangerTrackApi: MidiPlayerApi + Send + Sync + Sized { /// Name of track fn name (&self) -> &Arc>; /// Preferred width of track column diff --git a/crates/tek_core/src/space.rs b/crates/tek_core/src/space.rs index 31d68c8e..21e70a4a 100644 --- a/crates/tek_core/src/space.rs +++ b/crates/tek_core/src/space.rs @@ -50,34 +50,41 @@ pub struct ScaledAxis { macro_rules! impl_axis_common { ($A:ident $T:ty) => { impl $A<$T> { - #[inline] pub fn start_plus (&mut self, n: $T) -> $T { + #[inline] pub fn start_set (&mut self, n: $T) -> $T { + self.start = n; + self.start + } + #[inline] pub fn start_plus (&self, n: $T) -> $T { (self.start + n).min(self.clamp.unwrap_or(<$T>::MAX)) } #[inline] pub fn start_inc (&mut self, n: $T) -> $T { - self.start = self.start_plus(n); - self.start + self.start_set(self.start_plus(n)) } - #[inline] pub fn start_minus (&mut self, n: $T) -> $T { + #[inline] pub fn start_minus (&self, n: $T) -> $T { self.start.saturating_sub(n) } #[inline] pub fn start_dec (&mut self, n: $T) -> $T { self.start = self.start_minus(n); self.start } - #[inline] pub fn point_plus (&mut self, n: $T) -> Option<$T> { + + #[inline] pub fn point_set (&mut self, n: Option<$T>) -> Option<$T> { + self.point = n; + self.point + } + #[inline] pub fn point_plus (&self, n: $T) -> Option<$T> { self.point.map(|p|(p + n).min(self.clamp.unwrap_or(<$T>::MAX))) } #[inline] pub fn point_inc (&mut self, n: $T) -> Option<$T> { - self.point = self.point_plus(n); - self.point + self.point_set(self.point_plus(n)) } - #[inline] pub fn point_minus (&mut self, n: $T) -> Option<$T> { + #[inline] pub fn point_minus (&self, n: $T) -> Option<$T> { self.point.map(|p|p.saturating_sub(n)) } #[inline] pub fn point_dec (&mut self, n: $T) -> Option<$T> { - self.point = self.point_minus(n); - self.point + self.point_set(self.point_minus(n)) } + } } } impl_axis_common!(FixedAxis u16); @@ -85,6 +92,13 @@ impl_axis_common!(FixedAxis usize); impl_axis_common!(ScaledAxis u16); impl_axis_common!(ScaledAxis usize); +impl ScaledAxis { + #[inline] pub fn scale_set (&mut self, n: T) -> T { + self.scale = n; + n + } +} + // TODO: return impl Point and impl Size instead of [N;x] // to disambiguate between usage of 2-"tuple"s diff --git a/crates/tek_tui/src/tui_command.rs b/crates/tek_tui/src/tui_command.rs index ee74df07..7233775a 100644 --- a/crates/tek_tui/src/tui_command.rs +++ b/crates/tek_tui/src/tui_command.rs @@ -38,7 +38,7 @@ pub enum SequencerCommand { impl Command for SequencerCommand where - T: PhrasesControl + PhraseControl + PlayheadApi + T: PhrasesControl + PhraseEditorControl + PlayheadApi + FocusGrid + FocusEnter { fn execute (self, state: &mut T) -> Perhaps { @@ -93,9 +93,10 @@ impl Command for ArrangerCommand { None }, EditPhrase(phrase) => { - state.show_phrase(phrase); + state.edit_phrase(&phrase); None - } + }, + _ => { todo!() } }) } } @@ -185,7 +186,7 @@ impl Command for PhraseLengthCommand { Tick => { *length = length.saturating_sub(1) }, }, Self::Set(length) => { - let mut phrase = state.phrases[phrase].write().unwrap(); + let mut phrase = state.phrases()[*phrase].write().unwrap(); let old_length = phrase.length; phrase.length = length; *mode = None; @@ -217,10 +218,13 @@ where { fn execute (self, state: &mut T) -> Perhaps { use PhraseRenameCommand::*; - if let Some(PhrasesMode::Rename(phrase, ref mut old_name)) = state.phrases_mode_mut() { + if let Some(PhrasesMode::Rename( + phrase, + ref mut old_name + )) = state.phrases_mode_mut().clone() { match self { Set(s) => { - state.phrases()[*phrase].write().unwrap().name = s.into(); + state.phrases()[phrase].write().unwrap().name = s.into(); return Ok(Some(Self::Set(old_name.clone()))) }, Confirm => { @@ -229,7 +233,7 @@ where return Ok(Some(Self::Set(old_name))) }, Cancel => { - state.phrases()[*phrase].write().unwrap().name = old_name.clone(); + state.phrases()[phrase].write().unwrap().name = old_name.clone(); }, _ => unreachable!() }; @@ -251,17 +255,17 @@ pub enum PhraseCommand { ExitEditMode, NoteAppend, NoteSet, - NoteCursorSet(usize), + NoteCursorSet(Option), NoteLengthSet(usize), NoteScrollSet(usize), - TimeCursorSet(usize), + TimeCursorSet(Option), TimeScrollSet(usize), TimeZoomSet(usize), } impl Command for PhraseCommand where - T: PhraseControl + FocusEnter + T: PhraseEditorControl + FocusEnter { fn execute (self, state: &mut T) -> Perhaps { use PhraseCommand::*; @@ -270,24 +274,28 @@ where EnterEditMode => { state.focus_enter(); None }, ExitEditMode => { state.focus_exit(); None }, NoteAppend => { - if state.phrase_entered() { + if state.phrase_editor_entered() { state.put_note(); state.time_cursor_advance(); } None }, - NoteSet => { if state.phrase_entered() { state.put_note(); } None }, + NoteSet => { if state.phrase_editor_entered() { state.put_note(); } None }, TimeCursorSet(time) => { state.time_axis().write().unwrap().point_set(time); None }, TimeScrollSet(time) => { state.time_axis().write().unwrap().start_set(time); None }, TimeZoomSet(zoom) => { state.time_axis().write().unwrap().scale_set(zoom); None }, NoteScrollSet(note) => { state.note_axis().write().unwrap().start_set(note); None }, NoteLengthSet(time) => { *state.note_len_mut() = time; None }, NoteCursorSet(note) => { - let axis = state.note_axis().write().unwrap(); + let mut axis = state.note_axis().write().unwrap(); axis.point_set(note); if let Some(point) = axis.point { - if point > 73 { axis.point = Some(73); } - if point < axis.start { axis.start = (point / 2) * 2; } + if point > 73 { + axis.point = Some(73); + } + if point < axis.start { + axis.start = (point / 2) * 2; + } } None }, diff --git a/crates/tek_tui/src/tui_content.rs b/crates/tek_tui/src/tui_content.rs index 74b13cc7..693fa946 100644 --- a/crates/tek_tui/src/tui_content.rs +++ b/crates/tek_tui/src/tui_content.rs @@ -126,7 +126,7 @@ impl<'a, T: PhrasesViewState> Content for PhrasesView<'a, T> { let entered = self.0.entered(); let phrases = self.0.phrases(); let selected_phrase = self.0.phrase(); - let mode = self.0.mode(); + let mode = self.0.phrase_mode(); let content = col!( (i, phrase) in phrases.iter().enumerate() => Layers::new(|add|{ let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); diff --git a/crates/tek_tui/src/tui_control.rs b/crates/tek_tui/src/tui_control.rs index 07e19902..e35eaf25 100644 --- a/crates/tek_tui/src/tui_control.rs +++ b/crates/tek_tui/src/tui_control.rs @@ -7,7 +7,6 @@ pub trait SequencerControl: TransportControl {} pub trait ArrangerControl: TransportControl { fn selected (&self) -> ArrangerSelection; fn selected_mut (&mut self) -> &mut ArrangerSelection; - fn show_phrase (&mut self, phrase: Option>>); fn activate (&mut self); fn selected_phrase (&self) -> Option>>; fn toggle_loop (&mut self); @@ -51,13 +50,10 @@ pub trait PhrasesControl: HasPhrases { } } -pub trait HasPhrasesModel: HasPhrases { - fn phrases_model (&self) -> &PhrasesModel; - fn phrases_model_mut (&mut self) -> &mut PhrasesModel; -} - -pub trait PhraseControl { - fn phrase_entered (&self) -> bool; +pub trait PhraseEditorControl { + fn edit_phrase (&self, phrase: &Option>>); + fn editing_phrase (&self) -> &Option>>; + fn phrase_editor_entered (&self) -> bool; fn time_axis (&self) -> &RwLock>; fn note_axis (&self) -> &RwLock>; fn note_len (&self) -> usize; @@ -65,7 +61,7 @@ pub trait PhraseControl { fn put_note (&mut self); 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); + let length = self.editing_phrase().as_ref().map(|p|p.read().unwrap().length).unwrap_or(1); let forward = |time|(time + self.note_len()) % length; self.time_axis().write().unwrap().point = point.map(forward); } @@ -86,17 +82,11 @@ impl ArrangerControl for ArrangerTui { fn selected_mut (&mut self) -> &mut ArrangerSelection { &mut self.selected } - fn show_phrase (&mut self, phrase: Option>>) { - self.editor.show(self.selected_phrase().as_ref()); - //state.editor.phrase = phrase.clone(); - //state.focus(ArrangerFocus::PhraseEditor); - //state.focus_enter(); - } fn activate (&mut self) { if let ArrangerSelection::Scene(s) = self.selected { for (t, track) in self.tracks_mut().iter_mut().enumerate() { let clip = self.scenes()[s].clips[t].as_ref(); - if track.play_phrase.is_some() || clip.is_some() { + if track.player.play_phrase.is_some() || clip.is_some() { track.enqueue_next(clip); } } @@ -137,41 +127,48 @@ impl ArrangerControl for ArrangerTui { } } -impl HasPhrasesModel for ArrangerTui { - fn phrases_model (&self) -> &PhrasesModel { - &self.phrases - } - fn phrases_model_mut (&mut self) -> &mut PhrasesModel { - &mut self.phrases - } -} - -impl HasPhrasesModel for SequencerTui { - fn phrases_model (&self) -> &PhrasesModel { - &self.phrases - } - fn phrases_model_mut (&mut self) -> &mut PhrasesModel { - &mut self.phrases - } -} - -impl PhrasesControl for T { +impl PhrasesControl for SequencerTui { fn phrase_index (&self) -> usize { - self.phrases_model().phrase.load(Ordering::Relaxed) + self.phrases.phrase.load(Ordering::Relaxed) } fn set_phrase_index (&self, value: usize) { - self.phrases_model().phrase.store(value, Ordering::Relaxed); + self.phrases.phrase.store(value, Ordering::Relaxed); } fn phrases_mode (&self) -> &Option { - &self.phrases_model().mode + &self.phrases.mode } fn phrases_mode_mut (&mut self) -> &mut Option { - &mut self.phrases_model_mut().mode + &mut self.phrases.mode } } -impl PhraseControl for SequencerTui { - fn phrase_entered (&self) -> bool { +impl PhrasesControl for ArrangerTui { + fn phrase_index (&self) -> usize { + self.phrases.phrase.load(Ordering::Relaxed) + } + fn set_phrase_index (&self, value: usize) { + self.phrases.phrase.store(value, Ordering::Relaxed); + } + fn phrases_mode (&self) -> &Option { + &self.phrases.mode + } + fn phrases_mode_mut (&mut self) -> &mut Option { + &mut self.phrases.mode + } +} + +impl PhraseEditorControl for SequencerTui { + fn edit_phrase (&self, phrase: &Option>>) { + //self.editor.show(self.selected_phrase().as_ref()); + //state.editor.phrase = phrase.clone(); + //state.focus(ArrangerFocus::PhraseEditor); + //state.focus_enter(); + todo!() + } + fn editing_phrase (&self) -> &Option>> { + todo!() + } + fn phrase_editor_entered (&self) -> bool { self.entered && self.focused() == SequencerFocus::PhraseEditor } fn time_axis (&self) -> &RwLock> { @@ -191,8 +188,14 @@ impl PhraseControl for SequencerTui { } } -impl PhraseControl for ArrangerTui { - fn phrase_entered (&self) -> bool { +impl PhraseEditorControl for ArrangerTui { + fn edit_phrase (&self, phrase: &Option>>) { + todo!() + } + fn editing_phrase (&self) -> &Option>> { + todo!() + } + fn phrase_editor_entered (&self) -> bool { self.entered && self.focused() == ArrangerFocus::PhraseEditor } fn time_axis (&self) -> &RwLock> { diff --git a/crates/tek_tui/src/tui_focus.rs b/crates/tek_tui/src/tui_focus.rs index 5c134da5..ab6e7b83 100644 --- a/crates/tek_tui/src/tui_focus.rs +++ b/crates/tek_tui/src/tui_focus.rs @@ -18,7 +18,7 @@ pub enum SequencerFocus { /// The transport (toolbar) is focused Transport, /// The phrase list (pool) is focused - PhrasePool, + Phrases, /// The phrase editor (sequencer) is focused PhraseEditor, } @@ -32,7 +32,7 @@ pub enum ArrangerFocus { /// The arrangement (grid) is focused Arranger, /// The phrase list (pool) is focused - PhrasePool, + Phrases, /// The phrase editor (sequencer) is focused PhraseEditor, } @@ -150,7 +150,7 @@ impl FocusGrid for SequencerTui { &[ &[Menu, Menu ], &[Transport, Transport ], - &[PhrasePool, PhraseEditor], + &[Phrases, PhraseEditor], ] } fn focus_update (&mut self) { @@ -161,20 +161,22 @@ impl FocusGrid for SequencerTui { impl FocusEnter for ArrangerTui { type Item = ArrangerFocus; fn focus_enter (&mut self) { - use ArrangerFocus::*; - let focused = self.focused(); - if !self.entered { - self.entered = focused == Arranger; - self.editor.entered = focused == PhraseEditor; - self.phrases.entered = focused == PhrasePool; - } + self.entered = true; + //use ArrangerFocus::*; + //let focused = self.focused(); + //if !self.entered { + //self.entered = focused == Arranger; + //self.editor.entered = focused == PhraseEditor; + //self.phrases.entered = focused == Phrases; + //} } fn focus_exit (&mut self) { - if self.entered { - self.entered = false; - self.editor.entered = false; - self.phrases.entered = false; - } + self.entered = false; + //if self.entered { + //self.entered = false; + //self.editor.entered = false; + //self.phrases.entered = false; + //} } fn focus_entered (&self) -> Option { if self.entered { @@ -200,7 +202,7 @@ impl FocusGrid for ArrangerTui { &[Menu, Menu ], &[Transport, Transport ], &[Arranger, Arranger ], - &[PhrasePool, PhraseEditor], + &[Phrases, PhraseEditor], ] } fn focus_update (&mut self) { diff --git a/crates/tek_tui/src/tui_impls.rs b/crates/tek_tui/src/tui_impls.rs index 9560c6e4..755a14e7 100644 --- a/crates/tek_tui/src/tui_impls.rs +++ b/crates/tek_tui/src/tui_impls.rs @@ -151,6 +151,7 @@ impl_has_phrases!(ArrangerTui::phrases); impl_has_phrase!(SequencerTui::player); impl_has_phrase!(ArrangerTrack::player); impl_has_phrase!(PhrasePlayerModel); +impl_midi_player!(ArrangerTrack); impl HasScenes for ArrangerTui { fn scenes (&self) -> &Vec { diff --git a/crates/tek_tui/src/tui_init.rs b/crates/tek_tui/src/tui_init.rs index 0aef8f5d..e460a3c7 100644 --- a/crates/tek_tui/src/tui_init.rs +++ b/crates/tek_tui/src/tui_init.rs @@ -5,10 +5,10 @@ impl TryFrom<&Arc>> for TransportTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { Ok(Self { - cursor: (0, 0), - state: TransportModel::from(jack.read().unwrap().transport()), jack: jack.clone(), + state: TransportModel::from(jack.read().unwrap().transport()), size: Measure::new(), + cursor: (0, 0), }) } } @@ -17,17 +17,15 @@ impl TryFrom<&Arc>> for SequencerTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { Ok(Self { - cursor: (0, 0), - entered: false, jack: jack.clone(), - phrases: vec![], - phrases_mode: None, - size: Measure::new(), - split: 20, - view_phrase: 0, transport: TransportModel::from(jack.read().unwrap().transport()), + phrases: PhrasesModel::default(), player: PhrasePlayerModel::default(), editor: PhraseEditorModel::default(), + size: Measure::new(), + cursor: (0, 0), + entered: false, + split: 20, }) } } @@ -36,26 +34,24 @@ impl TryFrom<&Arc>> for ArrangerTui { type Error = Box; fn try_from (jack: &Arc>) -> Usually { Ok(Self { - color: Color::Rgb(28, 35, 25).into(), - cursor: (0, 0), - entered: false, - history: vec![], jack: jack.clone(), - menu_bar: None, + transport: TransportModel::from(jack.read().unwrap().transport()), + phrases: PhrasesModel::default(), + selected: ArrangerSelection::Clip(0, 0), + scenes: vec![], + tracks: vec![], + color: Color::Rgb(28, 35, 25).into(), + history: vec![], midi_buf: vec![], + note_buf: vec![], mode: ArrangerMode::Vertical(2), name: Arc::new(RwLock::new(String::new())), - note_buf: vec![], - phrase: 0, - phrases: vec![], - phrases_mode: None, - scenes: vec![], - selected: ArrangerSelection::Clip(0, 0), size: Measure::new(), + cursor: (0, 0), splits: [20, 20], + entered: false, + menu_bar: None, status_bar: None, - tracks: vec![], - transport: TransportModel::from(jack.read().unwrap().transport()), }) } } diff --git a/crates/tek_tui/src/tui_input.rs b/crates/tek_tui/src/tui_input.rs index 23000b7d..41064696 100644 --- a/crates/tek_tui/src/tui_input.rs +++ b/crates/tek_tui/src/tui_input.rs @@ -54,7 +54,7 @@ where impl InputToCommand for SequencerCommand where - T: SequencerControl + TransportControl + PhrasesControl + PhraseControl + PlayheadApi + T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl + PlayheadApi + HasFocus + FocusGrid + FocusEnter @@ -83,12 +83,10 @@ where }, } }, - SequencerFocus::Phrases => { - PhrasesCommand::input_to_command(state, input).map(Phrases) - }, - SequencerFocus::PhraseEditor => { - PhraseCommand::input_to_command(state, input).map(Editor) - }, + SequencerFocus::Phrases => + Phrases(PhrasesCommand::input_to_command(state, input)?), + SequencerFocus::PhraseEditor => + Editor(PhraseCommand::input_to_command(state, input)?), _ => return None, }) } @@ -96,7 +94,7 @@ where } impl InputToCommand for ArrangerCommand { - fn input_to_command (state: &ArrangerCommand, input: &TuiInput) -> Option { + fn input_to_command (state: &ArrangerTui, input: &TuiInput) -> Option { use FocusCommand::*; use ArrangerCommand::*; Some(match input.event() { @@ -126,13 +124,9 @@ impl InputToCommand for ArrangerCommand { ArrangerFocus::PhraseEditor => Editor( PhraseCommand::input_to_command(state, input)? ), - ArrangerFocus::PhrasePool => match input.event() { - key!(KeyCode::Char('e')) => EditPhrase( - Some(state.phrase().clone()) - ), - _ => Phrases( - PhrasePoolCommand::input_to_command(state, input)? - ) + ArrangerFocus::Phrases => match input.event() { + key!(KeyCode::Char('e')) => EditPhrase(Some(state.phrase().clone())), + _ => Phrases(PhrasePoolCommand::input_to_command(state, input)?) }, ArrangerFocus::Arranger => { use ArrangerSelection as Select; @@ -369,7 +363,7 @@ impl InputToCommand for PhraseRenameCommand { impl InputToCommand for PhraseCommand where - T: PhraseControl + FocusEnter + T: PhraseEditorControl + FocusEnter { fn input_to_command (state: &T, from: &TuiInput) -> Option { use PhraseCommand::*; @@ -385,27 +379,27 @@ where key!(KeyCode::Char('_')) => TimeZoomSet(next_note_length(state.time_axis().read().unwrap().scale)), key!(KeyCode::Char('=')) => TimeZoomSet(prev_note_length(state.time_axis().read().unwrap().scale)), key!(KeyCode::Char('+')) => TimeZoomSet(prev_note_length(state.time_axis().read().unwrap().scale)), - key!(KeyCode::Up) => match state.phrase_entered() { + key!(KeyCode::Up) => match state.phrase_editor_entered() { true => NoteCursorSet(state.note_axis().write().unwrap().point_plus(1)), false => NoteScrollSet(state.note_axis().write().unwrap().start_plus(1)), }, - key!(KeyCode::Down) => match state.phrase_entered() { + key!(KeyCode::Down) => match state.phrase_editor_entered() { true => NoteCursorSet(state.note_axis().write().unwrap().point_minus(1)), false => NoteScrollSet(state.note_axis().write().unwrap().start_minus(1)), }, - key!(KeyCode::PageUp) => match state.phrase_entered() { + key!(KeyCode::PageUp) => match state.phrase_editor_entered() { true => NoteCursorSet(state.note_axis().write().unwrap().point_plus(3)), false => NoteScrollSet(state.note_axis().write().unwrap().start_plus(3)), }, - key!(KeyCode::PageDown) => match state.phrase_entered() { + key!(KeyCode::PageDown) => match state.phrase_editor_entered() { true => NoteCursorSet(state.note_axis().write().unwrap().point_minus(3)), false => NoteScrollSet(state.note_axis().write().unwrap().start_minus(3)), }, - key!(KeyCode::Left) => match state.phrase_entered() { + key!(KeyCode::Left) => match state.phrase_editor_entered() { true => TimeCursorSet(state.note_axis().write().unwrap().point_minus(1)), false => TimeScrollSet(state.note_axis().write().unwrap().start_minus(1)), }, - key!(KeyCode::Right) => match state.phrase_entered() { + key!(KeyCode::Right) => match state.phrase_editor_entered() { true => TimeCursorSet(state.note_axis().write().unwrap().point_plus(1)), false => TimeScrollSet(state.note_axis().write().unwrap().start_plus(1)), }, diff --git a/crates/tek_tui/src/tui_model.rs b/crates/tek_tui/src/tui_model.rs index edaa7a6c..4887ec7d 100644 --- a/crates/tek_tui/src/tui_model.rs +++ b/crates/tek_tui/src/tui_model.rs @@ -160,6 +160,19 @@ pub struct PhrasesModel { pub(crate) entered: bool, } +impl Default for PhrasesModel { + fn default () -> Self { + Self { + phrases: vec![RwLock::new(Phrase::default()).into()], + phrase: 0.into(), + scroll: 0, + mode: None, + focused: false, + entered: false, + } + } +} + #[derive(Default, Debug, Clone)] pub struct ArrangerScene { /// Name of scene diff --git a/crates/tek_tui/src/tui_view.rs b/crates/tek_tui/src/tui_view.rs index c45988cb..17429073 100644 --- a/crates/tek_tui/src/tui_view.rs +++ b/crates/tek_tui/src/tui_view.rs @@ -33,7 +33,7 @@ pub trait PhrasesViewState: Send + Sync { fn entered (&self) -> bool; fn phrases (&self) -> Vec>>; fn phrase (&self) -> usize; - fn mode (&self) -> &Option; + fn phrase_mode (&self) -> &Option; } pub trait PhraseViewState: Send + Sync { @@ -105,7 +105,7 @@ impl PhrasesViewState for PhrasesModel { fn phrase (&self) -> usize { todo!() } - fn mode (&self) -> &Option { + fn phrase_mode (&self) -> &Option { &self.mode } } @@ -123,8 +123,8 @@ impl PhrasesViewState for SequencerTui { fn phrase (&self) -> usize { todo!() } - fn mode (&self) -> &Option { - &self.phrases_mode + fn phrase_mode (&self) -> &Option { + &self.phrases.mode } } @@ -141,8 +141,8 @@ impl PhrasesViewState for ArrangerTui { fn phrase (&self) -> usize { todo!() } - fn mode (&self) -> &Option { - &self.phrases_mode + fn phrase_mode (&self) -> &Option { + &self.phrases.mode } }