use crate::*; pub trait HasScenes { fn scenes (&self) -> &Vec; fn scenes_mut (&mut self) -> &mut Vec; fn scene_add (&mut self, name: Option<&str>, color: Option) -> Usually<&mut S>; fn scene_del (&mut self, index: usize) { self.scenes_mut().remove(index); } fn scene_default_name (&self) -> String { format!("Scene {}", self.scenes().len() + 1) } } #[derive(Clone, Debug)] pub enum ArrangerSceneCommand { Add, Delete(usize), RandomColor, Play(usize), Swap(usize, usize), SetSize(usize), SetZoom(usize), } //impl Command for ArrangerSceneCommand { //fn execute (self, state: &mut T) -> Perhaps { //match self { //Self::Delete(index) => { state.scene_del(index); }, //_ => todo!() //} //Ok(None) //} //} pub trait ArrangerSceneApi: Sized { fn name (&self) -> Arc>; fn clips (&self) -> &Vec>>>; fn color (&self) -> ItemColor; fn ppqs (scenes: &[Self], factor: usize) -> Vec<(usize, usize)> { let mut total = 0; if factor == 0 { scenes.iter().map(|scene|{ let pulses = scene.pulses().max(PPQ); total = total + pulses; (pulses, total - pulses) }).collect() } else { (0..=scenes.len()).map(|i|{ (factor*PPQ, factor*PPQ*i) }).collect() } } fn longest_name (scenes: &[Self]) -> usize { scenes.iter().map(|s|s.name().read().unwrap().len()).fold(0, usize::max) } /// Returns the pulse length of the longest phrase in the scene fn pulses (&self) -> usize { self.clips().iter().fold(0, |a, p|{ a.max(p.as_ref().map(|q|q.read().unwrap().length).unwrap_or(0)) }) } /// Returns true if all phrases in the scene are /// currently playing on the given collection of tracks. fn is_playing (&self, tracks: &[ArrangerTrack]) -> bool { self.clips().iter().any(|clip|clip.is_some()) && self.clips().iter().enumerate() .all(|(track_index, clip)|match clip { Some(clip) => tracks .get(track_index) .map(|track|if let Some((_, Some(phrase))) = &track.player.phrase { *phrase.read().unwrap() == *clip.read().unwrap() } else { false }) .unwrap_or(false), None => true }) } fn clip (&self, index: usize) -> Option<&Arc>> { match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None } } }