mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: refactor arranger to device
This commit is contained in:
parent
fa73821a0b
commit
89288f2920
40 changed files with 2015 additions and 1919 deletions
215
crates/device/src/arranger/arranger_select.rs
Normal file
215
crates/device/src/arranger/arranger_select.rs
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
use crate::*;
|
||||
|
||||
/// Represents the current user selection in the arranger
|
||||
#[derive(PartialEq, Clone, Copy, Debug, Default)]
|
||||
pub enum Selection {
|
||||
/// The whole mix is selected
|
||||
#[default] Mix,
|
||||
/// A MIDI input is selected.
|
||||
Input(usize),
|
||||
/// A MIDI output is selected.
|
||||
Output(usize),
|
||||
/// A scene is selected.
|
||||
Scene(usize),
|
||||
/// A track is selected.
|
||||
Track(usize),
|
||||
/// A clip (track × scene) is selected.
|
||||
TrackClip { track: usize, scene: usize },
|
||||
/// A track's MIDI input connection is selected.
|
||||
TrackInput { track: usize, port: usize },
|
||||
/// A track's MIDI output connection is selected.
|
||||
TrackOutput { track: usize, port: usize },
|
||||
/// A track device slot is selected.
|
||||
TrackDevice { track: usize, device: usize },
|
||||
}
|
||||
|
||||
/// Focus identification methods
|
||||
impl Selection {
|
||||
pub fn is_mix (&self) -> bool {
|
||||
matches!(self, Self::Mix)
|
||||
}
|
||||
pub fn is_track (&self) -> bool {
|
||||
matches!(self, Self::Track(_))
|
||||
}
|
||||
pub fn is_scene (&self) -> bool {
|
||||
matches!(self, Self::Scene(_))
|
||||
}
|
||||
pub fn is_clip (&self) -> bool {
|
||||
matches!(self, Self::TrackClip {..})
|
||||
}
|
||||
pub fn track (&self) -> Option<usize> {
|
||||
use Selection::*;
|
||||
match self {
|
||||
Track(track)
|
||||
| TrackClip { track, .. }
|
||||
| TrackInput { track, .. }
|
||||
| TrackOutput { track, .. }
|
||||
| TrackDevice { track, .. } => Some(*track),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
pub fn track_header (&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 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 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!()
|
||||
}
|
||||
}
|
||||
pub fn scene (&self) -> Option<usize> {
|
||||
use Selection::*;
|
||||
match self {
|
||||
Scene(scene) | TrackClip { scene, .. } => Some(*scene),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
pub fn 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 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!()
|
||||
}
|
||||
}
|
||||
pub fn describe (&self, tracks: &[Track], scenes: &[Scene]) -> Arc<str> {
|
||||
use Selection::*;
|
||||
format!("{}", match self {
|
||||
Mix => "Everything".to_string(),
|
||||
Scene(s) => scenes.get(*s)
|
||||
.map(|scene|format!("S{s}: {}", &scene.name))
|
||||
.unwrap_or_else(||"S??".into()),
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
impl Arrangement {
|
||||
/// Set the selection
|
||||
pub(crate) fn select (&mut self, s: Selection) {
|
||||
self.selected = s;
|
||||
// autoedit: load focused clip in editor.
|
||||
if let Some(ref mut editor) = self.editor {
|
||||
editor.set_clip(match self.selected {
|
||||
Selection::TrackClip { track, scene }
|
||||
if let Some(Some(Some(clip))) = self
|
||||
.scenes.get(scene)
|
||||
.map(|s|s.clips.get(track)) => Some(clip),
|
||||
_ => None
|
||||
});
|
||||
}
|
||||
}
|
||||
/// Launch a clip or scene
|
||||
pub(crate) fn launch (&mut self) {
|
||||
use Selection::*;
|
||||
match self.selected {
|
||||
Track(t) => {
|
||||
self.tracks[t].sequencer.enqueue_next(None)
|
||||
},
|
||||
TrackClip { track, scene } => {
|
||||
self.tracks[track].sequencer.enqueue_next(self.scenes[scene].clips[track].as_ref())
|
||||
},
|
||||
Scene(s) => {
|
||||
for t in 0..self.tracks.len() {
|
||||
self.tracks[t].sequencer.enqueue_next(self.scenes[s].clips[t].as_ref())
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
}
|
||||
/// Set the color of the selected entity
|
||||
pub fn set_color (&mut self, palette: Option<ItemTheme>) -> Option<ItemTheme> {
|
||||
use Selection::*;
|
||||
let palette = palette.unwrap_or_else(||ItemTheme::random());
|
||||
Some(match self.selected {
|
||||
Mix => {
|
||||
let old = self.color;
|
||||
self.color = palette;
|
||||
old
|
||||
},
|
||||
Scene(s) => {
|
||||
let old = self.scenes[s].color;
|
||||
self.scenes[s].color = palette;
|
||||
old
|
||||
}
|
||||
Track(t) => {
|
||||
let old = self.tracks[t].color;
|
||||
self.tracks[t].color = palette;
|
||||
old
|
||||
}
|
||||
TrackClip { track, scene } => {
|
||||
if let Some(ref clip) = self.scenes[scene].clips[track] {
|
||||
let mut clip = clip.write().unwrap();
|
||||
let old = clip.color;
|
||||
clip.color = palette;
|
||||
old
|
||||
} else {
|
||||
return None
|
||||
}
|
||||
},
|
||||
_ => todo!()
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue