mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
107 lines
3.4 KiB
Rust
107 lines
3.4 KiB
Rust
use crate::*;
|
|
|
|
/// Trait for thing that may receive MIDI.
|
|
pub trait HasMidiIns {
|
|
fn midi_ins (&self) -> &Vec<JackMidiIn>;
|
|
|
|
fn midi_ins_mut (&mut self) -> &mut Vec<JackMidiIn>;
|
|
|
|
fn has_midi_ins (&self) -> bool {
|
|
!self.midi_ins().is_empty()
|
|
}
|
|
}
|
|
|
|
pub trait MidiRecordApi: HasClock + HasPlayClip + HasMidiIns {
|
|
fn notes_in (&self) -> &Arc<RwLock<[bool;128]>>;
|
|
|
|
fn recording (&self) -> bool;
|
|
|
|
fn recording_mut (&mut self) -> &mut bool;
|
|
|
|
fn toggle_record (&mut self) {
|
|
*self.recording_mut() = !self.recording();
|
|
}
|
|
|
|
fn monitoring (&self) -> bool;
|
|
|
|
fn monitoring_mut (&mut self) -> &mut bool;
|
|
|
|
fn toggle_monitor (&mut self) {
|
|
*self.monitoring_mut() = !self.monitoring();
|
|
}
|
|
|
|
fn overdub (&self) -> bool;
|
|
|
|
fn overdub_mut (&mut self) -> &mut bool;
|
|
|
|
fn toggle_overdub (&mut self) {
|
|
*self.overdub_mut() = !self.overdub();
|
|
}
|
|
|
|
fn monitor (&mut self, scope: &ProcessScope, midi_buf: &mut Vec<Vec<Vec<u8>>>) {
|
|
// For highlighting keys and note repeat
|
|
let notes_in = self.notes_in().clone();
|
|
let monitoring = self.monitoring();
|
|
for input in self.midi_ins_mut().iter() {
|
|
for (sample, event, bytes) in parse_midi_input(input.port().iter(scope)) {
|
|
if let LiveEvent::Midi { message, .. } = event {
|
|
if monitoring {
|
|
midi_buf[sample].push(bytes.to_vec());
|
|
}
|
|
// FIXME: don't lock on every event!
|
|
update_keys(&mut notes_in.write().unwrap(), &message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn record (&mut self, scope: &ProcessScope, midi_buf: &mut Vec<Vec<Vec<u8>>>) {
|
|
if self.monitoring() {
|
|
self.monitor(scope, midi_buf);
|
|
}
|
|
if !self.clock().is_rolling() {
|
|
return
|
|
}
|
|
if let Some((started, ref clip)) = self.play_clip().clone() {
|
|
self.record_clip(scope, started, clip, midi_buf);
|
|
}
|
|
if let Some((_start_at, _clip)) = &self.next_clip() {
|
|
self.record_next();
|
|
}
|
|
}
|
|
|
|
fn record_clip (
|
|
&mut self,
|
|
scope: &ProcessScope,
|
|
started: Moment,
|
|
clip: &Option<Arc<RwLock<MidiClip>>>,
|
|
_midi_buf: &mut Vec<Vec<Vec<u8>>>
|
|
) {
|
|
if let Some(clip) = clip {
|
|
let sample0 = scope.last_frame_time() as usize;
|
|
let start = started.sample.get() as usize;
|
|
let _recording = self.recording();
|
|
let timebase = self.clock().timebase().clone();
|
|
let quant = self.clock().quant.get();
|
|
let mut clip = clip.write().unwrap();
|
|
let length = clip.length;
|
|
for input in self.midi_ins_mut().iter() {
|
|
for (sample, event, _bytes) in parse_midi_input(input.port().iter(scope)) {
|
|
if let LiveEvent::Midi { message, .. } = event {
|
|
clip.record_event({
|
|
let sample = (sample0 + sample - start) as f64;
|
|
let pulse = timebase.samples_to_pulse(sample);
|
|
let quantized = (pulse / quant).round() * quant;
|
|
quantized as usize % length
|
|
}, message);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn record_next (&mut self) {
|
|
// TODO switch to next clip and record into it
|
|
}
|
|
|
|
}
|