diff --git a/midi/src/lib.rs b/midi/src/lib.rs index 106b7a21..56c1804f 100644 --- a/midi/src/lib.rs +++ b/midi/src/lib.rs @@ -12,11 +12,9 @@ mod midi_view; pub use midi_view::*; mod midi_editor; pub use midi_editor::*; mod midi_select; pub use midi_select::*; -mod piano_h; pub use self::piano_h::*; -mod piano_h_cursor; pub use self::piano_h_cursor::*; -mod piano_h_keys; pub use self::piano_h_keys::*; -mod piano_h_notes; pub use self::piano_h_notes::*; -mod piano_h_time; pub use self::piano_h_time::*; +mod piano_h; pub use self::piano_h::*; +mod piano_h_keys; pub use self::piano_h_keys::*; +mod piano_h_time; pub use self::piano_h_time::*; pub(crate) use ::tek_time::*; pub(crate) use ::tek_jack::{*, jack::*}; diff --git a/midi/src/piano_h.rs b/midi/src/piano_h.rs index f3786b5b..dbe0f36f 100644 --- a/midi/src/piano_h.rs +++ b/midi/src/piano_h.rs @@ -10,10 +10,7 @@ render!(TuiOut: (self: PianoHorizontal) => Bsp::s( // the freeze is in the piano )), Fill::xy(Bsp::e( Fixed::x(self.keys_width, PianoHorizontalKeys(self)), - Fill::xy(self.size.of(lay!( - Fill::xy(PianoHorizontalNotes(self)), - Fill::xy(PianoHorizontalCursor(self)), - ))), + Fill::xy(self.size.of(lay!(self.notes(), self.cursor()))), )), )); impl PianoHorizontal { @@ -76,6 +73,70 @@ impl PianoHorizontal { } } + fn notes (&self) -> impl Content { + let time_start = self.time_start().get(); + let note_axis = self.note_axis().get(); + let note_lo = self.note_lo().get(); + let note_hi = self.note_hi(); + let note_point = self.note_point(); + let buffer = self.buffer.clone(); + RenderThunk::new(move|render: &mut TuiOut|{ + let source = buffer.read().unwrap(); + let [x0, y0, w, h] = render.area().xywh(); + if h as usize != note_axis { + panic!("area height mismatch: {h} <> {note_axis}"); + } + for (area_x, screen_x) in (x0..x0+w).enumerate() { + for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { + let source_x = time_start + area_x; + let source_y = note_hi - area_y; + // TODO: enable loop rollover: + //let source_x = (time_start + area_x) % source.width.max(1); + //let source_y = (note_hi - area_y) % source.height.max(1); + let is_in_x = source_x < source.width; + let is_in_y = source_y < source.height; + if is_in_x && is_in_y { + if let Some(source_cell) = source.get(source_x, source_y) { + if let Some(cell) = render.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { + *cell = source_cell.clone(); + } + } + } + } + } + }) + } + fn cursor (&self) -> impl Content { + let style = Some(Style::default().fg(self.color.lightest.rgb)); + let note_hi = self.note_hi(); + let note_len = self.note_len(); + let note_lo = self.note_lo().get(); + let note_point = self.note_point(); + let time_point = self.time_point(); + let time_start = self.time_start().get(); + let time_zoom = self.time_zoom().get(); + RenderThunk::new(move|render: &mut TuiOut|{ + let [x0, y0, w, _] = render.area().xywh(); + for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { + if note == note_point { + for x in 0..w { + let screen_x = x0 + x; + let time_1 = time_start + x as usize * time_zoom; + let time_2 = time_1 + time_zoom; + if time_1 <= time_point && time_point < time_2 { + render.blit(&"█", screen_x, screen_y, style); + let tail = note_len as u16 / time_zoom as u16; + for x_tail in (screen_x + 1)..(screen_x + tail) { + render.blit(&"▂", x_tail, screen_y, style); + } + break + } + } + break + } + } + }) + } } has_size!(|self:PianoHorizontal|&self.size); diff --git a/midi/src/piano_h_cursor.rs b/midi/src/piano_h_cursor.rs deleted file mode 100644 index 79b7217b..00000000 --- a/midi/src/piano_h_cursor.rs +++ /dev/null @@ -1,33 +0,0 @@ -use crate::*; -use super::*; - -pub struct PianoHorizontalCursor<'a>(pub(crate) &'a PianoHorizontal); -render!(TuiOut: |self: PianoHorizontalCursor<'a>, render|{ - let style = Some(Style::default().fg(self.0.color.lightest.rgb)); - let note_hi = self.0.note_hi(); - let note_len = self.0.note_len(); - let note_lo = self.0.note_lo().get(); - let note_point = self.0.note_point(); - let time_point = self.0.time_point(); - let time_start = self.0.time_start().get(); - let time_zoom = self.0.time_zoom().get(); - let [x0, y0, w, _] = render.area().xywh(); - for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { - if note == note_point { - for x in 0..w { - let screen_x = x0 + x; - let time_1 = time_start + x as usize * time_zoom; - let time_2 = time_1 + time_zoom; - if time_1 <= time_point && time_point < time_2 { - render.blit(&"█", screen_x, screen_y, style); - let tail = note_len as u16 / time_zoom as u16; - for x_tail in (screen_x + 1)..(screen_x + tail) { - render.blit(&"▂", x_tail, screen_y, style); - } - break - } - } - break - } - } -}); diff --git a/midi/src/piano_h_notes.rs b/midi/src/piano_h_notes.rs deleted file mode 100644 index 247fd3fe..00000000 --- a/midi/src/piano_h_notes.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::*; -use super::*; - -pub struct PianoHorizontalNotes<'a>(pub(crate) &'a PianoHorizontal); - -render!(TuiOut: |self: PianoHorizontalNotes<'a>, render|{ - let time_start = self.0.time_start().get(); - let note_axis = self.0.note_axis().get(); - let note_lo = self.0.note_lo().get(); - let note_hi = self.0.note_hi(); - let note_point = self.0.note_point(); - let source = self.0.buffer.read().unwrap(); - let [x0, y0, w, h] = render.area().xywh(); - if h as usize != note_axis { - panic!("area height mismatch: {h} <> {note_axis}"); - } - for (area_x, screen_x) in (x0..x0+w).enumerate() { - for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { - let source_x = time_start + area_x; - let source_y = note_hi - area_y; - // TODO: enable loop rollover: - //let source_x = (time_start + area_x) % source.width.max(1); - //let source_y = (note_hi - area_y) % source.height.max(1); - let is_in_x = source_x < source.width; - let is_in_y = source_y < source.height; - if is_in_x && is_in_y { - if let Some(source_cell) = source.get(source_x, source_y) { - if let Some(cell) = render.buffer.cell_mut(ratatui::prelude::Position::from((screen_x, screen_y))) { - *cell = source_cell.clone(); - } - } - } - } - } -});