wip: p.42, e=22, more intermediary trait layers

This commit is contained in:
🪞👃🪞 2024-11-16 21:31:04 +01:00
parent 638298ad32
commit dbf6e353b7
15 changed files with 937 additions and 688 deletions

View file

@ -1,6 +1,6 @@
use crate::*;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub enum ClockCommand {
SetBpm(f64),
SetQuant(f64),

View file

@ -7,27 +7,10 @@ pub trait HasPlayer: HasJack {
pub trait PlayerApi: MidiInputApi + MidiOutputApi + Send + Sync {}
pub trait HasMidiBuffer {
fn midi_buffer (&self) -> &Vec<Vec<Vec<u8>>>;
fn midi_buffer_mut (&self) -> &mut Vec<Vec<Vec<u8>>>;
pub trait HasPhrase: PlayheadApi {
fn reset (&self) -> bool;
fn reset_mut (&mut self) -> &mut bool;
/// Clear the section of the output buffer that we will be using,
/// emitting "all notes off" at start of buffer if requested.
fn clear (&mut self, scope: &ProcessScope, force_reset: bool) {
for frame in &mut self.midi_buffer_mut()[0..scope.n_frames() as usize] {
frame.clear();
}
if self.reset() || force_reset {
all_notes_off(&mut self.midi_buffer_mut());
*self.reset_mut() = false;
}
}
}
pub trait HasPhrase: PlayheadApi + HasMidiBuffer {
fn phrase (&self)
-> &Option<(Instant, Option<Arc<RwLock<Phrase>>>)>;
fn phrase_mut (&self)
@ -54,7 +37,7 @@ pub trait HasPhrase: PlayheadApi + HasMidiBuffer {
}
}
pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
pub trait MidiInputApi: PlayheadApi + HasPhrase {
fn midi_ins (&self) -> &Vec<Port<MidiIn>>;
fn midi_ins_mut (&self) -> &mut Vec<Port<MidiIn>>;
fn has_midi_ins (&self) -> bool {
@ -80,7 +63,11 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
fn notes_in (&self) -> &Arc<RwLock<[bool;128]>>;
fn record (&mut self, scope: &ProcessScope) {
fn record (
&mut self,
scope: &ProcessScope,
midi_buf: &mut Vec<Vec<Vec<u8>>>,
) {
let sample0 = scope.last_frame_time() as usize;
if let (true, Some((started, phrase))) = (self.is_rolling(), self.phrase()) {
let start = started.sample.get() as usize;
@ -92,7 +79,7 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event {
if self.monitoring() {
self.midi_buffer_mut()[sample].push(bytes.to_vec())
midi_buf[sample].push(bytes.to_vec())
}
if self.recording() {
if let Some(phrase) = phrase {
@ -117,12 +104,16 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
}
}
fn monitor (&mut self, scope: &ProcessScope) {
fn monitor (
&mut self,
scope: &ProcessScope,
midi_buf: &mut Vec<Vec<Vec<u8>>>,
) {
let mut notes_in = self.notes_in().write().unwrap();
for input in self.midi_ins_mut().iter() {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event {
self.midi_buffer_mut()[sample].push(bytes.to_vec());
midi_buf[sample].push(bytes.to_vec());
update_keys(&mut notes_in, &message);
}
}
@ -131,7 +122,7 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
}
pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
pub trait MidiOutputApi: PlayheadApi + HasPhrase {
fn midi_outs (&self) -> &Vec<Port<MidiOut>>;
fn midi_outs_mut (&mut self) -> &mut Vec<Port<MidiOut>>;
@ -144,6 +135,22 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
self.midi_outs().len() > 0
}
/// Clear the section of the output buffer that we will be using,
/// emitting "all notes off" at start of buffer if requested.
fn clear (
&mut self,
scope: &ProcessScope,
midi_buf: &mut Vec<Vec<Vec<u8>>>,
reset: bool
) {
for frame in &mut midi_buf[0..scope.n_frames() as usize] {
frame.clear();
}
if reset {
all_notes_off(midi_buf);
}
}
fn play (
&mut self,
scope: &ProcessScope,
@ -298,26 +305,26 @@ pub struct PlayerAudio<'a, T: PlayerApi>(
/// JACK process callback for a sequencer's phrase player/recorder.
impl<'a, T: PlayerApi> Audio for PlayerAudio<'a, T> {
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
let model = &mut self.0;
let note_buffer = &mut self.1;
let output_buffer = &mut self.2;
let model = &mut self.0;
let note_buf = &mut self.1;
let midi_buf = &mut self.2;
// Clear output buffer(s)
model.clear(scope, false);
model.clear(scope, midi_buf, false);
// Write chunk of phrase to output, handle switchover
if model.play(scope, note_buffer, output_buffer) {
model.switchover(scope, note_buffer, output_buffer);
if model.play(scope, note_buf, midi_buf) {
model.switchover(scope, note_buf, midi_buf);
}
if model.has_midi_ins() {
if model.recording() || model.monitoring() {
// Record and/or monitor input
model.record(scope)
model.record(scope, midi_buf)
} else if model.has_midi_outs() && model.monitoring() {
// Monitor input to output
model.monitor(scope)
model.monitor(scope, midi_buf)
}
}
// Write to output port(s)
model.write(scope, output_buffer);
model.write(scope, midi_buf);
Control::Continue
}
}

View file

@ -1,6 +1,6 @@
use crate::*;
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub enum PlayheadCommand {
Play(Option<usize>),
Pause(Option<usize>),

View file

@ -3,6 +3,18 @@ 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 {
@ -21,16 +33,6 @@ pub enum ArrangerTrackCommand {
SetZoom(usize),
}
//impl<T: ArrangerApi> Command<T> for ArrangerTrackCommand {
//fn execute (self, state: &mut T) -> Perhaps<Self> {
//match self {
//Self::Delete(index) => { state.track_del(index); },
//_ => todo!()
//}
//Ok(None)
//}
//}
pub trait ArrangerTrackApi: PlayerApi + Send + Sync + Sized {
/// Name of track
fn name (&self) -> &Arc<RwLock<String>>;