use crate::*; impl> HasSelection for T {} pub trait HasSelection: Has { fn selection (&self) -> &Selection { self.get() } fn selection_mut (&mut self) -> &mut Selection { self.get_mut() } } /// Represents the current user selection in the arranger #[derive(PartialEq, Clone, Copy, Debug, Default)] pub enum Selection { #[default] /// Nothing is selected Nothing, /// The whole mix is selected Mix, /// A MIDI input is selected. Input(usize), /// A MIDI output is selected. Output(usize), /// A scene is selected. #[cfg(feature = "scene")] Scene(usize), /// A track is selected. #[cfg(feature = "track")] Track(usize), /// A clip (track × scene) is selected. #[cfg(feature = "track")] TrackClip { track: usize, scene: usize }, /// A track's MIDI input connection is selected. #[cfg(feature = "track")] TrackInput { track: usize, port: usize }, /// A track's MIDI output connection is selected. #[cfg(feature = "track")] TrackOutput { track: usize, port: usize }, /// A track device slot is selected. #[cfg(feature = "track")] TrackDevice { track: usize, device: usize }, } #[cfg(feature = "track")] impl Selection { pub fn track (&self) -> Option { use Selection::*; if let Track(track)|TrackClip{track,..}|TrackInput{track,..}|TrackOutput{track,..}|TrackDevice{track,..} = self { Some(*track) } else { None } } pub fn select_track (&self, track_count: usize) -> Self { use Selection::*; match self { Mix => Track(0), Scene(_) => Mix, Track(t) => Track((t + 1) % track_count), TrackClip { track, .. } => Track(*track), _ => todo!(), } } pub fn select_track_next (&self, len: usize) -> Self { use Selection::*; match self { Mix => Track(0), Scene(s) => TrackClip { track: 0, scene: *s }, Track(t) => if t + 1 < len { Track(t + 1) } else { Mix }, TrackClip {track, scene} => if track + 1 < len { TrackClip { track: track + 1, scene: *scene } } else { Scene(*scene) }, _ => todo!() } } pub fn select_track_prev (&self) -> Self { use Selection::*; match self { Mix => Mix, Scene(s) => Scene(*s), Track(0) => Mix, Track(t) => Track(t - 1), TrackClip { track: 0, scene } => Scene(*scene), TrackClip { track: t, scene } => TrackClip { track: t - 1, scene: *scene }, _ => todo!() } } } #[cfg(feature = "scene")] impl Selection { pub fn scene (&self) -> Option { use Selection::*; match self { Scene(scene) | TrackClip { scene, .. } => Some(*scene), _ => None } } pub fn select_scene (&self, scene_count: usize) -> Self { use Selection::*; match self { Mix | Track(_) => Scene(0), Scene(s) => Scene((s + 1) % scene_count), TrackClip { scene, .. } => Track(*scene), _ => todo!(), } } pub fn select_scene_next (&self, len: usize) -> Self { use Selection::*; match self { Mix => Scene(0), Track(t) => TrackClip { track: *t, scene: 0 }, Scene(s) => if s + 1 < len { Scene(s + 1) } else { Mix }, TrackClip { track, scene } => if scene + 1 < len { TrackClip { track: *track, scene: scene + 1 } } else { Track(*track) }, _ => todo!() } } pub fn select_scene_prev (&self) -> Self { use Selection::*; match self { Mix | Scene(0) => Mix, Scene(s) => Scene(s - 1), Track(t) => Track(*t), TrackClip { track, scene: 0 } => Track(*track), TrackClip { track, scene } => TrackClip { track: *track, scene: scene - 1 }, _ => todo!() } } } impl Selection { pub fn describe ( &self, #[cfg(feature = "track")] tracks: &[Track], #[cfg(feature = "scene")] scenes: &[Scene], ) -> Arc { use Selection::*; format!("{}", match self { Mix => "Everything".to_string(), #[cfg(feature = "scene")] Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name)).unwrap_or_else(||"S??".into()), #[cfg(feature = "track")] Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name)).unwrap_or_else(||"T??".into()), TrackClip { track, scene } => match (tracks.get(*track), scenes.get(*scene)) { (Some(_), Some(s)) => match s.clip(*track) { Some(clip) => format!("T{track} S{scene} C{}", &clip.read().unwrap().name), None => format!("T{track} S{scene}: Empty") }, _ => format!("T{track} S{scene}: Empty"), }, _ => todo!() }).into() } }