diff --git a/crates/tek_api/src/api_clock.rs b/crates/tek_api/src/api_clock.rs index fad5d82b..9a8a7b5b 100644 --- a/crates/tek_api/src/api_clock.rs +++ b/crates/tek_api/src/api_clock.rs @@ -54,7 +54,11 @@ pub trait ClockApi: Send + Sync { fn next_launch_pulse (&self) -> usize { let sync = self.sync().get() as usize; let pulse = self.current().pulse.get() as usize; - if pulse % sync == 0 { pulse } else { (pulse / sync + 1) * sync } + if pulse % sync == 0 { + pulse + } else { + (pulse / sync + 1) * sync + } } fn play_from (&mut self, start: Option) -> Usually<()> { diff --git a/crates/tek_tui/src/tui_app_arranger.rs b/crates/tek_tui/src/tui_app_arranger.rs index a175a2cc..04312f37 100644 --- a/crates/tek_tui/src/tui_app_arranger.rs +++ b/crates/tek_tui/src/tui_app_arranger.rs @@ -54,6 +54,15 @@ impl TryFrom<&Arc>> for ArrangerTui { } } +impl HasPhrases for ArrangerTui { + fn phrases (&self) -> &Vec>> { + &self.phrases.phrases + } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases.phrases + } +} + /// Sections in the arranger app that may be focused #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum ArrangerFocus { diff --git a/crates/tek_tui/src/tui_app_sequencer.rs b/crates/tek_tui/src/tui_app_sequencer.rs index b2f8e1bb..968ca516 100644 --- a/crates/tek_tui/src/tui_app_sequencer.rs +++ b/crates/tek_tui/src/tui_app_sequencer.rs @@ -39,6 +39,15 @@ impl TryFrom<&Arc>> for SequencerTui { } } +impl HasPhrases for SequencerTui { + fn phrases (&self) -> &Vec>> { + &self.phrases.phrases + } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases.phrases + } +} + /// Sections in the sequencer app that may be focused #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum SequencerFocus { diff --git a/crates/tek_tui/src/tui_control_arranger.rs b/crates/tek_tui/src/tui_control_arranger.rs index 40bbb187..98fe36f5 100644 --- a/crates/tek_tui/src/tui_control_arranger.rs +++ b/crates/tek_tui/src/tui_control_arranger.rs @@ -31,7 +31,7 @@ impl Command for ArrangerCommand { Scene(cmd) => cmd.execute(state)?.map(Scene), Track(cmd) => cmd.execute(state)?.map(Track), Clip(cmd) => cmd.execute(state)?.map(Clip), - Phrases(cmd) => cmd.execute(state)?.map(Phrases), + Phrases(cmd) => cmd.execute(&mut state.phrases)?.map(Phrases), Editor(cmd) => cmd.execute(state)?.map(Editor), Clock(cmd) => cmd.execute(state)?.map(Clock), Zoom(zoom) => { todo!(); }, @@ -152,7 +152,7 @@ fn to_arranger_command (state: &ArrangerTui, input: &TuiInput) -> Option { - Cmd::Phrases(PhrasesCommand::input_to_command(state, input)?) + Cmd::Phrases(PhrasesCommand::input_to_command(&state.phrases, input)?) }, ArrangerFocus::Arranger => { use ArrangerSelection::*; diff --git a/crates/tek_tui/src/tui_control_file_browser.rs b/crates/tek_tui/src/tui_control_file_browser.rs index c5a96235..e47bf817 100644 --- a/crates/tek_tui/src/tui_control_file_browser.rs +++ b/crates/tek_tui/src/tui_control_file_browser.rs @@ -11,8 +11,8 @@ pub enum FileBrowserCommand { Filter(String), } -impl Command for FileBrowserCommand { - fn execute (self, state: &mut T) -> Perhaps { +impl Command for FileBrowserCommand { + fn execute (self, state: &mut PhraseListModel) -> Perhaps { use FileBrowserCommand::*; use PhrasesMode::{Import, Export}; let mode = state.phrases_mode_mut(); @@ -58,8 +58,8 @@ impl Command for FileBrowserCommand { } } -impl InputToCommand for FileBrowserCommand { - fn input_to_command (state: &T, from: &TuiInput) -> Option { +impl InputToCommand for FileBrowserCommand { + fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace}; use FileBrowserCommand::*; if let Some(PhrasesMode::Import(index, browser)) = state.phrases_mode() { @@ -96,8 +96,8 @@ impl InputToCommand for FileBrowserCommand { } } -impl InputToCommand for PhraseLengthCommand { - fn input_to_command (state: &T, from: &TuiInput) -> Option { +impl InputToCommand for PhraseLengthCommand { + fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { use KeyCode::{Up, Down, Right, Left, Enter, Esc}; if let Some(PhrasesMode::Length(_, length, _)) = state.phrases_mode() { Some(match from.event() { diff --git a/crates/tek_tui/src/tui_control_phrase_length.rs b/crates/tek_tui/src/tui_control_phrase_length.rs index 0cbcd9e5..03290c13 100644 --- a/crates/tek_tui/src/tui_control_phrase_length.rs +++ b/crates/tek_tui/src/tui_control_phrase_length.rs @@ -11,8 +11,8 @@ pub enum PhraseLengthCommand { Dec, } -impl Command for PhraseLengthCommand { - fn execute (self, state: &mut T) -> Perhaps { +impl Command for PhraseLengthCommand { + fn execute (self, state: &mut PhraseListModel) -> Perhaps { use PhraseLengthFocus::*; use PhraseLengthCommand::*; match state.phrases_mode_mut().clone() { diff --git a/crates/tek_tui/src/tui_control_phrase_list.rs b/crates/tek_tui/src/tui_control_phrase_list.rs index 4c9b8e15..aea620b1 100644 --- a/crates/tek_tui/src/tui_control_phrase_list.rs +++ b/crates/tek_tui/src/tui_control_phrase_list.rs @@ -10,8 +10,8 @@ pub enum PhrasesCommand { Export(FileBrowserCommand), } -impl Command for PhrasesCommand { - fn execute (self, state: &mut T) -> Perhaps { +impl Command for PhrasesCommand { + fn execute (self, state: &mut PhraseListModel) -> Perhaps { use PhrasesCommand::*; Ok(match self { Phrase(command) => command.execute(state)?.map(Phrase), @@ -61,58 +61,17 @@ impl Command for PhrasesCommand { } } -pub trait PhrasesControl: HasPhrases { - fn phrase_index (&self) -> usize; - fn set_phrase_index (&self, index: usize); - fn phrases_mode (&self) -> &Option; - fn phrases_mode_mut (&mut self) -> &mut Option; - fn index_of (&self, phrase: &Phrase) -> Option { - for i in 0..self.phrases().len() { - if *self.phrases()[i].read().unwrap() == *phrase { return Some(i) } - } - return None +impl HasPhrases for PhraseListModel { + fn phrases (&self) -> &Vec>> { + &self.phrases } -} -macro_rules! impl_phrases_control { - ($Struct:ident $(:: $field:ident)*) => { - impl PhrasesControl for $Struct { - 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 - } - } + fn phrases_mut (&mut self) -> &mut Vec>> { + &mut self.phrases } } -impl_phrases_control!(SequencerTui); -impl_phrases_control!(ArrangerTui); - -macro_rules! impl_has_phrases { - ($Struct:ident $(:: $field:ident)*) => { - impl HasPhrases for $Struct { - fn phrases (&self) -> &Vec>> { - &self$(.$field)*.phrases - } - fn phrases_mut (&mut self) -> &mut Vec>> { - &mut self$(.$field)*.phrases - } - } - } -} -impl_has_phrases!(PhraseListModel); -impl_has_phrases!(SequencerTui::phrases); -impl_has_phrases!(ArrangerTui::phrases); - -impl InputToCommand for PhrasesCommand { - fn input_to_command (state: &T, input: &TuiInput) -> Option { +impl InputToCommand for PhrasesCommand { + fn input_to_command (state: &PhraseListModel, input: &TuiInput) -> Option { use PhraseRenameCommand as Rename; use PhraseLengthCommand as Length; use FileBrowserCommand as Browse; @@ -126,7 +85,7 @@ impl InputToCommand for PhrasesCommand { } } -fn to_phrases_command (state: &T, input: &TuiInput) -> Option { +fn to_phrases_command (state: &PhraseListModel, input: &TuiInput) -> Option { use KeyCode::{Up, Down, Delete, Char}; use PhrasesCommand as Cmd; use PhrasePoolCommand as Pool; diff --git a/crates/tek_tui/src/tui_control_phrase_rename.rs b/crates/tek_tui/src/tui_control_phrase_rename.rs index dcd509fd..bd90e91b 100644 --- a/crates/tek_tui/src/tui_control_phrase_rename.rs +++ b/crates/tek_tui/src/tui_control_phrase_rename.rs @@ -8,8 +8,8 @@ pub enum PhraseRenameCommand { Set(String), } -impl Command for PhraseRenameCommand { - fn execute (self, state: &mut T) -> Perhaps { +impl Command for PhraseRenameCommand { + fn execute (self, state: &mut PhraseListModel) -> Perhaps { use PhraseRenameCommand::*; match state.phrases_mode_mut().clone() { Some(PhrasesMode::Rename(phrase, ref mut old_name)) => match self { @@ -33,8 +33,8 @@ impl Command for PhraseRenameCommand { } } -impl InputToCommand for PhraseRenameCommand { - fn input_to_command (state: &T, from: &TuiInput) -> Option { +impl InputToCommand for PhraseRenameCommand { + fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { use KeyCode::{Char, Backspace, Enter, Esc}; if let Some(PhrasesMode::Rename(_, ref old_name)) = state.phrases_mode() { Some(match from.event() { diff --git a/crates/tek_tui/src/tui_control_sequencer.rs b/crates/tek_tui/src/tui_control_sequencer.rs index 4df44484..8e9030ee 100644 --- a/crates/tek_tui/src/tui_control_sequencer.rs +++ b/crates/tek_tui/src/tui_control_sequencer.rs @@ -23,7 +23,7 @@ impl Command for SequencerCommand { use SequencerCommand::*; Ok(match self { Focus(cmd) => cmd.execute(state)?.map(Focus), - Phrases(cmd) => cmd.execute(state)?.map(Phrases), + Phrases(cmd) => cmd.execute(&mut state.phrases)?.map(Phrases), Editor(cmd) => cmd.execute(state)?.map(Editor), Clock(cmd) => cmd.execute(state)?.map(Clock), Enqueue(phrase) => { @@ -85,7 +85,7 @@ pub fn to_sequencer_command (state: &SequencerTui, input: &TuiInput) -> Option Phrases( - PhrasesCommand::input_to_command(state, input)? + PhrasesCommand::input_to_command(&state.phrases, input)? ), } _ => return None diff --git a/crates/tek_tui/src/tui_model_phrase_list.rs b/crates/tek_tui/src/tui_model_phrase_list.rs index 0fc2fbdf..6786d08b 100644 --- a/crates/tek_tui/src/tui_model_phrase_list.rs +++ b/crates/tek_tui/src/tui_model_phrase_list.rs @@ -23,6 +23,21 @@ impl Default for PhraseListModel { } } +impl PhraseListModel { + pub(crate) fn phrase_index (&self) -> usize { + self.phrase.load(Ordering::Relaxed) + } + pub(crate) fn set_phrase_index (&self, value: usize) { + self.phrase.store(value, Ordering::Relaxed); + } + pub(crate) fn phrases_mode (&self) -> &Option { + &self.mode + } + pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option { + &mut self.mode + } +} + /// Modes for phrase pool #[derive(Debug, Clone)] pub enum PhrasesMode {