//! MIDI player use crate::*; pub trait HasPlayer { fn player (&self) -> &impl MidiPlayerApi; fn player_mut (&mut self) -> &mut impl MidiPlayerApi; } #[macro_export] macro_rules! has_player { (|$self:ident:$Struct:ident$(<$($L:lifetime),*$($T:ident$(:$U:path)?),*>)?|$cb:expr) => { impl $(<$($L),*$($T $(: $U)?),*>)? HasPlayer for $Struct $(<$($L),*$($T),*>)? { fn player (&$self) -> &impl MidiPlayerApi { &$cb } fn player_mut (&mut $self) -> &mut impl MidiPlayerApi { &mut$cb } } } } pub trait MidiPlayerApi: MidiRecordApi + MidiPlaybackApi + Send + Sync {} impl MidiPlayerApi for MidiPlayer {} /// Contains state for playing a clip pub struct MidiPlayer { /// State of clock and playhead pub clock: Clock, /// Start time and clip being played pub play_clip: Option<(Moment, Option>>)>, /// Start time and next clip pub next_clip: Option<(Moment, Option>>)>, /// Play input through output. pub monitoring: bool, /// Write input to sequence. pub recording: bool, /// Overdub input to sequence. pub overdub: bool, /// Send all notes off pub reset: bool, // TODO?: after Some(nframes) /// Record from MIDI ports to current sequence. pub midi_ins: Vec, /// Play from current sequence to MIDI ports pub midi_outs: Vec, /// Notes currently held at input pub notes_in: Arc>, /// Notes currently held at output pub notes_out: Arc>, /// MIDI output buffer pub note_buf: Vec, } impl Default for MidiPlayer { fn default () -> Self { Self { play_clip: None, next_clip: None, recording: false, monitoring: false, overdub: false, notes_in: RwLock::new([false;128]).into(), notes_out: RwLock::new([false;128]).into(), note_buf: vec![0;8], reset: true, midi_ins: vec![], midi_outs: vec![], clock: Clock::default(), } } } impl MidiPlayer { pub fn new ( name: impl AsRef, jack: &Jack, clock: Option<&Clock>, clip: Option<&Arc>>, _midi_from: &[PortConnect], _midi_to: &[PortConnect], ) -> Usually { let name = name.as_ref(); let clock = clock.cloned().unwrap_or_default(); Ok(Self { midi_ins: vec![],//JackMidiIn::new(jack, format!("M/{name}"), midi_from)?,], midi_outs: vec![],//JackMidiOut::new(jack, format!("{name}/M"), midi_to)?, ], play_clip: clip.map(|clip|(Moment::zero(&clock.timebase), Some(clip.clone()))), clock, note_buf: vec![0;8], reset: true, recording: false, monitoring: false, overdub: false, next_clip: None, notes_in: RwLock::new([false;128]).into(), notes_out: RwLock::new([false;128]).into(), }) } } impl std::fmt::Debug for MidiPlayer { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("MidiPlayer") .field("clock", &self.clock) .field("play_clip", &self.play_clip) .field("next_clip", &self.next_clip) .finish() } } has_clock!(|self: MidiPlayer|self.clock); impl HasMidiIns for MidiPlayer { fn midi_ins (&self) -> &Vec { &self.midi_ins } fn midi_ins_mut (&mut self) -> &mut Vec { &mut self.midi_ins } } impl HasMidiOuts for MidiPlayer { fn midi_outs (&self) -> &Vec { &self.midi_outs } fn midi_outs_mut (&mut self) -> &mut Vec { &mut self.midi_outs } fn midi_note (&mut self) -> &mut Vec { &mut self.note_buf } } /// Hosts the JACK callback for a single MIDI player pub struct PlayerAudio<'a, T: MidiPlayerApi>( /// Player pub &'a mut T, /// Note buffer pub &'a mut Vec, /// Note chunk buffer pub &'a mut Vec>>, ); /// JACK process callback for a sequencer's clip player/recorder. impl Audio for PlayerAudio<'_, T> { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { let model = &mut self.0; let note_buf = &mut self.1; let midi_buf = &mut self.2; // Clear output buffer(s) model.clear(scope, midi_buf, false); // Write chunk of clip to output, handle switchover 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, midi_buf) } else if model.has_midi_outs() && model.monitoring() { // Monitor input to output model.monitor(scope, midi_buf) } } // Write to output port(s) model.write(scope, midi_buf); Control::Continue } } impl MidiRecordApi for MidiPlayer { fn recording (&self) -> bool { self.recording } fn recording_mut (&mut self) -> &mut bool { &mut self.recording } fn monitoring (&self) -> bool { self.monitoring } fn monitoring_mut (&mut self) -> &mut bool { &mut self.monitoring } fn overdub (&self) -> bool { self.overdub } fn overdub_mut (&mut self) -> &mut bool { &mut self.overdub } fn notes_in (&self) -> &Arc> { &self.notes_in } } impl MidiPlaybackApi for MidiPlayer { fn notes_out (&self) -> &Arc> { &self.notes_out } } impl HasPlayClip for MidiPlayer { fn reset (&self) -> bool { self.reset } fn reset_mut (&mut self) -> &mut bool { &mut self.reset } fn play_clip (&self) -> &Option<(Moment, Option>>)> { &self.play_clip } fn play_clip_mut (&mut self) -> &mut Option<(Moment, Option>>)> { &mut self.play_clip } fn next_clip (&self) -> &Option<(Moment, Option>>)> { &self.next_clip } fn next_clip_mut (&mut self) -> &mut Option<(Moment, Option>>)> { &mut self.next_clip } }