mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
140 lines
5 KiB
Rust
140 lines
5 KiB
Rust
use crate::*;
|
||
|
||
impl<T: Has<Selection>> HasSelection for T {}
|
||
pub trait HasSelection: Has<Selection> {
|
||
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<usize> {
|
||
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<usize> {
|
||
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<str> {
|
||
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()
|
||
}
|
||
}
|