diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index 200f498b..506d7835 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -106,6 +106,9 @@ pub trait UsecPosition { pub trait LaunchSync { fn sync (&self) -> T; fn set_sync (&self, sync: T); + #[inline] fn next_launch (&self) -> T where Self: FramePosition { + todo!("next_launch") + } } pub trait Quantize { diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index eff3877f..ea8e3f82 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -123,7 +123,7 @@ impl Arranger { let mut app = Self { focus_cursor: (0, 1), phrases_split: 20, - arrangement_split: 20, + arrangement_split: 21, editor: PhraseEditor::new(), status: ArrangerStatusBar::ArrangementClip, clock: if let Some(ref transport) = transport { @@ -237,13 +237,13 @@ impl Arrangement { match self.selected { ArrangementFocus::Scene(s) => { for (t, track) in self.tracks.iter_mut().enumerate() { - track.player.phrase = self.scenes[s].clips[t].clone(); - track.player.reset = true; + let start = self.clock.next_launch(); + track.player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); } }, ArrangementFocus::Clip(t, s) => { - self.tracks[t].player.phrase = self.scenes[s].clips[t].clone(); - self.tracks[t].player.reset = true; + let start = self.clock.next_launch(); + self.tracks[t].player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); }, _ => {} } @@ -689,7 +689,7 @@ impl Scene { .all(|(track_index, clip)|match clip { Some(clip) => tracks .get(track_index) - .map(|track|if let Some(phrase) = &track.player.phrase { + .map(|track|if let Some((_, Some(phrase))) = &track.player.phrase { *phrase.read().unwrap() == *clip.read().unwrap() } else { false diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index b43b15da..f0a1b304 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -169,7 +169,9 @@ impl<'a> Content for VerticalArranger<'a, Tui> { let max_w = w.saturating_sub(1).min(name.len()).max(2); let name = format!("▎{}", &name[0..max_w]); let time1 = track.player.phrase.as_ref() - .map(|_|format!("▎{:>}", track.player.now.load(Ordering::Relaxed))) + .map(|_|track.player.frames_since_start()) + .flatten() + .map(|t|format!("▎{t:>}")) .unwrap_or(String::from("▎")); let time2 = track.player.switch_at.as_ref() .map(|t|format!("▎{:>}", t.load(Ordering::Relaxed))) diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index f40605b7..1f2cc93b 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -115,12 +115,10 @@ pub struct PhrasePlayer { _engine: PhantomData, /// Global timebase pub clock: Arc, - /// Phrase being played - pub phrase: Option>>, - /// Next phrase - pub next_phrase: Option>>, - /// Current point in playing phrase - pub now: Arc, + /// Start time and phrase being played + pub phrase: Option<(AtomicUsize, Option>>)>, + /// Start time and next phrase + pub next_phrase: Option<(AtomicUsize, Option>>)>, /// Frames remaining until switch to next phrase pub switch_at: Option, /// Play input through output. @@ -336,7 +334,6 @@ impl PhrasePlayer { clock: clock.clone(), phrase: None, next_phrase: None, - now: Arc::new(0.into()), switch_at: None, notes_in: Arc::new(RwLock::new([false;128])), notes_out: Arc::new(RwLock::new([false;128])), @@ -351,6 +348,15 @@ impl PhrasePlayer { pub fn toggle_monitor (&mut self) { self.monitoring = !self.monitoring; } pub fn toggle_record (&mut self) { self.recording = !self.recording; } pub fn toggle_overdub (&mut self) { self.overdub = !self.overdub; } + pub fn enqueue_next (&mut self, start_at: usize, phrase: Option<&Arc>>) { + self.next_phrase = Some((start_at.into(), phrase.map(|p|p.clone()))); + self.reset = true; + } + pub fn frames_since_start (&self) -> Option { + self.phrase.as_ref() + .map(|(started,_)|started.load(Ordering::Relaxed)) + .map(|started|started - self.clock.frame()) + } } /// Displays and edits phrase length pub struct PhraseLength { diff --git a/crates/tek_sequencer/src/sequencer_snd.rs b/crates/tek_sequencer/src/sequencer_snd.rs index 33906aaa..eb29cb3f 100644 --- a/crates/tek_sequencer/src/sequencer_snd.rs +++ b/crates/tek_sequencer/src/sequencer_snd.rs @@ -58,7 +58,7 @@ impl PhrasePlayer { if let ( Some(TransportState::Rolling), Some((start_frame, _)), - Some(ref phrase) + Some((_started, Some(ref phrase))) ) = (playing, started, &self.phrase) { phrase.read().map(|phrase|{ if self.midi_out.is_some() {