mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
wip: refactor pt.41 (57e) nice
This commit is contained in:
parent
c875d87c33
commit
8856353eab
32 changed files with 911 additions and 1019 deletions
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
|
|
@ -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>>>,
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue