From 79895fe3f60d639dbd9390a8bbefdeea79649202 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Fri, 15 Nov 2024 20:58:16 +0100 Subject: [PATCH] wip: refactor pt.41 (52e) --- crates/tek_api/src/api_scene.rs | 2 +- crates/tek_api/src/api_track.rs | 2 +- crates/tek_tui/src/tui_arranger.rs | 180 +++++++++++++++++----------- crates/tek_tui/src/tui_transport.rs | 29 +++-- 4 files changed, 133 insertions(+), 80 deletions(-) diff --git a/crates/tek_api/src/api_scene.rs b/crates/tek_api/src/api_scene.rs index 2a7e06e6..5618da34 100644 --- a/crates/tek_api/src/api_scene.rs +++ b/crates/tek_api/src/api_scene.rs @@ -34,7 +34,7 @@ pub enum ArrangerSceneCommand { //} pub trait ArrangerSceneApi: Sized { - fn name (&self) -> Arc>; + fn name (&self) -> &Arc>; fn clips (&self) -> &Vec>>>; fn color (&self) -> ItemColor; diff --git a/crates/tek_api/src/api_track.rs b/crates/tek_api/src/api_track.rs index 3c6e34a1..b1d920b9 100644 --- a/crates/tek_api/src/api_track.rs +++ b/crates/tek_api/src/api_track.rs @@ -33,7 +33,7 @@ pub enum ArrangerTrackCommand { pub trait ArrangerTrackApi: PlayerApi + Send + Sync + Sized { /// Name of track - fn name (&self) -> Arc>; + fn name (&self) -> &Arc>; /// Preferred width of track column fn width (&self) -> usize; /// Preferred width of track column diff --git a/crates/tek_tui/src/tui_arranger.rs b/crates/tek_tui/src/tui_arranger.rs index c4b0c7a4..5761b696 100644 --- a/crates/tek_tui/src/tui_arranger.rs +++ b/crates/tek_tui/src/tui_arranger.rs @@ -12,6 +12,14 @@ impl TryFrom<&Arc>> for ArrangerApp { transport: jack.read().unwrap().transport(), clock: Arc::new(Clock::from(Instant::default())), jack: jack.clone(), + sequencer: SequencerView::from(&model.sequencer), + split: 20, + selected: ArrangerSelection::Clip(0, 0), + mode: ArrangerMode::Vertical(2), + color: Color::Rgb(28, 35, 25).into(), + size: Measure::new(), + focused: false, + entered: false, }.into(), None, None)) } } @@ -40,6 +48,7 @@ pub type ArrangerAppCommand = AppViewCommand; #[derive(Clone, Debug)] pub enum ArrangerViewCommand { + Clear, Scene(ArrangerSceneCommand), Track(ArrangerTrackCommand), Clip(ArrangerClipCommand), @@ -69,7 +78,7 @@ impl InputToCommand> for ArrangerAppCommand { key!(KeyCode::Enter) => Self::Focus(Enter), key!(KeyCode::Esc) => Self::Focus(Exit), key!(KeyCode::Char(' ')) => { - Self::App(Transport(TransportCommand::Play(None))) + Self::App(Playhead(PlayheadCommand::Play(None))) }, _ => Self::App(match view.focused() { Content(ArrangerViewFocus::Transport) => Transport( @@ -87,8 +96,7 @@ impl InputToCommand> for ArrangerAppCommand { ) }, Content(ArrangerViewFocus::Arranger) => { - use ArrangerSelection as Focus; - use ArrangerCommand as Model; + use ArrangerSelection as Select; use ArrangerTrackCommand as Track; use ArrangerClipCommand as Clip; use ArrangerSceneCommand as Scene; @@ -100,31 +108,31 @@ impl InputToCommand> for ArrangerAppCommand { // FIXME: boundary conditions key!(KeyCode::Up) => match view.selected { - ArrangerSelection::Mix => return None, - ArrangerSelection::Track(t) => return None, - ArrangerSelection::Scene(s) => Select(Focus::Scene(s - 1)), - ArrangerSelection::Clip(t, s) => Select(Focus::Clip(t, s - 1)), + Select::Mix => return None, + Select::Track(t) => return None, + Select::Scene(s) => Select(Select::Scene(s - 1)), + Select::Clip(t, s) => Select(Select::Clip(t, s - 1)), }, key!(KeyCode::Down) => match view.selected { - ArrangerSelection::Mix => Select(Focus::Scene(0)), - ArrangerSelection::Track(t) => Select(Focus::Clip(t, 0)), - ArrangerSelection::Scene(s) => Select(Focus::Scene(s + 1)), - ArrangerSelection::Clip(t, s) => Select(Focus::Clip(t, s + 1)), + Select::Mix => Select(Select::Scene(0)), + Select::Track(t) => Select(Select::Clip(t, 0)), + Select::Scene(s) => Select(Select::Scene(s + 1)), + Select::Clip(t, s) => Select(Select::Clip(t, s + 1)), }, key!(KeyCode::Left) => match view.selected { - ArrangerSelection::Mix => return None, - ArrangerSelection::Track(t) => Select(Focus::Track(t - 1)), - ArrangerSelection::Scene(s) => return None, - ArrangerSelection::Clip(t, s) => Select(Focus::Clip(t - 1, s)), + Select::Mix => return None, + Select::Track(t) => Select(Select::Track(t - 1)), + Select::Scene(s) => return None, + Select::Clip(t, s) => Select(Select::Clip(t - 1, s)), }, key!(KeyCode::Right) => match view.selected { - ArrangerSelection::Mix => return None, - ArrangerSelection::Track(t) => Select(Focus::Track(t + 1)), - ArrangerSelection::Scene(s) => Select(Focus::Clip(0, s)), - ArrangerSelection::Clip(t, s) => Select(Focus::Clip(t, s - 1)), + Select::Mix => return None, + Select::Track(t) => Select(Select::Track(t + 1)), + Select::Scene(s) => Select(Select::Clip(0, s)), + Select::Clip(t, s) => Select(Select::Clip(t, s - 1)), }, key!(KeyCode::Char('+')) => Zoom(0), @@ -138,56 +146,56 @@ impl InputToCommand> for ArrangerAppCommand { key!(KeyCode::Char('`')) => { todo!("toggle view mode") }, key!(KeyCode::Char(',')) => match view.selected { - ArrangerSelection::Mix => Zoom(0), - 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)), + Select::Mix => Zoom(0), + Select::Track(t) => Track(Track::Swap(t, t - 1)), + Select::Scene(s) => Scene(Scene::Swap(s, s - 1)), + Select::Clip(t, s) => Clip(Clip::Set(t, s, None)), }, key!(KeyCode::Char('.')) => match view.selected { - ArrangerSelection::Mix => Zoom(0), - 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)), + Select::Mix => Zoom(0), + Select::Track(t) => Track(Track::Swap(t, t + 1)), + Select::Scene(s) => Scene(Scene::Swap(s, s + 1)), + Select::Clip(t, s) => Clip(Clip::Set(t, s, None)), }, key!(KeyCode::Char('<')) => match view.selected { - ArrangerSelection::Mix => Zoom(0), - 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)), + Select::Mix => Zoom(0), + Select::Track(t) => Track(Track::Swap(t, t - 1)), + Select::Scene(s) => Scene(Scene::Swap(s, s - 1)), + Select::Clip(t, s) => Clip(Clip::Set(t, s, None)), }, key!(KeyCode::Char('>')) => match view.selected { - ArrangerSelection::Mix => Zoom(0), - 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)), + Select::Mix => Zoom(0), + Select::Track(t) => Track(Track::Swap(t, t + 1)), + Select::Scene(s) => Scene(Scene::Swap(s, s + 1)), + Select::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) => Scene(Scene::Play(s)), - ArrangerSelection::Clip(t, s) => return None, + Select::Mix => return None, + Select::Track(t) => return None, + Select::Scene(s) => Scene(Scene::Play(s)), + Select::Clip(t, s) => return None, }, key!(KeyCode::Delete) => match view.selected { - ArrangerSelection::Mix => Edit(Model::Clear), - ArrangerSelection::Track(t) => Track(Track::Delete(t)), - ArrangerSelection::Scene(s) => Scene(Scene::Delete(s)), - ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)), + Select::Mix => Clear, + Select::Track(t) => Track(Track::Delete(t)), + Select::Scene(s) => Scene(Scene::Delete(s)), + Select::Clip(t, s) => Clip(Clip::Set(t, s, None)), }, key!(KeyCode::Char('c')) => Clip(Clip::RandomColor), key!(KeyCode::Char('s')) => match view.selected { - ArrangerSelection::Clip(t, s) => Clip(Clip::Set(t, s, None)), + Select::Clip(t, s) => Clip(Clip::Set(t, s, None)), _ => return None, }, key!(KeyCode::Char('g')) => match view.selected { - ArrangerSelection::Clip(t, s) => Clip(Clip::Get(t, s)), + Select::Clip(t, s) => Clip(Clip::Get(t, s)), _ => return None, }, @@ -275,9 +283,15 @@ impl HasJack for ArrangerView { } } -impl HasClock for ArrangerView { - fn clock (&self) -> &Arc { - &self.transport.clock() +impl ClockApi for ArrangerView { + fn current (&self) -> &Instant { + &self.current + } + fn quant (&self) -> &Quantize { + &self.quant + } + fn sync (&self) -> &LaunchSync { + &self.sync } } @@ -302,10 +316,10 @@ impl HasTracks for ArrangerView { { let name = name.map_or_else(||self.track_default_name(), |x|x.to_string()); let track = ArrangerTrack { - width: name.len() + 2, - color: color.unwrap_or_else(||ItemColor::random()), - player: MIDIPlayer::new(&self.jack(), &self.clock(), name.as_str())?, name: Arc::new(name.into()), + color: color.unwrap_or_else(||ItemColor::random()), + width: name.len() + 2, + //player: MIDIPlayer::new(&self.jack(), &self.clock(), name.as_str())?, }; self.tracks_mut().push(track); let index = self.tracks().len() - 1; @@ -389,24 +403,6 @@ pub enum ArrangerStatusBar { PhraseEdit, } -impl From for ArrangerView { - fn from (model: ArrangerModel) -> Self { - let mut view = Self { - model, - sequencer: SequencerView::from(&model.sequencer), - split: 20, - selected: ArrangerSelection::Clip(0, 0), - mode: ArrangerMode::Vertical(2), - color: Color::Rgb(28, 35, 25).into(), - size: Measure::new(), - focused: false, - entered: false, - }; - //view.update_focus(); - view - } -} - /// Arranger display mode can be cycled impl ArrangerMode { /// Cycle arranger display mode @@ -1380,7 +1376,17 @@ pub struct ArrangerScene { pub color: ItemColor, } -impl ArrangerSceneApi for ArrangerTrack {} +impl ArrangerSceneApi for ArrangerTrack { + fn name (&self) -> &Arc> { + &self.name + } + fn clips (&self) -> &Vec>>> { + &self.clips + } + fn color (&self) -> ItemColor { + self.color + } +} #[derive(Debug)] pub struct ArrangerTrack { @@ -1416,4 +1422,36 @@ pub struct ArrangerTrack { notes_out: Arc>, } -impl ArrangerTrackApi for ArrangerTrack {} +impl ArrangerTrackApi for ArrangerTrack { + /// Name of track + fn name (&self) -> &Arc> { + &self.name + } + /// Preferred width of track column + fn width (&self) -> usize { + self.width + } + /// Preferred width of track column + fn width_mut (&mut self) -> &mut usize { + &mut self.width + } + /// Identifying color of track + fn color (&self) -> ItemColor { + self.color + } +} + +impl HasMidiBuffer for ArrangerTrack { +} + +impl HasPhrase for ArrangerTrack { +} + +impl MidiInputApi for ArrangerTrack { +} + +impl MidiOutputApi for ArrangerTrack { +} + +impl PlayerApi for ArrangerTrack { +} diff --git a/crates/tek_tui/src/tui_transport.rs b/crates/tek_tui/src/tui_transport.rs index 9b999f54..8e9ba54e 100644 --- a/crates/tek_tui/src/tui_transport.rs +++ b/crates/tek_tui/src/tui_transport.rs @@ -58,7 +58,7 @@ impl InputToCommand> for TransportCommand { use AppViewFocus::Content; use ClockCommand::{SetBpm, SetQuant, SetSync}; use TransportViewFocus::{Bpm, Quant, Sync, PlayPause, Clock}; - let clock = app.app.model.clock(); + let clock = app.app.clock(); Some(match input.event() { key!(Char('.')) => match app.focused() { Content(Bpm) => SetBpm(clock.timebase().bpm.get() + 1.0), @@ -120,7 +120,7 @@ impl Command> for TransportAppCommand { impl Command> for TransportCommand { fn execute (self, state: &mut TransportApp) -> Perhaps { use ClockCommand::{SetBpm, SetQuant, SetSync}; - let clock = state.app.model.clock(); + let clock = state.app.clock(); Ok(Some(match self { SetBpm(bpm) => SetBpm(clock.timebase().bpm.set(bpm)), SetQuant(quant) => SetQuant(clock.quant.set(quant)), @@ -154,6 +154,21 @@ pub struct TransportView { size: Measure, } +impl ClockApi for TransportView { + fn current (&self) -> &Instant { + &self.current + } + fn quant (&self) -> &Quantize { + &self.quant + } + fn sync (&self) -> &LaunchSync { + &self.sync + } +} + +impl PlayheadApi for TransportView { +} + /// Which item of the transport toolbar is focused #[derive(Clone, Copy, Debug, PartialEq)] pub enum TransportViewFocus { @@ -202,7 +217,7 @@ impl Content for TransportView { lay!( self.focus.wrap(self.focused, TransportViewFocus::PlayPause, &Styled( None, - match *self.model.clock().playing.read().unwrap() { + match *self.playing().read().unwrap() { Some(TransportState::Rolling) => "▶ PLAYING", Some(TransportState::Starting) => "READY ...", Some(TransportState::Stopped) => "⏹ STOPPED", @@ -212,20 +227,20 @@ impl Content for TransportView { row!( self.focus.wrap(self.focused, TransportViewFocus::Bpm, &Outset::X(1u16, { - let bpm = self.model.clock().timebase().bpm.get(); + let bpm = self.timebase().bpm.get(); row! { "BPM ", format!("{}.{:03}", bpm as usize, (bpm * 1000.0) % 1000.0) } })), //let quant = self.focus.wrap(self.focused, TransportViewFocus::Quant, &Outset::X(1u16, row! { //"QUANT ", ppq_to_name(self.quant as usize) //})), self.focus.wrap(self.focused, TransportViewFocus::Sync, &Outset::X(1u16, row! { - "SYNC ", pulses_to_name(self.model.clock().sync.get() as usize) + "SYNC ", pulses_to_name(self.sync().get() as usize) })) ).align_w().fill_x(), self.focus.wrap(self.focused, TransportViewFocus::Clock, &{ - let time1 = self.model.clock().current.format_beat(); - let time2 = self.model.clock().current.usec.format_msu(); + let time1 = self.current().format_beat(); + let time2 = self.current().usec.format_msu(); row!("B" ,time1.as_str(), " T", time2.as_str()).outset_x(1) }).align_e().fill_x(),