mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
remove PhrasesControl trait
This commit is contained in:
parent
d1fdc7f8b6
commit
4fdc3911e4
10 changed files with 64 additions and 68 deletions
|
|
@ -54,7 +54,11 @@ pub trait ClockApi: Send + Sync {
|
||||||
fn next_launch_pulse (&self) -> usize {
|
fn next_launch_pulse (&self) -> usize {
|
||||||
let sync = self.sync().get() as usize;
|
let sync = self.sync().get() as usize;
|
||||||
let pulse = self.current().pulse.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<u32>) -> Usually<()> {
|
fn play_from (&mut self, start: Option<u32>) -> Usually<()> {
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,15 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasPhrases for ArrangerTui {
|
||||||
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&self.phrases.phrases
|
||||||
|
}
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrases.phrases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sections in the arranger app that may be focused
|
/// Sections in the arranger app that may be focused
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum ArrangerFocus {
|
pub enum ArrangerFocus {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,15 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl HasPhrases for SequencerTui {
|
||||||
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&self.phrases.phrases
|
||||||
|
}
|
||||||
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
|
&mut self.phrases.phrases
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Sections in the sequencer app that may be focused
|
/// Sections in the sequencer app that may be focused
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum SequencerFocus {
|
pub enum SequencerFocus {
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ impl Command<ArrangerTui> for ArrangerCommand {
|
||||||
Scene(cmd) => cmd.execute(state)?.map(Scene),
|
Scene(cmd) => cmd.execute(state)?.map(Scene),
|
||||||
Track(cmd) => cmd.execute(state)?.map(Track),
|
Track(cmd) => cmd.execute(state)?.map(Track),
|
||||||
Clip(cmd) => cmd.execute(state)?.map(Clip),
|
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),
|
Editor(cmd) => cmd.execute(state)?.map(Editor),
|
||||||
Clock(cmd) => cmd.execute(state)?.map(Clock),
|
Clock(cmd) => cmd.execute(state)?.map(Clock),
|
||||||
Zoom(zoom) => { todo!(); },
|
Zoom(zoom) => { todo!(); },
|
||||||
|
|
@ -152,7 +152,7 @@ fn to_arranger_command (state: &ArrangerTui, input: &TuiInput) -> Option<Arrange
|
||||||
Cmd::Editor(PhraseCommand::input_to_command(state, input)?)
|
Cmd::Editor(PhraseCommand::input_to_command(state, input)?)
|
||||||
},
|
},
|
||||||
ArrangerFocus::Phrases => {
|
ArrangerFocus::Phrases => {
|
||||||
Cmd::Phrases(PhrasesCommand::input_to_command(state, input)?)
|
Cmd::Phrases(PhrasesCommand::input_to_command(&state.phrases, input)?)
|
||||||
},
|
},
|
||||||
ArrangerFocus::Arranger => {
|
ArrangerFocus::Arranger => {
|
||||||
use ArrangerSelection::*;
|
use ArrangerSelection::*;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ pub enum FileBrowserCommand {
|
||||||
Filter(String),
|
Filter(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> Command<T> for FileBrowserCommand {
|
impl Command<PhraseListModel> for FileBrowserCommand {
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
|
||||||
use FileBrowserCommand::*;
|
use FileBrowserCommand::*;
|
||||||
use PhrasesMode::{Import, Export};
|
use PhrasesMode::{Import, Export};
|
||||||
let mode = state.phrases_mode_mut();
|
let mode = state.phrases_mode_mut();
|
||||||
|
|
@ -58,8 +58,8 @@ impl<T: PhrasesControl> Command<T> for FileBrowserCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> InputToCommand<Tui, T> for FileBrowserCommand {
|
impl InputToCommand<Tui, PhraseListModel> for FileBrowserCommand {
|
||||||
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
|
||||||
use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace};
|
use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace};
|
||||||
use FileBrowserCommand::*;
|
use FileBrowserCommand::*;
|
||||||
if let Some(PhrasesMode::Import(index, browser)) = state.phrases_mode() {
|
if let Some(PhrasesMode::Import(index, browser)) = state.phrases_mode() {
|
||||||
|
|
@ -96,8 +96,8 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for FileBrowserCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseLengthCommand {
|
impl InputToCommand<Tui, PhraseListModel> for PhraseLengthCommand {
|
||||||
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
|
||||||
use KeyCode::{Up, Down, Right, Left, Enter, Esc};
|
use KeyCode::{Up, Down, Right, Left, Enter, Esc};
|
||||||
if let Some(PhrasesMode::Length(_, length, _)) = state.phrases_mode() {
|
if let Some(PhrasesMode::Length(_, length, _)) = state.phrases_mode() {
|
||||||
Some(match from.event() {
|
Some(match from.event() {
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ pub enum PhraseLengthCommand {
|
||||||
Dec,
|
Dec,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> Command<T> for PhraseLengthCommand {
|
impl Command<PhraseListModel> for PhraseLengthCommand {
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
|
||||||
use PhraseLengthFocus::*;
|
use PhraseLengthFocus::*;
|
||||||
use PhraseLengthCommand::*;
|
use PhraseLengthCommand::*;
|
||||||
match state.phrases_mode_mut().clone() {
|
match state.phrases_mode_mut().clone() {
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ pub enum PhrasesCommand {
|
||||||
Export(FileBrowserCommand),
|
Export(FileBrowserCommand),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> Command<T> for PhrasesCommand {
|
impl Command<PhraseListModel> for PhrasesCommand {
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
|
||||||
use PhrasesCommand::*;
|
use PhrasesCommand::*;
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Phrase(command) => command.execute(state)?.map(Phrase),
|
Phrase(command) => command.execute(state)?.map(Phrase),
|
||||||
|
|
@ -61,58 +61,17 @@ impl<T: PhrasesControl> Command<T> for PhrasesCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PhrasesControl: HasPhrases {
|
impl HasPhrases for PhraseListModel {
|
||||||
fn phrase_index (&self) -> usize;
|
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
||||||
fn set_phrase_index (&self, index: usize);
|
&self.phrases
|
||||||
fn phrases_mode (&self) -> &Option<PhrasesMode>;
|
|
||||||
fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode>;
|
|
||||||
fn index_of (&self, phrase: &Phrase) -> Option<usize> {
|
|
||||||
for i in 0..self.phrases().len() {
|
|
||||||
if *self.phrases()[i].read().unwrap() == *phrase { return Some(i) }
|
|
||||||
}
|
|
||||||
return None
|
|
||||||
}
|
}
|
||||||
}
|
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
||||||
macro_rules! impl_phrases_control {
|
&mut self.phrases
|
||||||
($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<PhrasesMode> {
|
|
||||||
&self.phrases.mode
|
|
||||||
}
|
|
||||||
fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
|
|
||||||
&mut self.phrases.mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_phrases_control!(SequencerTui);
|
impl InputToCommand<Tui, PhraseListModel> for PhrasesCommand {
|
||||||
impl_phrases_control!(ArrangerTui);
|
fn input_to_command (state: &PhraseListModel, input: &TuiInput) -> Option<Self> {
|
||||||
|
|
||||||
macro_rules! impl_has_phrases {
|
|
||||||
($Struct:ident $(:: $field:ident)*) => {
|
|
||||||
impl HasPhrases for $Struct {
|
|
||||||
fn phrases (&self) -> &Vec<Arc<RwLock<Phrase>>> {
|
|
||||||
&self$(.$field)*.phrases
|
|
||||||
}
|
|
||||||
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>> {
|
|
||||||
&mut self$(.$field)*.phrases
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl_has_phrases!(PhraseListModel);
|
|
||||||
impl_has_phrases!(SequencerTui::phrases);
|
|
||||||
impl_has_phrases!(ArrangerTui::phrases);
|
|
||||||
|
|
||||||
impl<T: PhrasesControl> InputToCommand<Tui, T> for PhrasesCommand {
|
|
||||||
fn input_to_command (state: &T, input: &TuiInput) -> Option<Self> {
|
|
||||||
use PhraseRenameCommand as Rename;
|
use PhraseRenameCommand as Rename;
|
||||||
use PhraseLengthCommand as Length;
|
use PhraseLengthCommand as Length;
|
||||||
use FileBrowserCommand as Browse;
|
use FileBrowserCommand as Browse;
|
||||||
|
|
@ -126,7 +85,7 @@ impl<T: PhrasesControl> InputToCommand<Tui, T> for PhrasesCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_phrases_command <T: PhrasesControl> (state: &T, input: &TuiInput) -> Option<PhrasesCommand> {
|
fn to_phrases_command (state: &PhraseListModel, input: &TuiInput) -> Option<PhrasesCommand> {
|
||||||
use KeyCode::{Up, Down, Delete, Char};
|
use KeyCode::{Up, Down, Delete, Char};
|
||||||
use PhrasesCommand as Cmd;
|
use PhrasesCommand as Cmd;
|
||||||
use PhrasePoolCommand as Pool;
|
use PhrasePoolCommand as Pool;
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ pub enum PhraseRenameCommand {
|
||||||
Set(String),
|
Set(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> Command<T> for PhraseRenameCommand {
|
impl Command<PhraseListModel> for PhraseRenameCommand {
|
||||||
fn execute (self, state: &mut T) -> Perhaps<Self> {
|
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
|
||||||
use PhraseRenameCommand::*;
|
use PhraseRenameCommand::*;
|
||||||
match state.phrases_mode_mut().clone() {
|
match state.phrases_mode_mut().clone() {
|
||||||
Some(PhrasesMode::Rename(phrase, ref mut old_name)) => match self {
|
Some(PhrasesMode::Rename(phrase, ref mut old_name)) => match self {
|
||||||
|
|
@ -33,8 +33,8 @@ impl<T: PhrasesControl> Command<T> for PhraseRenameCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: PhrasesControl> InputToCommand<Tui, T> for PhraseRenameCommand {
|
impl InputToCommand<Tui, PhraseListModel> for PhraseRenameCommand {
|
||||||
fn input_to_command (state: &T, from: &TuiInput) -> Option<Self> {
|
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
|
||||||
use KeyCode::{Char, Backspace, Enter, Esc};
|
use KeyCode::{Char, Backspace, Enter, Esc};
|
||||||
if let Some(PhrasesMode::Rename(_, ref old_name)) = state.phrases_mode() {
|
if let Some(PhrasesMode::Rename(_, ref old_name)) = state.phrases_mode() {
|
||||||
Some(match from.event() {
|
Some(match from.event() {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ impl Command<SequencerTui> for SequencerCommand {
|
||||||
use SequencerCommand::*;
|
use SequencerCommand::*;
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Focus(cmd) => cmd.execute(state)?.map(Focus),
|
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),
|
Editor(cmd) => cmd.execute(state)?.map(Editor),
|
||||||
Clock(cmd) => cmd.execute(state)?.map(Clock),
|
Clock(cmd) => cmd.execute(state)?.map(Clock),
|
||||||
Enqueue(phrase) => {
|
Enqueue(phrase) => {
|
||||||
|
|
@ -85,7 +85,7 @@ pub fn to_sequencer_command (state: &SequencerTui, input: &TuiInput) -> Option<S
|
||||||
state.phrases.phrases[state.phrases.phrase.load(Ordering::Relaxed)].clone()
|
state.phrases.phrases[state.phrases.phrase.load(Ordering::Relaxed)].clone()
|
||||||
)),
|
)),
|
||||||
_ => Phrases(
|
_ => Phrases(
|
||||||
PhrasesCommand::input_to_command(state, input)?
|
PhrasesCommand::input_to_command(&state.phrases, input)?
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
_ => return None
|
_ => return None
|
||||||
|
|
|
||||||
|
|
@ -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<PhrasesMode> {
|
||||||
|
&self.mode
|
||||||
|
}
|
||||||
|
pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
|
||||||
|
&mut self.mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Modes for phrase pool
|
/// Modes for phrase pool
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum PhrasesMode {
|
pub enum PhrasesMode {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue