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,15 +77,14 @@ audio!(|self: ArrangerTui, client, scope|{
// Start profiling cycle
let t0 = self.perf.get_t0();
// Update transport clock
if ClockAudio(self).process(client, scope) == Control::Quit {
if Control::Quit == ClockAudio(self).process(client, scope) {
return Control::Quit
}
// Update MIDI sequencers
let tracks = &mut self.tracks;
let note_buf = &mut self.note_buf;
let midi_buf = &mut self.midi_buf;
if TracksAudio(tracks, note_buf, midi_buf, Default::default())
.process(client, scope) == Control::Quit {
if Control::Quit == TracksAudio(tracks, note_buf, midi_buf).process(client, scope) {
return Control::Quit
}
// FIXME: one of these per playing track

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!(
(_, 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();
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)]),

View file

@ -42,7 +42,7 @@ impl ArrangerScene {
}
/// Returns true if all phrases in the scene are
/// 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()
.all(|(track_index, clip)|match clip {
Some(clip) => tracks

View file

@ -1,6 +1,39 @@
use crate::*;
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 {
/// Name of track
pub(crate) name: Arc<RwLock<String>>,
@ -35,10 +68,8 @@ impl ArrangerTrack {
data
})
}
}
impl ArrangerTrackApi for ArrangerTrack {
/// Name of track
fn name (&self) -> &Arc<RwLock<String>> {
pub fn name (&self) -> &Arc<RwLock<String>> {
&self.name
}
/// Preferred width of track column
@ -50,30 +81,20 @@ impl ArrangerTrackApi for ArrangerTrack {
&mut self.width
}
/// Identifying color of track
fn color (&self) -> ItemPalette {
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 trait HasTracks<T: ArrangerTrackApi>: Send + Sync {
fn tracks (&self) -> &Vec<T>;
fn tracks_mut (&mut self) -> &mut Vec<T>;
pub const MIN_WIDTH: usize = 6;
fn width_inc (&mut self) {
*self.width_mut() += 1;
}
impl<T: ArrangerTrackApi> HasTracks<T> for Vec<T> {
fn tracks (&self) -> &Vec<T> {
self
fn width_dec (&mut self) {
if self.width() > Self::MIN_WIDTH {
*self.width_mut() -= 1;
}
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<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),
}
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
pub struct TracksAudio<'a, T: ArrangerTrackApi, H: HasTracks<T>>(
pub struct TracksAudio<'a>(
// Track collection
pub &'a mut H,
pub &'a mut [ArrangerTrack],
/// 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> {
impl<'a> Audio for TracksAudio<'a> {
#[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() {
for track in model.iter_mut() {
if PlayerAudio(track.player_mut(), note_buffer, output_buffer).process(client, scope) == Control::Quit {
return Control::Quit
}
@ -157,34 +149,3 @@ pub fn to_arranger_track_command (input: &TuiInput, t: usize, len: usize) -> Opt
_ => 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);
}
}
}