use crate::*; impl> + Send + Sync> HasTracks for T {} pub trait HasTracks: Has> + Send + Sync { fn tracks (&self) -> &Vec { Has::>::get(self) } fn tracks_mut (&mut self) -> &mut Vec { Has::>::get_mut(self) } /// Run audio callbacks for every track and every device fn process_tracks (&mut self, client: &Client, scope: &ProcessScope) -> Control { for track in self.tracks_mut().iter_mut() { if Control::Quit == Audio::process(&mut track.sequencer, client, scope) { return Control::Quit } for device in track.devices.iter_mut() { if Control::Quit == DeviceAudio(device).process(client, scope) { return Control::Quit } } } Control::Continue } fn track_longest_name (&self) -> usize { self.tracks().iter().map(|s|s.name.len()).fold(0, usize::max) } /// Stop all playing clips fn tracks_stop_all (&mut self) { for track in self.tracks_mut().iter_mut() { track.sequencer.enqueue_next(None); } } /// Stop all playing clips fn tracks_launch (&mut self, clips: Option>>>>) { if let Some(clips) = clips { for (clip, track) in clips.iter().zip(self.tracks_mut()) { track.sequencer.enqueue_next(clip.as_ref()); } } else { for track in self.tracks_mut().iter_mut() { track.sequencer.enqueue_next(None); } } } /// Iterate over tracks with their corresponding sizes. fn tracks_with_sizes ( &self, selection: &Selection, editor_width: Option ) -> impl TracksSizes<'_> { let mut x = 0; let active_track = if let Some(width) = editor_width { selection.track() } else { None }; self.tracks().iter().enumerate().map(move |(index, track)|{ let width = active_track .and_then(|_|editor_width) .unwrap_or(track.width.max(8)); let data = (index, track, x, x + width); x += width + Self::TRACK_SPACING; data }) } /// Spacing between tracks. const TRACK_SPACING: usize = 0; } impl Arrangement { /// Add multiple tracks pub fn tracks_add ( &mut self, count: usize, width: Option, mins: &[PortConnect], mouts: &[PortConnect], ) -> Usually<()> { let jack = self.jack().clone(); let track_color_1 = ItemColor::random(); let track_color_2 = ItemColor::random(); for i in 0..count { let color = track_color_1.mix(track_color_2, i as f32 / count as f32).into(); let mut track = self.track_add(None, Some(color), mins, mouts)?.1; if let Some(width) = width { track.width = width; } } Ok(()) } /// Add a track pub fn track_add ( &mut self, name: Option<&str>, color: Option, mins: &[PortConnect], mouts: &[PortConnect], ) -> Usually<(usize, &mut Track)> { self.track_last += 1; let name: Arc = name.map_or_else( ||format!("Track{:02}", self.track_last).into(), |x|x.to_string().into() ); let mut track = Track { width: (name.len() + 2).max(12), color: color.unwrap_or_else(ItemTheme::random), sequencer: Sequencer::new( &format!("{name}"), self.jack(), Some(self.clock()), None, mins, mouts )?, name, ..Default::default() }; self.tracks_mut().push(track); let len = self.tracks().len(); let index = len - 1; for scene in self.scenes_mut().iter_mut() { while scene.clips.len() < len { scene.clips.push(None); } } Ok((index, &mut self.tracks_mut()[index])) } }