mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: p.42, e=22, more intermediary trait layers
This commit is contained in:
parent
638298ad32
commit
dbf6e353b7
15 changed files with 937 additions and 688 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum ClockCommand {
|
||||
SetBpm(f64),
|
||||
SetQuant(f64),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum PlayheadCommand {
|
||||
Play(Option<usize>),
|
||||
Pause(Option<usize>),
|
||||
|
|
|
|||
|
|
@ -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>>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue