wip: modularize once again

This commit is contained in:
🪞👃🪞 2025-01-08 18:50:15 +01:00
parent e08c9d1790
commit 3b6ff81dad
44 changed files with 984 additions and 913 deletions

93
midi/src/midi_pool.rs Normal file
View file

@ -0,0 +1,93 @@
use crate::*;
pub trait HasPhrases {
fn phrases (&self) -> &Vec<Arc<RwLock<MidiClip>>>;
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<MidiClip>>>;
}
#[macro_export] macro_rules! has_phrases {
(|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => {
impl $(<$($L),*$($T $(: $U)?),*>)? HasPhrases for $Struct $(<$($L),*$($T),*>)? {
fn phrases (&$self) -> &Vec<Arc<RwLock<MidiClip>>> { &$cb }
fn phrases_mut (&mut $self) -> &mut Vec<Arc<RwLock<MidiClip>>> { &mut$cb }
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum PhrasePoolCommand {
Add(usize, MidiClip),
Delete(usize),
Swap(usize, usize),
Import(usize, PathBuf),
Export(usize, PathBuf),
SetName(usize, Arc<str>),
SetLength(usize, usize),
SetColor(usize, ItemColor),
}
impl<T: HasPhrases> Command<T> for PhrasePoolCommand {
fn execute (self, model: &mut T) -> Perhaps<Self> {
use PhrasePoolCommand::*;
Ok(match self {
Add(mut index, phrase) => {
let phrase = Arc::new(RwLock::new(phrase));
let phrases = model.phrases_mut();
if index >= phrases.len() {
index = phrases.len();
phrases.push(phrase)
} else {
phrases.insert(index, phrase);
}
Some(Self::Delete(index))
},
Delete(index) => {
let phrase = model.phrases_mut().remove(index).read().unwrap().clone();
Some(Self::Add(index, phrase))
},
Swap(index, other) => {
model.phrases_mut().swap(index, other);
Some(Self::Swap(index, other))
},
Import(index, path) => {
let bytes = std::fs::read(&path)?;
let smf = Smf::parse(bytes.as_slice())?;
let mut t = 0u32;
let mut events = vec![];
for track in smf.tracks.iter() {
for event in track.iter() {
t += event.delta.as_int();
if let TrackEventKind::Midi { channel, message } = event.kind {
events.push((t, channel.as_int(), message));
}
}
}
let mut phrase = MidiClip::new("imported", true, t as usize + 1, None, None);
for event in events.iter() {
phrase.notes[event.0 as usize].push(event.2);
}
Self::Add(index, phrase).execute(model)?
},
Export(_index, _path) => {
todo!("export phrase to midi file");
},
SetName(index, name) => {
let mut phrase = model.phrases()[index].write().unwrap();
let old_name = phrase.name.clone();
phrase.name = name;
Some(Self::SetName(index, old_name))
},
SetLength(index, length) => {
let mut phrase = model.phrases()[index].write().unwrap();
let old_len = phrase.length;
phrase.length = length;
Some(Self::SetLength(index, old_len))
},
SetColor(index, color) => {
let mut color = ItemPalette::from(color);
std::mem::swap(&mut color, &mut model.phrases()[index].write().unwrap().color);
Some(Self::SetColor(index, color.base))
},
})
}
}