use crate::*; pub trait HasTracks: Send + Sync { fn tracks (&self) -> &Vec; fn tracks_mut (&mut self) -> &mut Vec; } impl HasTracks for Vec { fn tracks (&self) -> &Vec { self } fn tracks_mut (&mut self) -> &mut Vec { self } } pub trait ArrangerTracksApi: HasTracks { fn track_add (&mut self, name: Option<&str>, color: Option)-> Usually<&mut T>; fn track_del (&mut self, index: usize); fn track_default_name (&self) -> String { format!("Track {}", self.tracks().len() + 1) } } #[derive(Clone, Debug)] pub enum ArrangerTrackCommand { Add, Delete(usize), RandomColor, Stop, Swap(usize, usize), SetSize(usize), SetZoom(usize), } pub trait ArrangerTrackApi: MidiPlayerApi + Send + Sync + Sized { /// Name of track fn name (&self) -> &Arc>; /// Preferred width of track column fn width (&self) -> usize; /// Preferred width of track column fn width_mut (&mut self) -> &mut usize; /// Identifying color of track fn color (&self) -> ItemColor; fn longest_name (tracks: &[Self]) -> usize { tracks.iter().map(|s|s.name().read().unwrap().len()).fold(0, usize::max) } const MIN_WIDTH: usize = 3; fn width_inc (&mut self) { *self.width_mut() += 1; } fn width_dec (&mut self) { if self.width() > Self::MIN_WIDTH { *self.width_mut() -= 1; } } } /// Hosts the JACK callback for a collection of tracks pub struct TracksAudio<'a, T: ArrangerTrackApi, H: HasTracks>( // Track collection pub &'a mut H, /// Note buffer pub &'a mut Vec, /// Note chunk buffer pub &'a mut Vec>>, /// Marker pub PhantomData, ); impl<'a, T: ArrangerTrackApi, H: HasTracks> Audio for TracksAudio<'a, T, H> { #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { let model = &mut self.0; let note_buffer = &mut self.1; let output_buffer = &mut self.2; for track in model.tracks_mut().iter_mut() { if PlayerAudio(track, note_buffer, output_buffer).process(client, scope) == Control::Quit { return Control::Quit } } Control::Continue } }