diff --git a/layout/src/ops.rs b/layout/src/ops.rs index 698e1011..117a77fc 100644 --- a/layout/src/ops.rs +++ b/layout/src/ops.rs @@ -1,23 +1,25 @@ use crate::*; -use std::sync::RwLock; - impl Layout for E {} pub trait Layout { /// Content `item` when `cond` is true. - fn when > (cond: bool, item: A) -> When { + fn when (cond: bool, item: A) -> When where + A: Content + { When(cond, item, Default::default()) } /// Content `item` if `cond` is true, otherwise render `other`. - fn either , B: Content> (cond: bool, a: A, b: B) - -> Either + fn either (cond: bool, a: A, b: B) -> Either where + A: Content, + B: Content, { Either(cond, a, b, Default::default()) } /// Maps an [Option] through a callback `F` - fn opt R, R: Content> (option: Option, cb: F) - -> Opt + fn opt (option: Option, cb: F) -> Opt where + F: Fn(A) -> R, + R: Content { Opt(option, cb, Default::default()) } diff --git a/src/midi.rs b/src/midi.rs index 3ec99d15..7eed3c1a 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -3,8 +3,9 @@ use crate::*; pub(crate) mod midi_pool; pub(crate) use midi_pool::*; pub(crate) mod midi_clip; pub(crate) use midi_clip::*; pub(crate) mod midi_launch; pub(crate) use midi_launch::*; -pub(crate) mod midi_play; pub(crate) use midi_play::*; -pub(crate) mod midi_rec; pub(crate) use midi_rec::*; +pub(crate) mod midi_player; pub(crate) use midi_player::*; +pub(crate) mod midi_in; pub(crate) use midi_in::*; +pub(crate) mod midi_out; pub(crate) use midi_out::*; pub(crate) mod midi_note; pub(crate) use midi_note::*; pub(crate) mod midi_range; pub(crate) use midi_range::*; @@ -13,26 +14,6 @@ pub(crate) mod midi_view; pub(crate) use midi_view::*; pub(crate) mod midi_editor; pub(crate) use midi_editor::*; -/// 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() - } -} - -/// Trait for thing that may output MIDI. -pub trait HasMidiOuts { - fn midi_outs (&self) -> &Vec>; - fn midi_outs_mut (&mut self) -> &mut Vec>; - fn has_midi_outs (&self) -> bool { - !self.midi_outs().is_empty() - } - /// Buffer for serializing a MIDI event. FIXME rename - fn midi_note (&mut self) -> &mut Vec; -} - /// Add "all notes off" to the start of a buffer. pub fn all_notes_off (output: &mut [Vec>]) { let mut buf = vec![]; @@ -59,300 +40,3 @@ pub fn update_keys (keys: &mut[bool;128], message: &MidiMessage) { _ => {} } } - -pub fn to_note_name (n: usize) -> &'static str { - if n > 127 { - panic!("to_note_name({n}): must be 0-127"); - } - MIDI_NOTE_NAMES[n] -} - -pub const MIDI_NOTE_NAMES: [&str; 128] = [ - "C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0", - "C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1", - "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2", - "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", - "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", - "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5", - "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6", - "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7", - "C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "B8", - "C9", "C#9", "D9", "D#9", "E9", "F9", "F#9", "G9", "G#9", "A9", "A#9", "B9", - "C10", "C#10", "D10", "D#10", "E10", "F10", "F#10", "G10", -]; - -pub trait MidiPlayerApi: MidiRecordApi + MidiPlaybackApi + Send + Sync {} - -impl MidiPlayerApi for MidiPlayer {} - -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 } - } - } -} - -/// Contains state for playing a phrase -pub struct MidiPlayer { - /// State of clock and playhead - pub(crate) clock: Clock, - /// Start time and phrase being played - pub(crate) play_phrase: Option<(Moment, Option>>)>, - /// Start time and next phrase - pub(crate) next_phrase: Option<(Moment, Option>>)>, - /// Play input through output. - pub(crate) monitoring: bool, - /// Write input to sequence. - pub(crate) recording: bool, - /// Overdub input to sequence. - pub(crate) overdub: bool, - /// Send all notes off - pub(crate) 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(crate) notes_in: Arc>, - /// Notes currently held at output - pub(crate) notes_out: Arc>, - /// MIDI output buffer - pub note_buf: Vec, -} -impl MidiPlayer { - pub fn new ( - jack: &Arc>, - name: impl AsRef, - midi_from: &[impl AsRef], - midi_to: &[impl AsRef], - ) -> Usually { - let name = name.as_ref(); - Ok(Self { - clock: Clock::from(jack), - play_phrase: None, - next_phrase: None, - recording: false, - monitoring: false, - overdub: false, - - notes_in: RwLock::new([false;128]).into(), - midi_ins: vec![ - jack.midi_in(&format!("M/{name}"), midi_from)?, - ], - - midi_outs: vec![ - jack.midi_out(&format!("{name}/M"), midi_to)?, - ], - notes_out: RwLock::new([false;128]).into(), - reset: true, - - note_buf: vec![0;8], - }) - } -} -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_phrase", &self.play_phrase) - .field("next_phrase", &self.next_phrase) - .finish() - } -} -from!(|clock: &Clock| MidiPlayer = Self { - clock: clock.clone(), - midi_ins: vec![], - midi_outs: vec![], - note_buf: vec![0;8], - reset: true, - recording: false, - monitoring: false, - overdub: false, - play_phrase: None, - next_phrase: None, - notes_in: RwLock::new([false;128]).into(), - notes_out: RwLock::new([false;128]).into(), -}); -from!(|state: (&Clock, &Arc>)|MidiPlayer = { - let (clock, phrase) = state; - let mut model = Self::from(clock); - model.play_phrase = Some((Moment::zero(&clock.timebase), Some(phrase.clone()))); - model -}); -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 phrase 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 phrase 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 HasPlayPhrase for MidiPlayer { - fn reset (&self) -> bool { - self.reset - } - fn reset_mut (&mut self) -> &mut bool { - &mut self.reset - } - fn play_phrase (&self) -> &Option<(Moment, Option>>)> { - &self.play_phrase - } - fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { - &mut self.play_phrase - } - fn next_phrase (&self) -> &Option<(Moment, Option>>)> { - &self.next_phrase - } - fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { - &mut self.next_phrase - } -} - -//#[derive(Debug)] -//pub struct MIDIPlayer { - ///// Global timebase - //pub clock: Arc, - ///// Start time and phrase being played - //pub play_phrase: Option<(Moment, Option>>)>, - ///// Start time and next phrase - //pub next_phrase: 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_inputs: Vec>, - ///// Play from current sequence to MIDI ports - //pub midi_outputs: Vec>, - ///// MIDI output buffer - //pub midi_note: Vec, - ///// MIDI output buffer - //pub midi_chunk: Vec>>, - ///// Notes currently held at input - //pub notes_in: Arc>, - ///// Notes currently held at output - //pub notes_out: Arc>, -//} - -///// Methods used primarily by the process callback -//impl MIDIPlayer { - //pub fn new ( - //jack: &Arc>, - //clock: &Arc, - //name: &str - //) -> Usually { - //let jack = jack.read().unwrap(); - //Ok(Self { - //clock: clock.clone(), - //phrase: None, - //next_phrase: None, - //notes_in: Arc::new(RwLock::new([false;128])), - //notes_out: Arc::new(RwLock::new([false;128])), - //monitoring: false, - //recording: false, - //overdub: true, - //reset: true, - //midi_note: Vec::with_capacity(8), - //midi_chunk: vec![Vec::with_capacity(16);16384], - //midi_outputs: vec![ - //jack.client().register_port(format!("{name}_out0").as_str(), MidiOut::default())? - //], - //midi_inputs: vec![ - //jack.client().register_port(format!("{name}_in0").as_str(), MidiIn::default())? - //], - //}) - //} -//} diff --git a/src/midi/midi_rec.rs b/src/midi/midi_in.rs similarity index 92% rename from src/midi/midi_rec.rs rename to src/midi/midi_in.rs index 6d65e427..4cf8d1f4 100644 --- a/src/midi/midi_rec.rs +++ b/src/midi/midi_in.rs @@ -1,5 +1,14 @@ 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 + HasPlayPhrase + HasMidiIns { fn notes_in (&self) -> &Arc>; diff --git a/src/midi/midi_note.rs b/src/midi/midi_note.rs index ca08b5ea..b6b370cf 100644 --- a/src/midi/midi_note.rs +++ b/src/midi/midi_note.rs @@ -3,6 +3,26 @@ use crate::*; pub struct Note; impl Note { + pub const NAMES: [&str; 128] = [ + "C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0", + "C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1", + "C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2", + "C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3", + "C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4", + "C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5", + "C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6", + "C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7", + "C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "B8", + "C9", "C#9", "D9", "D#9", "E9", "F9", "F#9", "G9", "G#9", "A9", "A#9", "B9", + "C10", "C#10", "D10", "D#10", "E10", "F10", "F#10", "G10", + ]; + pub fn pitch_to_name (n: usize) -> &'static str { + if n > 127 { + panic!("to_note_name({n}): must be 0-127"); + } + Self::NAMES[n] + } + /// (pulses, name), assuming 96 PPQ pub const DURATIONS: [(usize, &str);26] = [ (1, "1/384"), (2, "1/192"), diff --git a/src/midi/midi_play.rs b/src/midi/midi_out.rs similarity index 94% rename from src/midi/midi_play.rs rename to src/midi/midi_out.rs index dde2c05f..0f9f3118 100644 --- a/src/midi/midi_play.rs +++ b/src/midi/midi_out.rs @@ -1,5 +1,16 @@ use crate::*; +/// Trait for thing that may output MIDI. +pub trait HasMidiOuts { + fn midi_outs (&self) -> &Vec>; + fn midi_outs_mut (&mut self) -> &mut Vec>; + fn has_midi_outs (&self) -> bool { + !self.midi_outs().is_empty() + } + /// Buffer for serializing a MIDI event. FIXME rename + fn midi_note (&mut self) -> &mut Vec; +} + pub trait MidiPlaybackApi: HasPlayPhrase + HasClock + HasMidiOuts { fn notes_out (&self) -> &Arc>; diff --git a/src/midi/midi_player.rs b/src/midi/midi_player.rs new file mode 100644 index 00000000..e1ba9159 --- /dev/null +++ b/src/midi/midi_player.rs @@ -0,0 +1,277 @@ +use crate::*; + +pub trait MidiPlayerApi: MidiRecordApi + MidiPlaybackApi + Send + Sync {} + +impl MidiPlayerApi for MidiPlayer {} + +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 } + } + } +} + +/// Contains state for playing a phrase +pub struct MidiPlayer { + /// State of clock and playhead + pub(crate) clock: Clock, + /// Start time and phrase being played + pub(crate) play_phrase: Option<(Moment, Option>>)>, + /// Start time and next phrase + pub(crate) next_phrase: Option<(Moment, Option>>)>, + /// Play input through output. + pub(crate) monitoring: bool, + /// Write input to sequence. + pub(crate) recording: bool, + /// Overdub input to sequence. + pub(crate) overdub: bool, + /// Send all notes off + pub(crate) 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(crate) notes_in: Arc>, + /// Notes currently held at output + pub(crate) notes_out: Arc>, + /// MIDI output buffer + pub note_buf: Vec, +} +impl MidiPlayer { + pub fn new ( + jack: &Arc>, + name: impl AsRef, + midi_from: &[impl AsRef], + midi_to: &[impl AsRef], + ) -> Usually { + let name = name.as_ref(); + Ok(Self { + clock: Clock::from(jack), + play_phrase: None, + next_phrase: None, + recording: false, + monitoring: false, + overdub: false, + + notes_in: RwLock::new([false;128]).into(), + midi_ins: vec![ + jack.midi_in(&format!("M/{name}"), midi_from)?, + ], + + midi_outs: vec![ + jack.midi_out(&format!("{name}/M"), midi_to)?, + ], + notes_out: RwLock::new([false;128]).into(), + reset: true, + + note_buf: vec![0;8], + }) + } +} +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_phrase", &self.play_phrase) + .field("next_phrase", &self.next_phrase) + .finish() + } +} +from!(|clock: &Clock| MidiPlayer = Self { + clock: clock.clone(), + midi_ins: vec![], + midi_outs: vec![], + note_buf: vec![0;8], + reset: true, + recording: false, + monitoring: false, + overdub: false, + play_phrase: None, + next_phrase: None, + notes_in: RwLock::new([false;128]).into(), + notes_out: RwLock::new([false;128]).into(), +}); +from!(|state: (&Clock, &Arc>)|MidiPlayer = { + let (clock, phrase) = state; + let mut model = Self::from(clock); + model.play_phrase = Some((Moment::zero(&clock.timebase), Some(phrase.clone()))); + model +}); +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 phrase 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 phrase 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 HasPlayPhrase for MidiPlayer { + fn reset (&self) -> bool { + self.reset + } + fn reset_mut (&mut self) -> &mut bool { + &mut self.reset + } + fn play_phrase (&self) -> &Option<(Moment, Option>>)> { + &self.play_phrase + } + fn play_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { + &mut self.play_phrase + } + fn next_phrase (&self) -> &Option<(Moment, Option>>)> { + &self.next_phrase + } + fn next_phrase_mut (&mut self) -> &mut Option<(Moment, Option>>)> { + &mut self.next_phrase + } +} + +//#[derive(Debug)] +//pub struct MIDIPlayer { + ///// Global timebase + //pub clock: Arc, + ///// Start time and phrase being played + //pub play_phrase: Option<(Moment, Option>>)>, + ///// Start time and next phrase + //pub next_phrase: 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_inputs: Vec>, + ///// Play from current sequence to MIDI ports + //pub midi_outputs: Vec>, + ///// MIDI output buffer + //pub midi_note: Vec, + ///// MIDI output buffer + //pub midi_chunk: Vec>>, + ///// Notes currently held at input + //pub notes_in: Arc>, + ///// Notes currently held at output + //pub notes_out: Arc>, +//} + +///// Methods used primarily by the process callback +//impl MIDIPlayer { + //pub fn new ( + //jack: &Arc>, + //clock: &Arc, + //name: &str + //) -> Usually { + //let jack = jack.read().unwrap(); + //Ok(Self { + //clock: clock.clone(), + //phrase: None, + //next_phrase: None, + //notes_in: Arc::new(RwLock::new([false;128])), + //notes_out: Arc::new(RwLock::new([false;128])), + //monitoring: false, + //recording: false, + //overdub: true, + //reset: true, + //midi_note: Vec::with_capacity(8), + //midi_chunk: vec![Vec::with_capacity(16);16384], + //midi_outputs: vec![ + //jack.client().register_port(format!("{name}_out0").as_str(), MidiOut::default())? + //], + //midi_inputs: vec![ + //jack.client().register_port(format!("{name}_in0").as_str(), MidiIn::default())? + //], + //}) + //} +//} diff --git a/src/piano/piano_h_keys.rs b/src/piano/piano_h_keys.rs index 35efaa77..96e73575 100644 --- a/src/piano/piano_h_keys.rs +++ b/src/piano/piano_h_keys.rs @@ -19,9 +19,9 @@ render!(Tui: |self: PianoHorizontalKeys<'a>, to|{ continue } if note == note_point { - to.blit(&format!("{:<5}", to_note_name(note)), x, screen_y, on_style) + to.blit(&format!("{:<5}", Note::pitch_to_name(note)), x, screen_y, on_style) } else { - to.blit(&to_note_name(note), x, screen_y, off_style) + to.blit(&Note::pitch_to_name(note), x, screen_y, off_style) }; } }); diff --git a/src/status.rs b/src/status.rs index c8b995d5..c8b379ef 100644 --- a/src/status.rs +++ b/src/status.rs @@ -21,8 +21,8 @@ render!(Tui: (self:MidiEditStatus<'a>) => { if self.0.time_lock().get() { "[lock]" } else { " " })), " ", field(" Note", format!("{} ({}) {} | {}-{} ({})", - self.0.note_point(), to_note_name(self.0.note_point()), self.0.note_len(), - to_note_name(self.0.note_lo().get()), to_note_name(self.0.note_hi()), + self.0.note_point(), Note::pitch_to_name(self.0.note_point()), self.0.note_len(), + Note::pitch_to_name(self.0.note_lo().get()), Note::pitch_to_name(self.0.note_hi()), self.0.note_axis().get())) )))) });