wip: refactor pt.41 (57e) nice

This commit is contained in:
🪞👃🪞 2024-11-15 20:09:49 +01:00
parent c875d87c33
commit 8856353eab
32 changed files with 911 additions and 1019 deletions

View file

@ -6,7 +6,7 @@ version = "0.1.0"
[dependencies]
tek_core = { path = "../tek_core" }
tek_api = { path = "../tek_api" }
tek_snd = { path = "../tek_snd" }
#tek_snd = { path = "../tek_snd" }
livi = "0.7.4"
suil-rs = { path = "../suil" }

View file

@ -2,7 +2,6 @@ pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers};
pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage};
pub(crate) use tek_core::jack::*;
pub(crate) use tek_api::*;
pub(crate) use tek_snd::*;
pub(crate) use std::collections::BTreeMap;
pub(crate) use std::sync::{Arc, Mutex, RwLock};

View file

@ -3,17 +3,15 @@ use crate::*;
impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerApp<Tui> {
type Error = Box<dyn std::error::Error>;
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
Ok(Self::new(ArrangerModel {
Ok(Self::new(ArrangerView {
name: Arc::new(RwLock::new(String::new())),
phrases: vec![],
scenes: vec![],
tracks: vec![],
transport: TransportModel {
metronome: false,
transport: jack.read().unwrap().transport(),
clock: Arc::new(Clock::from(Instant::default())),
jack: jack.clone(),
},
metronome: false,
transport: jack.read().unwrap().transport(),
clock: Arc::new(Clock::from(Instant::default())),
jack: jack.clone(),
}.into(), None, None))
}
}
@ -25,6 +23,12 @@ pub type ArrangerApp<E: Engine> = AppView<
ArrangerStatusBar
>;
impl Audio for ArrangerApp {
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
ArrangerRefAudio(self.app).process(client, scope)
}
}
/// Handle top-level events in standalone arranger.
impl Handle<Tui> for ArrangerApp<Tui> {
fn handle (&mut self, i: &TuiInput) -> Perhaps<bool> {
@ -39,10 +43,10 @@ pub enum ArrangerViewCommand {
Scene(ArrangerSceneCommand),
Track(ArrangerTrackCommand),
Clip(ArrangerClipCommand),
Edit(ArrangerCommand),
Select(ArrangerSelection),
Zoom(usize),
Transport(TransportCommand),
Clock(ClockCommand),
Playhead(PlayheadCommand),
Phrases(PhrasePoolViewCommand),
Editor(PhraseEditorCommand),
EditPhrase(Option<Arc<RwLock<Phrase>>>),
@ -135,63 +139,63 @@ impl InputToCommand<Tui, ArrangerApp<Tui>> for ArrangerAppCommand {
key!(KeyCode::Char(',')) => match view.selected {
ArrangerSelection::Mix => Zoom(0),
ArrangerSelection::Track(t) => Edit(Model::Track(Track::Swap(t, t - 1))),
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Swap(s, s - 1))),
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Track(t) => Track(Track::Swap(t, t - 1)),
ArrangerSelection::Scene(s) => Scene(Scene::Swap(s, s - 1)),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
},
key!(KeyCode::Char('.')) => match view.selected {
ArrangerSelection::Mix => Zoom(0),
ArrangerSelection::Track(t) => Edit(Model::Track(Track::Swap(t, t + 1))),
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Swap(s, s + 1))),
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Track(t) => Track(Track::Swap(t, t + 1)),
ArrangerSelection::Scene(s) => Scene(Scene::Swap(s, s + 1)),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
},
key!(KeyCode::Char('<')) => match view.selected {
ArrangerSelection::Mix => Zoom(0),
ArrangerSelection::Track(t) => Edit(Model::Track(Track::Swap(t, t - 1))),
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Swap(s, s - 1))),
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Track(t) => Track(Track::Swap(t, t - 1)),
ArrangerSelection::Scene(s) => Scene(Scene::Swap(s, s - 1)),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
},
key!(KeyCode::Char('>')) => match view.selected {
ArrangerSelection::Mix => Zoom(0),
ArrangerSelection::Track(t) => Edit(Model::Track(Track::Swap(t, t + 1))),
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Swap(s, s + 1))),
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Track(t) => Track(Track::Swap(t, t + 1)),
ArrangerSelection::Scene(s) => Scene(Scene::Swap(s, s + 1)),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
},
key!(KeyCode::Enter) => match view.selected {
ArrangerSelection::Mix => return None,
ArrangerSelection::Track(t) => return None,
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Play(s))),
ArrangerSelection::Scene(s) => Scene(Scene::Play(s)),
ArrangerSelection::Clip(t, s) => return None,
},
key!(KeyCode::Delete) => match view.selected {
ArrangerSelection::Mix => Edit(Model::Clear),
ArrangerSelection::Track(t) => Edit(Model::Track(Track::Delete(t))),
ArrangerSelection::Scene(s) => Edit(Model::Scene(Scene::Delete(s))),
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Track(t) => Track(Track::Delete(t)),
ArrangerSelection::Scene(s) => Scene(Scene::Delete(s)),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
},
key!(KeyCode::Char('c')) => Edit(Model::Clip(Clip::RandomColor)),
key!(KeyCode::Char('c')) => Clip(Clip::RandomColor),
key!(KeyCode::Char('s')) => match view.selected {
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Set(t, s, None))),
ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)),
_ => return None,
},
key!(KeyCode::Char('g')) => match view.selected {
ArrangerSelection::Clip(t, s) => Edit(Model::Clip(Clip::Get(t, s))),
ArrangerSelection::Clip(t, s) => Clip(Clip::Get(t, s)),
_ => return None,
},
key!(Ctrl-KeyCode::Char('a')) => Edit(Model::Scene(Scene::Add)),
key!(Ctrl-KeyCode::Char('a')) => Scene(Scene::Add),
key!(Ctrl-KeyCode::Char('t')) => Edit(Model::Track(Track::Add)),
key!(Ctrl-KeyCode::Char('t')) => Track(Track::Add),
key!(KeyCode::Char('l')) => Edit(Model::Clip(Clip::SetLoop(false))),
key!(KeyCode::Char('l')) => Clip(Clip::SetLoop(false)),
_ => return None
}
@ -220,17 +224,15 @@ impl Command<ArrangerApp<Tui>> for ArrangerViewCommand {
fn execute (self, state: &mut ArrangerApp<Tui>) -> Perhaps<Self> {
use ArrangerViewCommand::*;
match self {
Scene(cmd) => { delegate(cmd, Scene, &mut state.app) },
Track(cmd) => { delegate(cmd, Track, &mut state.app) },
Clip(cmd) => { delegate(cmd, Clip, &mut state.app) },
Phrases(cmd) => { delegate(cmd, Phrases, &mut state.app) },
Editor(cmd) => { delegate(cmd, Editor, &mut state.app) },
Transport(cmd) => { delegate(cmd, Transport, &mut state.app) },
Scene(cmd) => { delegate(cmd, Scene, &mut state.app) },
Track(cmd) => { delegate(cmd, Track, &mut state.app) },
Clip(cmd) => { delegate(cmd, Clip, &mut state.app) },
Phrases(cmd) => { delegate(cmd, Phrases, &mut state.app) },
Editor(cmd) => { delegate(cmd, Editor, &mut state.app) },
Clock(cmd) => { delegate(cmd, Clock, &mut state.app) },
Playhead(cmd) => { delegate(cmd, Playhead, &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);
@ -1378,6 +1380,8 @@ pub struct ArrangerScene {
pub color: ItemColor,
}
impl ArrangerSceneApi for ArrangerTrack {}
#[derive(Debug)]
pub struct ArrangerTrack {
/// Name of track
@ -1386,8 +1390,6 @@ pub struct ArrangerTrack {
pub width: usize,
/// Identifying color of track
pub color: ItemColor,
/// The MIDI player for the track
pub player: MIDIPlayer
/// Start time and phrase being played
play_phrase: Option<(Instant, Option<Arc<RwLock<Phrase>>>)>,
/// Start time and next phrase
@ -1413,3 +1415,5 @@ pub struct ArrangerTrack {
/// Notes currently held at output
notes_out: Arc<RwLock<[bool; 128]>>,
}
impl ArrangerTrackApi for ArrangerTrack {}

View file

@ -78,7 +78,6 @@ pub struct SequencerView<E: Engine> {
current: Instant,
quant: Quantize,
sync: LaunchSync,
clock: Arc<Clock>,
transport: jack::Transport,
metronome: bool,
phrases: Vec<Arc<RwLock<Phrase>>>,

View file

@ -8,7 +8,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportApp<Tui> {
metronome: false,
transport: jack.read().unwrap().transport(),
jack: jack.clone(),
clock: Arc::new(Clock::from(Instant::default()))
clock: Arc::new(Clock::from(Instant::default())),
focused: false,
focus: TransportViewFocus::PlayPause,
size: Measure::new(),
@ -33,6 +33,12 @@ impl Handle<Tui> for TransportApp<Tui> {
pub type TransportAppCommand = AppViewCommand<TransportCommand>;
#[derive(Clone, Debug)]
pub enum TransportCommand {
Clock(ClockCommand),
Playhead(PlayheadCommand),
}
impl InputToCommand<Tui, TransportApp<Tui>> for TransportAppCommand {
fn input_to_command (app: &TransportApp<Tui>, input: &TuiInput) -> Option<Self> {
use KeyCode::{Left, Right};
@ -50,7 +56,7 @@ impl InputToCommand<Tui, TransportApp<Tui>> for TransportCommand {
fn input_to_command (app: &TransportApp<Tui>, input: &TuiInput) -> Option<Self> {
use KeyCode::Char;
use AppViewFocus::Content;
use TransportCommand::{SetBpm, SetQuant, SetSync};
use ClockCommand::{SetBpm, SetQuant, SetSync};
use TransportViewFocus::{Bpm, Quant, Sync, PlayPause, Clock};
let clock = app.app.model.clock();
Some(match input.event() {
@ -113,7 +119,7 @@ impl Command<TransportApp<Tui>> for TransportAppCommand {
impl Command<TransportApp<Tui>> for TransportCommand {
fn execute (self, state: &mut TransportApp<Tui>) -> Perhaps<Self> {
use TransportCommand::{SetBpm, SetQuant, SetSync};
use ClockCommand::{SetBpm, SetQuant, SetSync};
let clock = state.app.model.clock();
Ok(Some(match self {
SetBpm(bpm) => SetBpm(clock.timebase().bpm.set(bpm)),