mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
77 lines
2.8 KiB
Rust
77 lines
2.8 KiB
Rust
use crate::*;
|
|
impl Arranger {
|
|
pub fn scene_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
|
|
-> 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<RwLock<String>>,
|
|
/// Clips in scene, one per track
|
|
pub(crate) clips: Vec<Option<Arc<RwLock<MidiClip>>>>,
|
|
/// Identifying color of scene
|
|
pub(crate) color: ItemPalette,
|
|
}
|
|
impl ArrangerScene {
|
|
pub fn name (&self) -> &Arc<RwLock<String>> {
|
|
&self.name
|
|
}
|
|
pub fn clips (&self) -> &Vec<Option<Arc<RwLock<MidiClip>>>> {
|
|
&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<RwLock<MidiClip>>> {
|
|
match self.clips().get(index) { Some(Some(clip)) => Some(clip), _ => None }
|
|
}
|
|
}
|