use crate::*; impl Arranger { pub fn track_next_name (&self) -> String { format!("T{}", self.tracks.len() + 1) } pub fn track_add (&mut self, name: Option<&str>, color: Option) -> Usually<&mut ArrangerTrack> { let name = name.map_or_else(||self.track_next_name(), |x|x.to_string()); let track = ArrangerTrack { width: name.len() + 2, name: Arc::new(name.into()), color: color.unwrap_or_else(ItemPalette::random), player: MidiPlayer::from(&self.clock), }; self.tracks.push(track); let index = self.tracks.len() - 1; Ok(&mut self.tracks[index]) } pub fn track_del (&mut self, index: usize) { self.tracks.remove(index); for scene in self.scenes.iter_mut() { scene.clips.remove(index); } } } #[derive(Debug)] pub struct ArrangerTrack { /// Name of track pub name: Arc>, /// Preferred width of track column pub width: usize, /// Identifying color of track pub color: ItemPalette, /// MIDI player state pub player: MidiPlayer, } has_clock!(|self:ArrangerTrack|self.player.clock()); has_player!(|self:ArrangerTrack|self.player); impl ArrangerTrack { pub fn widths (tracks: &[Self]) -> Vec<(usize, usize)> { let mut widths = vec![]; let mut total = 0; for track in tracks.iter() { let width = track.width; widths.push((width, total)); total += width; } widths.push((0, total)); widths } pub fn with_widths (tracks: &[ArrangerTrack]) -> impl Iterator { let mut x = 0; tracks.iter().enumerate().map(move |(index, track)|{ let data = (index, track, x, x + track.width); x += track.width; data }) } /// Name of track pub fn name (&self) -> &Arc> { &self.name } /// Preferred width of track column fn width (&self) -> usize { self.width } /// Preferred width of track column fn width_mut (&mut self) -> &mut usize { &mut self.width } /// Identifying color of track pub fn color (&self) -> ItemPalette { self.color } fn longest_name (tracks: &[Self]) -> usize { tracks.iter().map(|s|s.name().read().unwrap().len()).fold(0, usize::max) } pub const MIN_WIDTH: usize = 6; 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>( // Track collection pub &'a mut [ArrangerTrack], /// Note buffer pub &'a mut Vec, /// Note chunk buffer pub &'a mut Vec>>, ); impl Audio for TracksAudio<'_> { #[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.iter_mut() { if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit { return Control::Quit } } Control::Continue } }