use crate::{core::*, model::*}; /// Represents the tracks and scenes of the composition. pub struct Arranger { /// Display mode of arranger pub mode: bool, /// Currently selected element. pub selected: ArrangerFocus, /// Collection of tracks. pub tracks: Vec, /// Collection of scenes. pub scenes: Vec, pub focused: bool, pub entered: bool, } impl Arranger { pub fn new () -> Self { Self { mode: false, selected: ArrangerFocus::Clip(0, 0), scenes: vec![], tracks: vec![], entered: true, focused: true, } } pub fn activate (&mut self) { match self.selected { ArrangerFocus::Scene(s) => { for (track_index, track) in self.tracks.iter_mut().enumerate() { track.sequence = self.scenes[s].clips[track_index]; track.reset = true; } }, ArrangerFocus::Clip(t, s) => { self.tracks[t].sequence = self.scenes[s].clips[t]; self.tracks[t].reset = true; }, _ => {} } } } /// Track management methods impl Arranger { pub fn track (&self) -> Option<&Track> { self.selected.track().map(|t|self.tracks.get(t)).flatten() } pub fn track_mut (&mut self) -> Option<&mut Track> { self.selected.track().map(|t|self.tracks.get_mut(t)).flatten() } pub fn track_next (&mut self) { self.selected.track_next(self.tracks.len()) } pub fn track_prev (&mut self) { self.selected.track_prev() } pub fn track_add (&mut self, name: Option<&str>) -> Usually<&mut Track> { self.tracks.push(name.map_or_else( || Track::new(&self.track_default_name()), |name| Track::new(name), )?); let index = self.tracks.len() - 1; Ok(&mut self.tracks[index]) } pub fn track_del (&mut self) { unimplemented!("Arranger::track_del"); } pub fn track_default_name (&self) -> String { format!("Track {}", self.tracks.len() + 1) } } /// Scene management methods impl Arranger { pub fn scene (&self) -> Option<&Scene> { self.selected.scene().map(|s|self.scenes.get(s)).flatten() } pub fn scene_mut (&mut self) -> Option<&mut Scene> { self.selected.scene().map(|s|self.scenes.get_mut(s)).flatten() } pub fn scene_next (&mut self) { self.selected.scene_next(self.scenes.len()) } pub fn scene_prev (&mut self) { self.selected.scene_prev() } pub fn scene_add (&mut self, name: Option<&str>) -> Usually<&mut Scene> { let clips = vec![None;self.tracks.len()]; self.scenes.push(match name { Some(name) => Scene::new(name, clips), None => Scene::new(&self.track_default_name(), clips), }); let index = self.scenes.len() - 1; Ok(&mut self.scenes[index]) } pub fn scene_del (&mut self) { unimplemented!("Arranger::scene_del"); } pub fn scene_default_name (&self) -> String { format!("Scene {}", self.scenes.len() + 1) } } /// Phrase management methods impl Arranger { pub fn phrase (&self) -> Option<&Arc>> { let track_id = self.selected.track()?; self.tracks.get(track_id)?.phrases.get((*self.scene()?.clips.get(track_id)?)?) } //pub fn phrase_mut (&mut self) -> Option<&mut Phrase> { //let track_id = self.selected.track()?; //let clip = *self.scene()?.clips.get(track_id)?; //self.tracks.get_mut(track_id)?.phrases.get_mut(clip?) //} pub fn phrase_next (&mut self) { unimplemented!(); //if let Some((track_index, track)) = self.track_mut() { //let phrases = track.phrases.len(); //if let Some((_, scene)) = self.scene_mut() { //if let Some(phrase_index) = scene.clips[track_index] { //if phrase_index >= phrases - 1 { //scene.clips[track_index] = None; //} else { //scene.clips[track_index] = Some(phrase_index + 1); //} //} else if phrases > 0 { //scene.clips[track_index] = Some(0); //} //} //} } pub fn phrase_prev (&mut self) { unimplemented!(); //if let Some((track_index, track)) = self.track_mut() { //let phrases = track.phrases.len(); //if let Some((_, scene)) = self.scene_mut() { //if let Some(phrase_index) = scene.clips[track_index] { //scene.clips[track_index] = if phrase_index == 0 { //None //} else { //Some(phrase_index - 1) //}; //} else if phrases > 0 { //scene.clips[track_index] = Some(phrases - 1); //} //} //} } } #[derive(PartialEq)] /// Represents the current user selection in the arranger pub enum ArrangerFocus { /// The whole mix is selected Mix, /// A track is selected. Track(usize), /// A scene is selected. Scene(usize), /// A clip (track × scene) is selected. Clip(usize, usize), } /// Identification methods impl ArrangerFocus { pub fn is_track (&self) -> bool { match self { Self::Track(_) => true, _ => false } } pub fn is_scene (&self) -> bool { match self { Self::Scene(_) => true, _ => false } } pub fn is_clip (&self) -> bool { match self { Self::Clip(_, _) => true, _ => false } } } /// Track methods impl ArrangerFocus { pub fn track (&self) -> Option { match self { Self::Clip(t, _) => Some(*t), Self::Track(t) => Some(*t), _ => None } } pub fn track_next (&mut self, last_track: usize) { *self = match self { Self::Mix => Self::Track(0), Self::Track(t) => Self::Track(last_track.min(*t + 1)), Self::Scene(s) => Self::Clip(0, *s), Self::Clip(t, s) => Self::Clip(last_track.min(*t + 1), *s), } } pub fn track_prev (&mut self) { *self = match self { Self::Mix => Self::Mix, Self::Scene(s) => Self::Scene(*s), Self::Track(0) => Self::Mix, Self::Track(t) => Self::Track(*t - 1), Self::Clip(t, s) => Self::Clip(t.saturating_sub(1), *s), } } } /// Scene methods impl ArrangerFocus { pub fn scene (&self) -> Option { match self { Self::Clip(_, s) => Some(*s), Self::Scene(s) => Some(*s), _ => None } } pub fn scene_next (&mut self, last_scene: usize) { *self = match self { Self::Mix => Self::Scene(0), Self::Track(t) => Self::Scene(*t), Self::Scene(s) => Self::Scene(last_scene.min(*s + 1)), Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)), } } pub fn scene_prev (&mut self) { *self = match self { Self::Mix => Self::Mix, Self::Track(t) => Self::Track(*t), Self::Scene(0) => Self::Mix, Self::Scene(s) => Self::Scene(*s - 1), Self::Clip(t, s) => Self::Clip(*t, s.saturating_sub(1)), } } }