mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
87 lines
2.4 KiB
Rust
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
|
|
}
|
|
}
|