tek/crates/tek_api/src/api_track.rs

87 lines
2.4 KiB
Rust

use crate::*;
pub trait HasTracks<T: ArrangerTrackApi>: Send + Sync {
fn tracks (&self) -> &Vec<T>;
fn tracks_mut (&mut self) -> &mut Vec<T>;
}
impl<T: ArrangerTrackApi> HasTracks<T> for Vec<T> {
fn tracks (&self) -> &Vec<T> {
self
}
fn tracks_mut (&mut self) -> &mut Vec<T> {
self
}
}
pub trait ArrangerTracksApi<T: ArrangerTrackApi>: HasTracks<T> {
fn track_add (&mut self, name: Option<&str>, color: Option<ItemColor>)-> 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: HasPlayer + Send + Sync + Sized {
/// Name of track
fn name (&self) -> &Arc<RwLock<String>>;
/// 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<T>>(
// Track collection
pub &'a mut H,
/// Note buffer
pub &'a mut Vec<u8>,
/// Note chunk buffer
pub &'a mut Vec<Vec<Vec<u8>>>,
/// Marker
pub PhantomData<T>,
);
impl<'a, T: ArrangerTrackApi, H: HasTracks<T>> 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.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit {
return Control::Quit
}
}
Control::Continue
}
}