wip: refactor pt.31: 41 errors

This commit is contained in:
🪞👃🪞 2024-11-14 22:46:14 +01:00
parent 28e15d3f56
commit 8b5931c321
3 changed files with 98 additions and 89 deletions

View file

@ -64,7 +64,7 @@ impl InputToCommand<Tui, ArrangerApp<Tui>> for ArrangerAppCommand {
key!(KeyCode::Char(' ')) => { key!(KeyCode::Char(' ')) => {
Self::App(Transport(TransportViewCommand::Transport(TransportCommand::Play(None)))) Self::App(Transport(TransportViewCommand::Transport(TransportCommand::Play(None))))
}, },
_ => match view.focused() { _ => Self::App(match view.focused() {
Content(ArrangerViewFocus::Transport) => Transport( Content(ArrangerViewFocus::Transport) => Transport(
TransportViewCommand::input_to_command(&view.sequencer.transport, input)? TransportViewCommand::input_to_command(&view.sequencer.transport, input)?
), ),
@ -194,44 +194,17 @@ impl InputToCommand<Tui, ArrangerApp<Tui>> for ArrangerAppCommand {
} }
} }
} }
} })
}) })
} }
} }
impl Command<ArrangerApp<Tui>> for ArrangerAppCommand { impl Command<ArrangerApp<Tui>> for ArrangerAppCommand {
fn execute (self, state: &mut ArrangerApp<Tui>) -> Perhaps<Self> { fn execute (self, state: &mut ArrangerApp<Tui>) -> Perhaps<Self> {
use AppViewCommand::*;
let undo = match self { let undo = match self {
Self::Focus(cmd) => { Focus(cmd) => { delegate(cmd, Focus, state) },
delegate(cmd, Self::Focus, state) App(cmd) => { delegate(cmd, App, state) }
},
Self::App(cmd) => match cmd {
ArrangerViewCommand::Phrases(cmd) => {
delegate(cmd, |x|Self::App(ArrangerViewCommand::Phrases(x)), &mut state.app)
},
ArrangerViewCommand::Editor(cmd) => {
delegate(cmd, |x|Self::App(ArrangerViewCommand::Editor(x)), &mut state.app)
},
ArrangerViewCommand::Transport(cmd) => {
delegate(cmd, |x|Self::App(ArrangerViewCommand::Transport(x)), &mut state.app)
},
ArrangerViewCommand::Zoom(zoom) => {
todo!();
},
ArrangerViewCommand::Select(selected) => {
state.selected = selected;
Ok(None)
},
ArrangerViewCommand::Edit(command) => {
return Ok(command.execute(&mut state.model)?.map(ArrangerViewCommand::Edit))
},
ArrangerViewCommand::EditPhrase(phrase) => {
app.sequencer.editor.phrase = phrase.clone();
state.focus(ArrangerViewFocus::PhraseEditor);
state.focus_enter();
Ok(None)
}
},
_ => {todo!()} _ => {todo!()}
}?; }?;
state.show_phrase(); state.show_phrase();
@ -240,6 +213,28 @@ impl Command<ArrangerApp<Tui>> for ArrangerAppCommand {
} }
} }
impl Command<ArrangerApp<Tui>> for ArrangerViewCommand {
fn execute (self, state: &mut ArrangerApp<Tui>) -> Perhaps<Self> {
use ArrangerViewCommand::*;
match self {
Phrases(cmd) => { delegate(cmd, Phrases, &mut state.app) },
Editor(cmd) => { delegate(cmd, Editor, &mut state.app) },
Transport(cmd) => { delegate(cmd, Transport, &mut state.app) },
Zoom(zoom) => { todo!(); },
Select(selected) => { state.selected = selected; Ok(None) },
Edit(command) => {
return Ok(command.execute(&mut state.model)?.map(ArrangerViewCommand::Edit))
},
EditPhrase(phrase) => {
state.sequencer.editor.phrase = phrase.clone();
state.focus(ArrangerViewFocus::PhraseEditor);
state.focus_enter();
Ok(None)
}
}
}
}
/// Root view for standalone `tek_arranger` /// Root view for standalone `tek_arranger`
pub struct ArrangerView<E: Engine> { pub struct ArrangerView<E: Engine> {
pub model: ArrangerModel, pub model: ArrangerModel,

View file

@ -352,7 +352,7 @@ const NTH_OCTAVE: [&'static str; 11] = [
"-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8",
]; ];
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq, Debug)]
pub enum PhraseEditorCommand { pub enum PhraseEditorCommand {
// TODO: 1-9 seek markers that by default start every 8th of the phrase // TODO: 1-9 seek markers that by default start every 8th of the phrase
ToggleDirection, ToggleDirection,

View file

@ -1,5 +1,22 @@
use crate::*; use crate::*;
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerApp<Tui> {
type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
let clock = Arc::new(Clock::from(Instant::default()));
Ok(Self::new(SequencerModel {
phrases: vec![],
player: MIDIPlayer::new(jack, &clock, "preview")?,
transport: TransportModel {
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
clock: clock.clone()
},
}.into(), None, None))
}
}
pub type SequencerApp<E: Engine> = AppView< pub type SequencerApp<E: Engine> = AppView<
E, E,
SequencerView<E>, SequencerView<E>,
@ -7,13 +24,52 @@ pub type SequencerApp<E: Engine> = AppView<
SequencerStatusBar, SequencerStatusBar,
>; >;
#[derive(Clone, PartialEq)] impl Handle<Tui> for SequencerApp<Tui> {
fn handle (&mut self, i: &TuiInput) -> Perhaps<bool> {
SequencerAppCommand::execute_with_state(self, i)
}
}
pub type SequencerAppCommand = AppViewCommand<SequencerViewCommand>;
#[derive(Clone, Debug, PartialEq)]
pub enum SequencerViewCommand { pub enum SequencerViewCommand {
Transport(TransportCommand), Transport(TransportCommand),
Phrases(PhrasePoolViewCommand), Phrases(PhrasePoolViewCommand),
Editor(PhraseEditorCommand), Editor(PhraseEditorCommand),
} }
impl InputToCommand<Tui, SequencerApp<Tui>> for SequencerAppCommand {
fn input_to_command (state: &SequencerApp<Tui>, input: &TuiInput) -> Option<Self> {
use AppViewFocus::*;
use FocusCommand::*;
use SequencerViewCommand::*;
match input.event() {
key!(KeyCode::Tab) => Some(Self::Focus(Next)),
key!(Shift-KeyCode::Tab) => Some(Self::Focus(Prev)),
key!(KeyCode::BackTab) => Some(Self::Focus(Prev)),
key!(Shift-KeyCode::BackTab) => Some(Self::Focus(Prev)),
key!(KeyCode::Up) => Some(Self::Focus(Up)),
key!(KeyCode::Down) => Some(Self::Focus(Down)),
key!(KeyCode::Left) => Some(Self::Focus(Left)),
key!(KeyCode::Right) => Some(Self::Focus(Right)),
_ => Some(Self::App(match state.focused() {
Content(SequencerFocus::Transport) =>
TransportCommand::input_to_command(&state.transport, input)
.map(Transport),
Content(SequencerFocus::PhrasePool) =>
PhrasePoolViewCommand::input_to_command(&state.phrases, input)
.map(Phrases),
Content(SequencerFocus::PhraseEditor) =>
PhraseEditorCommand::input_to_command(&state.editor, input)
.map(Editor),
_ => return None,
}))
}
}
}
/// Root view for standalone `tek_sequencer`. /// Root view for standalone `tek_sequencer`.
pub struct SequencerView<E: Engine> { pub struct SequencerView<E: Engine> {
pub model: SequencerModel, pub model: SequencerModel,
@ -46,23 +102,6 @@ pub enum SequencerStatusBar {
PhraseEditor, PhraseEditor,
} }
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerApp<Tui> {
type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
let clock = Arc::new(Clock::from(Instant::default()));
Ok(Self::new(SequencerModel {
phrases: vec![],
player: MIDIPlayer::new(jack, &clock, "preview")?,
transport: TransportModel {
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
clock: clock.clone()
},
}.into(), None, None))
}
}
impl<E: Engine> From<SequencerModel> for SequencerView<E> { impl<E: Engine> From<SequencerModel> for SequencerView<E> {
fn from (model: SequencerModel) -> Self { fn from (model: SequencerModel) -> Self {
Self { Self {
@ -88,7 +127,7 @@ impl Content for SequencerView<Tui> {
} }
} }
impl Audio for SequencerView<Tui> { impl<E: Engine> Audio for SequencerView<E> {
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
self.model.process(client, scope) self.model.process(client, scope)
} }
@ -112,48 +151,23 @@ impl Content for SequencerStatusBar {
} }
} }
impl Handle<Tui> for SequencerApp<Tui> { impl Command<SequencerApp<Tui>> for SequencerAppCommand {
fn handle (&mut self, i: &TuiInput) -> Perhaps<bool> { fn execute (self, state: &mut SequencerApp<Tui>) -> Perhaps<Self> {
SequencerViewCommand::execute_with_state(self, i) use AppViewCommand::*;
}
}
impl<E: Engine> Command<SequencerApp<E>> for SequencerViewCommand {
fn execute (self, state: &mut SequencerApp<E>) -> Perhaps<Self> {
match self { match self {
Self::Focus(cmd) => delegate(cmd, Self::Focus, state), Focus(cmd) => delegate(cmd, Focus, state),
Self::Phrases(cmd) => delegate(cmd, Self::Phrases, &mut state.phrases), App(cmd) => delegate(cmd, App, state),
Self::Editor(cmd) => delegate(cmd, Self::Editor, &mut state.editor),
Self::Transport(cmd) => delegate(cmd, Self::Transport, &mut state.transport)
} }
} }
} }
impl InputToCommand<Tui, SequencerApp<Tui>> for SequencerViewCommand { impl Command<SequencerApp<Tui>> for SequencerViewCommand {
fn input_to_command (state: &SequencerApp<Tui>, input: &TuiInput) -> Option<Self> { fn execute (self, state: &mut SequencerApp<Tui>) -> Perhaps<Self> {
use AppViewFocus::*; use SequencerViewCommand::*;
use FocusCommand::*; match self {
match input.event() { Phrases(cmd) => delegate(cmd, Phrases, &mut state.phrases),
key!(KeyCode::Tab) => Some(Self::Focus(Next)), Editor(cmd) => delegate(cmd, Editor, &mut state.editor),
key!(Shift-KeyCode::Tab) => Some(Self::Focus(Prev)), Transport(cmd) => delegate(cmd, Transport, &mut state.transport)
key!(KeyCode::BackTab) => Some(Self::Focus(Prev)),
key!(Shift-KeyCode::BackTab) => Some(Self::Focus(Prev)),
key!(KeyCode::Up) => Some(Self::Focus(Up)),
key!(KeyCode::Down) => Some(Self::Focus(Down)),
key!(KeyCode::Left) => Some(Self::Focus(Left)),
key!(KeyCode::Right) => Some(Self::Focus(Right)),
_ => match state.focused() {
Content(SequencerFocus::Transport) =>
TransportViewCommand::input_to_command(&state.transport, input)
.map(Self::Transport),
Content(SequencerFocus::PhrasePool) =>
PhrasePoolViewCommand::input_to_command(&state.phrases, input)
.map(Self::Phrases),
Content(SequencerFocus::PhraseEditor) =>
PhraseEditorCommand::input_to_command(&state.editor, input)
.map(Self::Editor),
_ => None,
}
} }
} }
} }