use crate::*; /// Trait for thing that may receive MIDI. pub trait HasMidiIns { fn midi_ins (&self) -> &Vec; fn midi_ins_mut (&mut self) -> &mut Vec; fn has_midi_ins (&self) -> bool { !self.midi_ins().is_empty() } } pub trait MidiRecordApi: HasClock + HasPlayClip + HasMidiIns { fn notes_in (&self) -> &Arc>; 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>>) { // 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>>) { 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>>, _midi_buf: &mut Vec>> ) { 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 } }