diff --git a/crates/tek_api/src/api_clock.rs b/crates/tek_api/src/api_clock.rs index 436c73cf..1da57eb8 100644 --- a/crates/tek_api/src/api_clock.rs +++ b/crates/tek_api/src/api_clock.rs @@ -2,6 +2,11 @@ use crate::*; #[derive(Clone, Debug, PartialEq)] pub enum ClockCommand { + Play(Option), + Pause(Option), + SeekUsec(f64), + SeekSample(f64), + SeekPulse(f64), SetBpm(f64), SetQuant(f64), SetSync(f64), @@ -11,6 +16,24 @@ impl Command for ClockCommand { fn execute (self, state: &mut T) -> Perhaps { use ClockCommand::*; Ok(Some(match self { + Play(_start) => { + todo!() + }, + Pause(_start) => { + todo!() + }, + SeekUsec(usec) => { + state.current().update_from_usec(usec); + return Ok(None) + }, + SeekSample(sample) => { + state.current().update_from_sample(sample); + return Ok(None) + }, + SeekPulse(pulse) => { + state.current().update_from_pulse(pulse); + return Ok(None) + }, SetBpm(bpm) => SetBpm(state.timebase().bpm.set(bpm)), SetQuant(quant) => SetQuant(state.quant().set(quant)), SetSync(sync) => SetSync(state.sync().set(sync)), @@ -19,13 +42,12 @@ impl Command for ClockCommand { } pub trait ClockApi: Send + Sync { + /// Current moment in time + fn current (&self) -> &Arc; /// Temporal resolution in all units - fn timebase (&self) -> &Arc; - /// Note quantization factor - fn quant (&self) -> &Quantize; - /// Launch quantization factor - fn sync (&self) -> &LaunchSync; - + fn timebase (&self) -> &Arc { + &self.current().timebase + } fn sr (&self) -> &SampleRate { &self.timebase().sr } @@ -36,16 +58,93 @@ pub trait ClockApi: Send + Sync { &self.timebase().ppq } + /// Note quantization factor + fn quant (&self) -> &Arc; fn next_quant (&self) -> f64 { next_note_length(self.quant().get() as usize) as f64 } fn prev_quant (&self) -> f64 { prev_note_length(self.quant().get() as usize) as f64 } + + /// Launch quantization factor + fn sync (&self) -> &Arc; fn next_sync (&self) -> f64 { next_note_length(self.sync().get() as usize) as f64 } fn prev_sync (&self) -> f64 { prev_note_length(self.sync().get() as usize) as f64 } + + fn next_launch_pulse (&self) -> usize { + let sync = self.sync().get() as usize; + let pulse = self.current().pulse.get() as usize; + if pulse % sync == 0 { pulse } else { (pulse / sync + 1) * sync } + } + + /// Handle to JACK transport + fn transport_handle (&self) -> &Arc; + /// Playback state + fn transport_state (&self) -> &Arc>>; + /// Global sample and usec at which playback started + fn transport_offset (&self) -> &Arc>>; + + fn is_stopped (&self) -> bool { + *self.transport_state().read().unwrap() == Some(TransportState::Stopped) + } + fn is_rolling (&self) -> bool { + *self.transport_state().read().unwrap() == Some(TransportState::Rolling) + } + fn toggle_play (&self) -> Usually<()> { + let playing = self.transport_state().read().unwrap().expect("1st sample has not been processed yet"); + let playing = match playing { + TransportState::Stopped => { + self.transport_handle().start()?; + Some(TransportState::Starting) + }, + _ => { + self.transport_handle().stop()?; + self.transport_handle().locate(0)?; + Some(TransportState::Stopped) + }, + }; + *self.transport_state().write().unwrap() = playing; + Ok(()) + } +} + +/// Hosts the JACK callback for updating the temporal pointer and playback status. +pub struct ClockAudio<'a, T: ClockApi>(pub &'a mut T); + +impl<'a, T: ClockApi> Audio for ClockAudio<'a, T> { + #[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { + let state = &mut self.0; + let times = scope.cycle_times().unwrap(); + let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times; + let _chunk_size = scope.n_frames() as usize; + let transport = state.transport_handle().query().unwrap(); + state.current().sample.set(transport.pos.frame() as f64); + let mut playing = state.transport_state().write().unwrap(); + let mut started = state.transport_offset().write().unwrap(); + if *playing != Some(transport.state) { + match transport.state { + TransportState::Rolling => { + *started = Some((current_frames as usize, current_usecs as usize)) + }, + TransportState::Stopped => { + *started = None + }, + _ => {} + } + }; + *playing = Some(transport.state); + if *playing == Some(TransportState::Stopped) { + *started = None; + } + state.current().update_from_usec(match *started { + Some((_, usecs)) => current_usecs as f64 - usecs as f64, + None => 0. + }); + Control::Continue + } } diff --git a/crates/tek_api/src/api_player.rs b/crates/tek_api/src/api_player.rs index 4320d839..8906b742 100644 --- a/crates/tek_api/src/api_player.rs +++ b/crates/tek_api/src/api_player.rs @@ -7,7 +7,7 @@ pub trait HasPlayer: JackApi { pub trait MidiPlayerApi: MidiInputApi + MidiOutputApi + Send + Sync {} -pub trait HasPhrase: PlayheadApi { +pub trait HasPhrase: ClockApi { fn reset (&self) -> bool; fn reset_mut (&mut self) -> &mut bool; @@ -37,7 +37,7 @@ pub trait HasPhrase: PlayheadApi { } } -pub trait MidiInputApi: PlayheadApi + HasPhrase { +pub trait MidiInputApi: ClockApi + HasPhrase { fn midi_ins (&self) -> &Vec>; fn midi_ins_mut (&self) -> &mut Vec>; fn has_midi_ins (&self) -> bool { @@ -122,7 +122,7 @@ pub trait MidiInputApi: PlayheadApi + HasPhrase { } -pub trait MidiOutputApi: PlayheadApi + HasPhrase { +pub trait MidiOutputApi: ClockApi + HasPhrase { fn midi_outs (&self) -> &Vec>; fn midi_outs_mut (&mut self) -> &mut Vec>; @@ -165,7 +165,7 @@ pub trait MidiOutputApi: PlayheadApi + HasPhrase { // If no phrase is playing, prepare for switchover immediately next = self.phrase().is_none(); let phrase = self.phrase(); - let started0 = self.started(); + let started0 = self.transport_offset(); let timebase = self.timebase(); let notes_out = self.notes_out(); let next_phrase = self.next_phrase(); @@ -231,7 +231,7 @@ pub trait MidiOutputApi: PlayheadApi + HasPhrase { //let samples = scope.n_frames() as usize; if let Some((start_at, phrase)) = &self.next_phrase() { let start = start_at.sample.get() as usize; - let sample = self.started().read().unwrap().unwrap().0; + let sample = self.transport_offset().read().unwrap().unwrap().0; // If it's time to switch to the next phrase: if start <= sample0.saturating_sub(sample) { // Samples elapsed since phrase was supposed to start diff --git a/crates/tek_api/src/api_playhead.rs b/crates/tek_api/src/api_playhead.rs deleted file mode 100644 index 9d369b26..00000000 --- a/crates/tek_api/src/api_playhead.rs +++ /dev/null @@ -1,118 +0,0 @@ -use crate::*; - -#[derive(Clone, Debug, PartialEq)] -pub enum PlayheadCommand { - Play(Option), - Pause(Option), - SeekUsec(f64), - SeekSample(f64), - SeekPulse(f64), -} - -impl Command for PlayheadCommand { - fn execute (self, state: &mut T) -> Perhaps { - use PlayheadCommand::*; - match self { - Play(_start) => { - todo!() - }, - Pause(_start) => { - todo!() - }, - SeekUsec(usec) => { - state.current().update_from_usec(usec); - }, - SeekSample(sample) => { - state.current().update_from_sample(sample); - }, - SeekPulse(pulse) => { - state.current().update_from_pulse(pulse); - }, - }; - Ok(None) - } -} - -pub trait PlayheadApi: ClockApi { - /// Current moment in time - fn current (&self) -> &Instant; - /// Handle to JACK transport - fn transport (&self) -> &jack::Transport; - /// Playback state - fn playing (&self) -> &RwLock>; - /// Global sample and usec at which playback started - fn started (&self) -> &RwLock>; - - fn is_stopped (&self) -> bool { - *self.playing().read().unwrap() == Some(TransportState::Stopped) - } - - fn is_rolling (&self) -> bool { - *self.playing().read().unwrap() == Some(TransportState::Rolling) - } - - /// Current pulse - fn pulse (&self) -> f64 { - self.current().pulse.get() - } - - fn next_launch_pulse (&self) -> usize { - let sync = self.sync().get() as usize; - let pulse = self.pulse() as usize; - if pulse % sync == 0 { pulse } else { (pulse / sync + 1) * sync } - } - - fn toggle_play (&self) -> Usually<()> { - let playing = self.playing().read().unwrap().expect("1st sample has not been processed yet"); - let playing = match playing { - TransportState::Stopped => { - self.transport().start()?; - Some(TransportState::Starting) - }, - _ => { - self.transport().stop()?; - self.transport().locate(0)?; - Some(TransportState::Stopped) - }, - }; - *self.playing().write().unwrap() = playing; - Ok(()) - } - -} - -/// Hosts the JACK callback for updating the temporal pointer and playback status. -pub struct PlayheadAudio<'a, T: PlayheadApi>(pub &'a mut T); - -impl<'a, T: PlayheadApi> Audio for PlayheadAudio<'a, T> { - #[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { - let state = &mut self.0; - let times = scope.cycle_times().unwrap(); - let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times; - let _chunk_size = scope.n_frames() as usize; - let transport = state.transport().query().unwrap(); - state.current().sample.set(transport.pos.frame() as f64); - let mut playing = state.playing().write().unwrap(); - let mut started = state.started().write().unwrap(); - if *playing != Some(transport.state) { - match transport.state { - TransportState::Rolling => { - *started = Some((current_frames as usize, current_usecs as usize)) - }, - TransportState::Stopped => { - *started = None - }, - _ => {} - } - }; - *playing = Some(transport.state); - if *playing == Some(TransportState::Stopped) { - *started = None; - } - state.current().update_from_usec(match *started { - Some((_, usecs)) => current_usecs as f64 - usecs as f64, - None => 0. - }); - Control::Continue - } -} diff --git a/crates/tek_api/src/lib.rs b/crates/tek_api/src/lib.rs index a81cd01e..b0c6f497 100644 --- a/crates/tek_api/src/lib.rs +++ b/crates/tek_api/src/lib.rs @@ -15,7 +15,6 @@ submod! { api_jack api_phrase api_player - api_playhead api_scene api_track diff --git a/crates/tek_tui/src/tui_command.rs b/crates/tek_tui/src/tui_command.rs index 072ea264..37f8360e 100644 --- a/crates/tek_tui/src/tui_command.rs +++ b/crates/tek_tui/src/tui_command.rs @@ -4,12 +4,11 @@ use crate::*; pub enum TransportCommand { Focus(FocusCommand), Clock(ClockCommand), - Playhead(PlayheadCommand), } impl Command for TransportCommand { fn execute (self, state: &mut T) -> Perhaps { - use TransportCommand::{Focus, Clock, Playhead}; + use TransportCommand::{Focus, Clock}; use FocusCommand::{Next, Prev}; use ClockCommand::{SetBpm, SetQuant, SetSync}; Ok(Some(match self { @@ -31,23 +30,21 @@ pub enum SequencerCommand { Redo, Clear, Clock(ClockCommand), - Playhead(PlayheadCommand), Phrases(PhrasesCommand), Editor(PhraseCommand), } impl Command for SequencerCommand where - T: PhrasesControl + PhraseEditorControl + PlayheadApi + FocusGrid + T: ClockApi + PhrasesControl + PhraseEditorControl + FocusGrid { fn execute (self, state: &mut T) -> Perhaps { use SequencerCommand::*; Ok(match self { - Focus(cmd) => cmd.execute(state)?.map(Focus), - Phrases(cmd) => cmd.execute(state)?.map(Phrases), - Editor(cmd) => cmd.execute(state)?.map(Editor), - Clock(cmd) => cmd.execute(state)?.map(Clock), - Playhead(cmd) => cmd.execute(state)?.map(Playhead), + Focus(cmd) => cmd.execute(state)?.map(Focus), + Phrases(cmd) => cmd.execute(state)?.map(Phrases), + Editor(cmd) => cmd.execute(state)?.map(Editor), + Clock(cmd) => cmd.execute(state)?.map(Clock), Undo => { todo!() }, Redo => { todo!() }, Clear => { todo!() }, @@ -63,7 +60,6 @@ pub enum ArrangerCommand { Clear, Color(ItemColor), Clock(ClockCommand), - Playhead(PlayheadCommand), Scene(ArrangerSceneCommand), Track(ArrangerTrackCommand), Clip(ArrangerClipCommand), @@ -85,7 +81,6 @@ impl Command for ArrangerCommand { Phrases(cmd) => cmd.execute(state)?.map(Phrases), Editor(cmd) => cmd.execute(state)?.map(Editor), Clock(cmd) => cmd.execute(state)?.map(Clock), - Playhead(cmd) => cmd.execute(state)?.map(Playhead), Zoom(zoom) => { todo!(); }, Select(selected) => { *state.selected_mut() = selected; diff --git a/crates/tek_tui/src/tui_content.rs b/crates/tek_tui/src/tui_content.rs index abcb8358..0a0c3239 100644 --- a/crates/tek_tui/src/tui_content.rs +++ b/crates/tek_tui/src/tui_content.rs @@ -8,7 +8,7 @@ impl<'a, T: TransportViewState> Content for TransportView<'a, T> { lay!( state.transport_selected().wrap(focused, TransportFocus::PlayPause, &Styled( None, - match state.transport_state() { + match *state.transport_state().read().unwrap() { Some(TransportState::Rolling) => "▶ PLAYING", Some(TransportState::Starting) => "READY ...", Some(TransportState::Stopped) => "⏹ STOPPED", diff --git a/crates/tek_tui/src/tui_impls.rs b/crates/tek_tui/src/tui_impls.rs index 500d1374..d4c5c16a 100644 --- a/crates/tek_tui/src/tui_impls.rs +++ b/crates/tek_tui/src/tui_impls.rs @@ -13,32 +13,22 @@ macro_rules! impl_jack_api { macro_rules! impl_clock_api { ($Struct:ident $(:: $field:ident)*) => { impl ClockApi for $Struct { - fn timebase (&self) -> &Arc { - &self$(.$field)*.current.timebase - } - fn quant (&self) -> &Quantize { + fn quant (&self) -> &Arc { &self$(.$field)*.quant } - fn sync (&self) -> &LaunchSync { + fn sync (&self) -> &Arc { &self$(.$field)*.sync } - } - } -} - -macro_rules! impl_playhead_api { - ($Struct:ident $(:: $field:ident)*) => { - impl PlayheadApi for $Struct { - fn current (&self) -> &Instant { + fn current (&self) -> &Arc { &self$(.$field)*.current } - fn transport (&self) -> &jack::Transport { + fn transport_handle (&self) -> &Arc { &self$(.$field)*.transport } - fn playing (&self) -> &RwLock> { + fn transport_state (&self) -> &Arc>> { &self$(.$field)*.playing } - fn started (&self) -> &RwLock> { + fn transport_offset (&self) -> &Arc>> { &self$(.$field)*.started } } @@ -187,14 +177,9 @@ impl_jack_api!(ArrangerTui::jack); impl_clock_api!(TransportTui::state); impl_clock_api!(SequencerTui::transport); impl_clock_api!(ArrangerTui::transport); -impl_clock_api!(PhrasePlayerModel::transport); -impl_clock_api!(ArrangerTrack); -impl_playhead_api!(TransportTui::state); -impl_playhead_api!(SequencerTui::transport); -impl_playhead_api!(ArrangerTui::transport); -impl_playhead_api!(PhrasePlayerModel::transport); -impl_playhead_api!(ArrangerTrack); -impl_has_phrases!(PhrasesModel::phrases); +impl_clock_api!(PhrasePlayerModel); +impl_clock_api!(ArrangerTrack::player); +impl_has_phrases!(PhrasesModel); impl_has_phrases!(SequencerTui::phrases); impl_has_phrases!(ArrangerTui::phrases); impl_midi_player!(SequencerTui::player); diff --git a/crates/tek_tui/src/tui_input.rs b/crates/tek_tui/src/tui_input.rs index 5325a8db..41dab1ad 100644 --- a/crates/tek_tui/src/tui_input.rs +++ b/crates/tek_tui/src/tui_input.rs @@ -5,7 +5,7 @@ impl InputToCommand for TransportCommand { use KeyCode::Char; use ClockCommand::{SetBpm, SetQuant, SetSync}; use TransportFocus as Focused; - use TransportCommand::{Focus, Clock, Playhead}; + use TransportCommand::{Focus, Clock}; let focused = state.transport_focused(); Some(match input.event() { key!(Left) => Focus(FocusCommand::Prev), @@ -14,32 +14,32 @@ impl InputToCommand for TransportCommand { Focused::Bpm => Clock(SetBpm(state.bpm().get() + 1.0)), Focused::Quant => Clock(SetQuant(state.next_quant())), Focused::Sync => Clock(SetSync(state.next_sync())), - Focused::PlayPause => Playhead(todo!()), - Focused::Clock => Playhead(todo!()), + Focused::PlayPause => Clock(todo!()), + Focused::Clock => Clock(todo!()), _ => {todo!()} }, key!(Char(',')) => match focused { Focused::Bpm => Clock(SetBpm(state.bpm().get() - 1.0)), Focused::Quant => Clock(SetQuant(state.prev_quant())), Focused::Sync => Clock(SetSync(state.prev_sync())), - Focused::PlayPause => Playhead(todo!()), - Focused::Clock => Playhead(todo!()), + Focused::PlayPause => Clock(todo!()), + Focused::Clock => Clock(todo!()), _ => {todo!()} }, key!(Char('>')) => match focused { Focused::Bpm => Clock(SetBpm(state.bpm().get() + 0.001)), Focused::Quant => Clock(SetQuant(state.next_quant())), Focused::Sync => Clock(SetSync(state.next_sync())), - Focused::PlayPause => Playhead(todo!()), - Focused::Clock => Playhead(todo!()), + Focused::PlayPause => Clock(todo!()), + Focused::Clock => Clock(todo!()), _ => {todo!()} }, key!(Char('<')) => match focused { Focused::Bpm => Clock(SetBpm(state.bpm().get() - 0.001)), Focused::Quant => Clock(SetQuant(state.prev_quant())), Focused::Sync => Clock(SetSync(state.prev_sync())), - Focused::PlayPause => Playhead(todo!()), - Focused::Clock => Playhead(todo!()), + Focused::PlayPause => Clock(todo!()), + Focused::Clock => Clock(todo!()), _ => {todo!()} }, _ => return None @@ -49,7 +49,7 @@ impl InputToCommand for TransportCommand { impl InputToCommand for SequencerCommand where - T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl + PlayheadApi + T: SequencerControl + TransportControl + PhrasesControl + PhraseEditorControl + HasFocus + FocusGrid { @@ -67,10 +67,9 @@ where key!(KeyCode::Right) => Some(Self::Focus(Right)), _ => Some(match state.focused() { SequencerFocus::Transport => { - use TransportCommand::{Clock, Playhead, Focus}; + use TransportCommand::{Clock, Focus}; match TransportCommand::input_to_command(state, input)? { Clock(command) => { todo!() }, - Playhead(command) => { todo!() }, Focus(command) => { todo!() }, } }, @@ -99,14 +98,13 @@ impl InputToCommand for ArrangerCommand { key!(KeyCode::Right) => Self::Focus(Right), key!(KeyCode::Enter) => Self::Focus(Enter), key!(KeyCode::Esc) => Self::Focus(Exit), - key!(KeyCode::Char(' ')) => Self::Playhead(PlayheadCommand::Play(None)), + key!(KeyCode::Char(' ')) => Self::Clock(ClockCommand::Play(None)), _ => match state.focused() { ArrangerFocus::Menu => { todo!() }, ArrangerFocus::Transport => { - use TransportCommand::{Clock, Playhead, Focus}; + use TransportCommand::{Clock, Focus}; match TransportCommand::input_to_command(state, input)? { Clock(command) => { todo!() }, - Playhead(command) => { todo!() }, Focus(command) => { todo!() } } }, diff --git a/crates/tek_tui/src/tui_jack.rs b/crates/tek_tui/src/tui_jack.rs index 8d318aa4..4a2b0d5b 100644 --- a/crates/tek_tui/src/tui_jack.rs +++ b/crates/tek_tui/src/tui_jack.rs @@ -2,13 +2,13 @@ use crate::*; impl Audio for TransportTui { fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - PlayheadAudio(self).process(client, scope) + ClockAudio(self).process(client, scope) } } impl Audio for SequencerTui { fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { - if PlayheadAudio(self).process(client, scope) == Control::Quit { + if ClockAudio(self).process(client, scope) == Control::Quit { return Control::Quit } if PlayerAudio( diff --git a/crates/tek_tui/src/tui_model.rs b/crates/tek_tui/src/tui_model.rs index f5fd01c4..65b49ec9 100644 --- a/crates/tek_tui/src/tui_model.rs +++ b/crates/tek_tui/src/tui_model.rs @@ -1,18 +1,18 @@ use crate::*; pub struct TransportModel { - /// Playback state - pub(crate) playing: RwLock>, - /// Global sample and usec at which playback started - pub(crate) started: RwLock>, - /// Current moment in time - pub(crate) current: Instant, - /// Note quantization factor - pub(crate) quant: Quantize, - /// Launch quantization factor - pub(crate) sync: LaunchSync, /// JACK transport handle. - pub(crate) transport: jack::Transport, + pub(crate) transport: Arc, + /// Playback state + pub(crate) playing: Arc>>, + /// Global sample and usec at which playback started + pub(crate) started: Arc>>, + /// Current moment in time + pub(crate) current: Arc, + /// Note quantization factor + pub(crate) quant: Arc, + /// Launch quantization factor + pub(crate) sync: Arc, /// Enable metronome? pub(crate) metronome: bool, /// Selected transport component @@ -22,17 +22,17 @@ pub struct TransportModel { } impl From for TransportModel { - fn from (transport: jack::Transport) -> Self { + fn from (transport: Transport) -> Self { Self { - current: Instant::default(), - metronome: false, - playing: RwLock::new(None), - quant: Quantize::default(), - started: RwLock::new(None), - sync: LaunchSync::default(), + current: Instant::default().into(), focus: TransportFocus::PlayPause, is_focused: true, - transport, + metronome: false, + playing: RwLock::new(None).into(), + quant: Quantize::default().into(), + started: RwLock::new(None).into(), + sync: LaunchSync::default().into(), + transport: transport.into(), } } } @@ -40,6 +40,17 @@ impl From for TransportModel { /// Contains state for playing a phrase #[derive(Debug)] pub struct PhrasePlayerModel { + /// Playback state + pub(crate) playing: Arc>>, + /// Global sample and usec at which playback started + pub(crate) started: Arc>>, + /// Current moment in time + pub(crate) current: Arc, + /// Note quantization factor + pub(crate) quant: Arc, + /// Launch quantization factor + pub(crate) sync: Arc, + /// Start time and phrase being played pub(crate) play_phrase: Option<(Instant, Option>>)>, /// Start time and next phrase @@ -65,6 +76,11 @@ pub struct PhrasePlayerModel { impl Default for PhrasePlayerModel { fn default () -> Self { Self { + playing: RwLock::new(None).into(), + started: RwLock::new(None).into(), + current: Instant::default().into(), + quant: Quantize::default().into(), + sync: LaunchSync::default().into(), midi_ins: vec![], midi_outs: vec![], reset: true, @@ -79,6 +95,19 @@ impl Default for PhrasePlayerModel { } } +impl From<&TransportModel> for PhrasePlayerModel { + fn from (transport: &TransportModel) -> Self { + Self { + playing: transport.playing.clone(), + started: transport.started.clone(), + current: transport.current.clone(), + quant: transport.quant.clone(), + sync: transport.sync.clone(), + ..Default::default() + } + } +} + /// Contains state for viewing and editing a phrase pub struct PhraseEditorModel { /// Phrase being played @@ -252,13 +281,13 @@ impl ArrangerTracksApi for ArrangerTui { #[derive(Debug)] pub struct ArrangerTrack { /// Name of track - pub(crate) name: Arc>, + pub(crate) name: Arc>, /// Preferred width of track column - pub(crate) width: usize, + pub(crate) width: usize, /// Identifying color of track - pub(crate) color: ItemColor, + pub(crate) color: ItemColor, /// MIDI player state - pub(crate) player: PhrasePlayerModel, + pub(crate) player: PhrasePlayerModel, } impl ArrangerTrackApi for ArrangerTrack { diff --git a/crates/tek_tui/src/tui_view.rs b/crates/tek_tui/src/tui_view.rs index 4eb2b765..1adb2294 100644 --- a/crates/tek_tui/src/tui_view.rs +++ b/crates/tek_tui/src/tui_view.rs @@ -6,10 +6,9 @@ pub struct PhrasesView<'a, T: PhrasesViewState>(pub &'a T); pub struct PhraseView<'a, T: PhraseViewState>(pub &'a T); -pub trait TransportViewState: ClockApi + PlayheadApi + Send + Sync { +pub trait TransportViewState: ClockApi + Send + Sync { fn transport_selected (&self) -> TransportFocus; fn transport_focused (&self) -> bool; - fn transport_state (&self) -> Option; fn bpm_value (&self) -> f64 { self.bpm().get() } @@ -57,9 +56,6 @@ impl TransportViewState for TransportTui { fn transport_focused (&self) -> bool { true } - fn transport_state (&self) -> Option { - *self.playing().read().unwrap() - } } impl TransportViewState for SequencerTui { @@ -69,9 +65,6 @@ impl TransportViewState for SequencerTui { fn transport_focused (&self) -> bool { self.focused() == SequencerFocus::Transport } - fn transport_state (&self) -> Option { - *self.playing().read().unwrap() - } } impl TransportViewState for ArrangerTui { @@ -81,9 +74,6 @@ impl TransportViewState for ArrangerTui { fn transport_focused (&self) -> bool { self.focused() == ArrangerFocus::Transport } - fn transport_state (&self) -> Option { - *self.playing().read().unwrap() - } } impl ArrangerViewState for ArrangerTui {