use crate::*; pub trait HasPlayClip: HasClock { fn reset (&self) -> bool; fn reset_mut (&mut self) -> &mut bool; fn play_clip (&self) -> &Option<(Moment, Option>>)>; fn play_clip_mut (&mut self) -> &mut Option<(Moment, Option>>)>; fn next_clip (&self) -> &Option<(Moment, Option>>)>; fn next_clip_mut (&mut self) -> &mut Option<(Moment, Option>>)>; fn pulses_since_start (&self) -> Option { if let Some((started, Some(_))) = self.play_clip().as_ref() { let elapsed = self.clock().playhead.pulse.get() - started.pulse.get(); return Some(elapsed) } None } fn pulses_since_start_looped (&self) -> Option<(f64, f64)> { if let Some((started, Some(clip))) = self.play_clip().as_ref() { let elapsed = self.clock().playhead.pulse.get() - started.pulse.get(); let length = clip.read().unwrap().length.max(1); // prevent div0 on empty clip let times = (elapsed as usize / length) as f64; let elapsed = (elapsed as usize % length) as f64; return Some((times, elapsed)) } None } fn enqueue_next (&mut self, clip: Option<&Arc>>) { *self.next_clip_mut() = Some((self.clock().next_launch_instant(), clip.cloned())); *self.reset_mut() = true; } fn play_status (&self) -> impl Content { let (name, color): (Arc, ItemTheme) = if let Some((_, Some(clip))) = self.play_clip() { let MidiClip { ref name, color, .. } = *clip.read().unwrap(); (name.clone(), color) } else { ("".into(), Tui::g(64).into()) }; let time: String = self.pulses_since_start_looped() .map(|(times, time)|format!("{:>3}x {:>}", times+1.0, self.clock().timebase.format_beats_1(time))) .unwrap_or_else(||String::from(" ")).into(); FieldV(color, "Now:", format!("{} {}", time, name)) } fn next_status (&self) -> impl Content { let mut time: Arc = String::from("--.-.--").into(); let mut name: Arc = String::from("").into(); let mut color = ItemTheme::G[64]; let clock = self.clock(); if let Some((t, Some(clip))) = self.next_clip() { let clip = clip.read().unwrap(); name = clip.name.clone(); color = clip.color.clone(); time = { let target = t.pulse.get(); let current = clock.playhead.pulse.get(); if target > current { let remaining = target - current; format!("-{:>}", clock.timebase.format_beats_1(remaining)) } else { String::new() } }.into() } else if let Some((t, Some(clip))) = self.play_clip() { let clip = clip.read().unwrap(); if clip.looped { name = clip.name.clone(); color = clip.color.clone(); let target = t.pulse.get() + clip.length as f64; let current = clock.playhead.pulse.get(); if target > current { time = format!("-{:>}", clock.timebase.format_beats_0(target - current)).into() } } else { name = "Stop".to_string().into(); } }; FieldV(color, "Next:", format!("{} {}", time, name)) } }