use crate::*; impl Arranger { pub fn scene_add (&mut self, name: Option<&str>, color: Option) -> Usually<&mut ArrangerScene> { let name = name.map_or_else(||self.scene_default_name(), |x|x.to_string()); let scene = ArrangerScene { name: Arc::new(name.into()), clips: vec![None;self.tracks.len()], color: color.unwrap_or_else(ItemPalette::random), }; self.scenes.push(scene); let index = self.scenes.len() - 1; Ok(&mut self.scenes[index]) } pub fn scene_del (&mut self, index: usize) { todo!("delete scene"); } fn scene_default_name (&self) -> String { format!("S{:3>}", self.scenes.len() + 1) } pub fn selected_scene (&self) -> Option<&ArrangerScene> { self.selected.scene().and_then(|s|self.scenes.get(s)) } pub fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> { self.selected.scene().and_then(|s|self.scenes.get_mut(s)) } } #[derive(Default, Debug, Clone)] pub struct ArrangerScene { /// Name of scene pub(crate) name: Arc>, /// Clips in scene, one per track pub(crate) clips: Vec>>>, /// Identifying color of scene pub(crate) color: ItemPalette, } impl ArrangerScene { pub fn name (&self) -> &Arc> { &self.name } pub fn clips (&self) -> &Vec>>> { &self.clips } pub fn color (&self) -> ItemPalette { self.color } pub 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 pub 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. pub 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().play_phrase() { *phrase.read().unwrap() == *clip.read().unwrap() } else { false } }) .unwrap_or(false), None => true }) } pub fn clip (&self, index: usize) -> Option<&Arc>> { match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None } } }