remove ArrangerTrackApi and HasTracks

This commit is contained in:
🪞👃🪞 2024-12-21 03:42:58 +01:00
parent 8a2f7da8b3
commit b671d8e028
4 changed files with 54 additions and 94 deletions

View file

@ -77,17 +77,16 @@ audio!(|self: ArrangerTui, client, scope|{
// Start profiling cycle // Start profiling cycle
let t0 = self.perf.get_t0(); let t0 = self.perf.get_t0();
// Update transport clock // Update transport clock
if ClockAudio(self).process(client, scope) == Control::Quit { if Control::Quit == ClockAudio(self).process(client, scope) {
return Control::Quit return Control::Quit
} }
// Update MIDI sequencers // Update MIDI sequencers
let tracks = &mut self.tracks; let tracks = &mut self.tracks;
let note_buf = &mut self.note_buf; let note_buf = &mut self.note_buf;
let midi_buf = &mut self.midi_buf; let midi_buf = &mut self.midi_buf;
if TracksAudio(tracks, note_buf, midi_buf, Default::default()) if Control::Quit == TracksAudio(tracks, note_buf, midi_buf).process(client, scope) {
.process(client, scope) == Control::Quit { return Control::Quit
return Control::Quit }
}
// FIXME: one of these per playing track // FIXME: one of these per playing track
//self.now.set(0.); //self.now.set(0.);
//if let ArrangerSelection::Clip(t, s) = self.selected { //if let ArrangerSelection::Clip(t, s) = self.selected {

View file

@ -28,7 +28,7 @@ from!(<'a>|state: &'a ArrangerTui|ArrangerVHead<'a> = Self { // A
}); });
render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!( render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!(
(_, track, x1, x2) in ArrangerTrack::with_widths(self.tracks) => { (_, track, x1, x2) in ArrangerTrack::with_widths(self.tracks) => {
let (w, h) = (x2 - x1, HEADER_H); let (w, h) = (ArrangerTrack::MIN_WIDTH.max(x2 - x1), HEADER_H);
let color = track.color(); let color = track.color();
Tui::bg(color.base.rgb, Tui::min_xy(w as u16, h, Fixed::wh(w as u16, 5, col!([ Tui::bg(color.base.rgb, Tui::min_xy(w as u16, h, Fixed::wh(w as u16, 5, col!([
row!(![Tui::fg(color.light.rgb, ""), Self::format_name(track, w)]), row!(![Tui::fg(color.light.rgb, ""), Self::format_name(track, w)]),

View file

@ -42,7 +42,7 @@ impl ArrangerScene {
} }
/// Returns true if all phrases in the scene are /// Returns true if all phrases in the scene are
/// currently playing on the given collection of tracks. /// currently playing on the given collection of tracks.
pub fn is_playing <T: ArrangerTrackApi> (&self, tracks: &[T]) -> bool { pub fn is_playing (&self, tracks: &[ArrangerTrack]) -> bool {
self.clips().iter().any(|clip|clip.is_some()) && self.clips().iter().enumerate() self.clips().iter().any(|clip|clip.is_some()) && self.clips().iter().enumerate()
.all(|(track_index, clip)|match clip { .all(|(track_index, clip)|match clip {
Some(clip) => tracks Some(clip) => tracks

View file

@ -1,6 +1,39 @@
use crate::*; use crate::*;
use KeyCode::{Char, Delete}; use KeyCode::{Char, Delete};
impl ArrangerTui {
pub fn tracks (&self) -> &Vec<ArrangerTrack> {
&self.tracks
}
pub fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
&mut self.tracks
}
pub fn track_next_name (&self) -> String {
format!("T{}", self.tracks().len() + 1)
}
pub fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> 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: PhrasePlayerModel::from(&self.clock),
};
self.tracks_mut().push(track);
let index = self.tracks().len() - 1;
Ok(&mut self.tracks_mut()[index])
}
pub fn track_del (&mut self, index: usize) {
self.tracks_mut().remove(index);
for scene in self.scenes_mut().iter_mut() {
scene.clips.remove(index);
}
}
}
#[derive(Debug)] pub struct ArrangerTrack { #[derive(Debug)] pub struct ArrangerTrack {
/// Name of track /// Name of track
pub(crate) name: Arc<RwLock<String>>, pub(crate) name: Arc<RwLock<String>>,
@ -35,10 +68,8 @@ impl ArrangerTrack {
data data
}) })
} }
}
impl ArrangerTrackApi for ArrangerTrack {
/// Name of track /// Name of track
fn name (&self) -> &Arc<RwLock<String>> { pub fn name (&self) -> &Arc<RwLock<String>> {
&self.name &self.name
} }
/// Preferred width of track column /// Preferred width of track column
@ -50,30 +81,20 @@ impl ArrangerTrackApi for ArrangerTrack {
&mut self.width &mut self.width
} }
/// Identifying color of track /// Identifying color of track
fn color (&self) -> ItemPalette { pub fn color (&self) -> ItemPalette {
self.color self.color
} }
} fn longest_name (tracks: &[Self]) -> usize {
tracks.iter().map(|s|s.name().read().unwrap().len()).fold(0, usize::max)
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> { pub const MIN_WIDTH: usize = 6;
self fn width_inc (&mut self) {
*self.width_mut() += 1;
} }
} fn width_dec (&mut self) {
if self.width() > Self::MIN_WIDTH {
pub trait ArrangerTracksApi<T: ArrangerTrackApi>: HasTracks<T> { *self.width_mut() -= 1;
fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)-> Usually<&mut T>; }
fn track_del (&mut self, index: usize);
fn track_default_name (&self) -> String {
format!("T{}", self.tracks().len() + 1)
} }
} }
@ -88,51 +109,22 @@ pub enum ArrangerTrackCommand {
SetZoom(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) -> ItemPalette;
fn longest_name (tracks: &[Self]) -> usize {
tracks.iter().map(|s|s.name().read().unwrap().len()).fold(0, usize::max)
}
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 /// Hosts the JACK callback for a collection of tracks
pub struct TracksAudio<'a, T: ArrangerTrackApi, H: HasTracks<T>>( pub struct TracksAudio<'a>(
// Track collection // Track collection
pub &'a mut H, pub &'a mut [ArrangerTrack],
/// Note buffer /// Note buffer
pub &'a mut Vec<u8>, pub &'a mut Vec<u8>,
/// Note chunk buffer /// Note chunk buffer
pub &'a mut Vec<Vec<Vec<u8>>>, pub &'a mut Vec<Vec<Vec<u8>>>,
/// Marker
pub PhantomData<T>,
); );
impl<'a, T: ArrangerTrackApi, H: HasTracks<T>> Audio for TracksAudio<'a, T, H> { impl<'a> Audio for TracksAudio<'a> {
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control { #[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
let model = &mut self.0; let model = &mut self.0;
let note_buffer = &mut self.1; let note_buffer = &mut self.1;
let output_buffer = &mut self.2; let output_buffer = &mut self.2;
for track in model.tracks_mut().iter_mut() { for track in model.iter_mut() {
if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit { if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit {
return Control::Quit return Control::Quit
} }
@ -157,34 +149,3 @@ pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Opt
_ => return None _ => return None
}) })
} }
impl HasTracks<ArrangerTrack> for ArrangerTui {
fn tracks (&self) -> &Vec<ArrangerTrack> {
&self.tracks
}
fn tracks_mut (&mut self) -> &mut Vec<ArrangerTrack> {
&mut self.tracks
}
}
impl ArrangerTracksApi<ArrangerTrack> for ArrangerTui {
fn track_add (&mut self, name: Option<&str>, color: Option<ItemPalette>)
-> Usually<&mut ArrangerTrack>
{
let name = name.map_or_else(||self.track_default_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: PhrasePlayerModel::from(&self.clock),
};
self.tracks_mut().push(track);
let index = self.tracks().len() - 1;
Ok(&mut self.tracks_mut()[index])
}
fn track_del (&mut self, index: usize) {
self.tracks_mut().remove(index);
for scene in self.scenes_mut().iter_mut() {
scene.clips.remove(index);
}
}
}