From aa8eaf2e2b8ca0a07d54c3661b69aaa35d001627 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Wed, 23 Apr 2025 09:05:34 +0300 Subject: [PATCH] always redraw grid on note length change --- crates/app/src/view/view_track.rs | 13 ++++--------- crates/midi/src/midi_edit.rs | 4 ++-- crates/midi/src/midi_pitch.rs | 20 ++++++++++---------- crates/midi/src/midi_player.rs | 16 ++++++++++++++++ crates/midi/src/midi_point.rs | 2 +- 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/crates/app/src/view/view_track.rs b/crates/app/src/view/view_track.rs index c660799c..f298a726 100644 --- a/crates/app/src/view/view_track.rs +++ b/crates/app/src/view/view_track.rs @@ -30,21 +30,16 @@ impl<'a> ArrangerView<'a> { Tryptich::center(*scenes_height) .left(*width_side, Map::new(||self.scenes_with_scene_colors(), move|(index, scene, y1, y2, previous): SceneWithColor, _|{ - let name = Some(scene.name.clone()); - let color = scene.color; - let prev_color = previous; - let is_last = *scene_last == index; - let selected = *scene_selected; let same_track = true; - let scene = index; let height = (1 + y2 - y1) as u16; + let name = Some(scene.name.clone()); Fill::x(map_south(y1 as u16, (1 + y2 - y1) as u16, Fixed::y(height, Phat { width: 0, height: 0, content: Fill::x(Align::w(Tui::bold(true, Bsp::e(" ⯈ ", name)))), colors: Tek::colors( - &color, - prev_color, + &scene.color, + previous, same_track && *scene_selected == Some(index), same_track && index > 0 && *scene_selected == Some(index - 1), *scene_last == index @@ -68,7 +63,7 @@ impl<'a> ArrangerView<'a> { content: Fill::x(Align::w(Tui::bold(true, Bsp::e(" ⏹ ", name)))), colors: Tek::colors( &bg, - None, + Some(bg), same_track && *scene_selected == Some(scene_index), same_track && scene_index > 0 && *scene_selected == Some(scene_index - 1), *scene_last == scene_index diff --git a/crates/midi/src/midi_edit.rs b/crates/midi/src/midi_edit.rs index 4c43333d..ea97b9ef 100644 --- a/crates/midi/src/midi_edit.rs +++ b/crates/midi/src/midi_edit.rs @@ -232,9 +232,9 @@ impl Command for MidiEditCommand { let note_len = state.note_len(); let time_zoom = state.time_zoom().get(); state.set_note_len(x); - if note_len / time_zoom != x / time_zoom { + //if note_len / time_zoom != x / time_zoom { state.redraw(); - } + //} }, SetTimeCursor(x) => { state.set_time_pos(x); }, SetNoteCursor(note) => { state.set_note_pos(note.min(127)); }, diff --git a/crates/midi/src/midi_pitch.rs b/crates/midi/src/midi_pitch.rs index 00269cf6..06e455ce 100644 --- a/crates/midi/src/midi_pitch.rs +++ b/crates/midi/src/midi_pitch.rs @@ -2,16 +2,16 @@ 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", + "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 { diff --git a/crates/midi/src/midi_player.rs b/crates/midi/src/midi_player.rs index 34660ef9..b7df1fe9 100644 --- a/crates/midi/src/midi_player.rs +++ b/crates/midi/src/midi_player.rs @@ -1,9 +1,11 @@ //! 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),*>)? { @@ -12,8 +14,11 @@ pub trait HasPlayer { } } } + 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 @@ -41,6 +46,7 @@ pub struct MidiPlayer { /// MIDI output buffer pub note_buf: Vec, } + impl Default for MidiPlayer { fn default () -> Self { Self { @@ -61,6 +67,7 @@ impl Default for MidiPlayer { } } } + impl MidiPlayer { pub fn new ( name: impl AsRef, @@ -88,6 +95,7 @@ impl MidiPlayer { }) } } + impl std::fmt::Debug for MidiPlayer { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("MidiPlayer") @@ -97,16 +105,20 @@ impl std::fmt::Debug for MidiPlayer { .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 @@ -116,6 +128,7 @@ pub struct PlayerAudio<'a, T: MidiPlayerApi>( /// 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 { @@ -142,6 +155,7 @@ impl Audio for PlayerAudio<'_, T> { Control::Continue } } + impl MidiRecordApi for MidiPlayer { fn recording (&self) -> bool { self.recording @@ -165,11 +179,13 @@ impl MidiRecordApi for MidiPlayer { &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 diff --git a/crates/midi/src/midi_point.rs b/crates/midi/src/midi_point.rs index a7b05332..e1b47e10 100644 --- a/crates/midi/src/midi_point.rs +++ b/crates/midi/src/midi_point.rs @@ -15,7 +15,7 @@ impl Default for MidiPointModel { Self { time_pos: Arc::new(0.into()), note_pos: Arc::new(36.into()), - note_len: Arc::new(24.into()), + note_len: Arc::new(24.into()), } } }