add getter/setters to note cursor traits

This commit is contained in:
🪞👃🪞 2025-05-08 03:19:47 +03:00
parent a6100ab1d6
commit a8be2e9dad
8 changed files with 214 additions and 188 deletions

View file

@ -53,12 +53,62 @@ impl Tek {
matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..))) matches!(self.pool.as_ref().map(|p|p.mode.as_ref()).flatten(), Some(PoolMode::Length(..)))
} }
fn editor_pitch (&self) -> Option<u7> { fn editor_pitch (&self) -> Option<u7> {
(self.editor().map(|e|e.note_pos()).unwrap() as u8).into() Some((self.editor().map(|e|e.note_pos()).unwrap() as u8).into())
} }
fn w_sidebar (&self) -> Option<u7> { /// Width of display
self.w_sidebar() pub(crate) fn w (&self) -> u16 {
self.size.w() as u16
} }
fn scene_count (&self) -> Option<usize> { /// Width allocated for sidebar.
pub(crate) fn w_sidebar (&self) -> u16 {
self.w() / if self.is_editing() { 16 } else { 8 } as u16
}
/// Width taken by all tracks.
pub(crate) fn w_tracks (&self) -> u16 {
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
}
/// Width available to display tracks.
pub(crate) fn w_tracks_area (&self) -> u16 {
self.w().saturating_sub(2 * self.w_sidebar())
}
/// Height of display
pub(crate) fn h (&self) -> u16 {
self.size.h() as u16
}
/// Height available to display track headers.
pub(crate) fn h_tracks_area (&self) -> u16 {
5 // FIXME
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
}
/// Height available to display tracks.
pub(crate) fn h_scenes_area (&self) -> u16 {
//15
self.h().saturating_sub(
self.h_inputs() +
self.h_outputs() +
self.h_devices() +
13 // FIXME
)
}
/// Height taken by all scenes.
pub(crate) fn h_scenes (&self) -> u16 {
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by all inputs.
pub(crate) fn h_inputs (&self) -> u16 {
self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by all outputs.
pub(crate) fn h_outputs (&self) -> u16 {
self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by visible device slots.
pub(crate) fn h_devices (&self) -> u16 {
2
//1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
fn scene_count (&self) -> usize {
self.scenes.len() self.scenes.len()
} }
fn scene_selected (&self) -> Option<usize> { fn scene_selected (&self) -> Option<usize> {
@ -70,7 +120,7 @@ impl Tek {
fn scene_select_prev (&self) -> Selection { fn scene_select_prev (&self) -> Selection {
self.selected.scene_prev() self.selected.scene_prev()
} }
fn track_count (&self) -> Option<usize> { fn track_count (&self) -> usize {
self.tracks.len() self.tracks.len()
} }
fn track_selected (&self) -> Option<usize> { fn track_selected (&self) -> Option<usize> {
@ -139,64 +189,70 @@ impl MidiPool {
#[tengri_proc::expose] #[tengri_proc::expose]
impl MidiEditor { impl MidiEditor {
fn time_lock (&self) -> bool { fn time_lock (&self) -> bool {
self.time_lock().get() self.get_time_lock()
} }
fn time_lock_toggle (&self) -> bool { fn time_lock_toggled (&self) -> bool {
!self.time_lock().get() !self.get_time_lock()
} }
fn note_length (&self) -> usize { fn note_length (&self) -> usize {
self.note_len() self.get_note_len()
} }
fn note_pos (&self) -> usize { fn note_pos (&self) -> usize {
self.note_pos() self.get_note_pos()
} }
fn note_pos_next (&self) -> usize { fn note_pos_next (&self) -> usize {
self.note_pos() + 1 self.get_note_pos() + 1
} }
fn note_pos_next_octave (&self) -> usize { fn note_pos_next_octave (&self) -> usize {
self.note_pos() + 12 self.get_note_pos() + 12
} }
fn note_pos_prev (&self) -> usize { fn note_pos_prev (&self) -> usize {
self.note_pos().saturating_sub(1) self.get_note_pos().saturating_sub(1)
} }
fn note_pos_prev_octave (&self) -> usize { fn note_pos_prev_octave (&self) -> usize {
self.note_pos().saturating_sub(12) self.get_note_pos().saturating_sub(12)
} }
fn note_len (&self) -> usize { fn note_len (&self) -> usize {
self.note_len() self.get_note_len()
} }
fn note_len_next (&self) -> usize { fn note_len_next (&self) -> usize {
self.note_len() + 1 self.get_note_len() + 1
} }
fn note_len_prev (&self) -> usize { fn note_len_prev (&self) -> usize {
self.note_len().saturating_sub(1) self.get_note_len().saturating_sub(1)
} }
fn note_range (&self) -> usize { fn note_range (&self) -> usize {
self.note_axis() self.get_note_axis()
} }
fn note_range_next (&self) -> usize { fn note_range_next (&self) -> usize {
self.note_axis() + 1 self.get_note_axis() + 1
} }
fn note_range_prev (&self) -> usize { fn note_range_prev (&self) -> usize {
self.note_axis().saturating_sub(1) self.get_note_axis().saturating_sub(1)
} }
fn time_pos (&self) -> usize { fn time_pos (&self) -> usize {
self.time_pos() self.get_time_pos()
} }
fn time_pos_next (&self) -> usize { fn time_pos_next (&self) -> usize {
self.time_pos() + self.time_zoom().get() self.get_time_pos() + self.time_zoom()
} }
fn time_pos_prev (&self) -> usize { fn time_pos_prev (&self) -> usize {
self.time_pos().saturating_sub(self.time_zoom().get()) self.get_time_pos().saturating_sub(self.time_zoom())
} }
fn time_zoom (&self) -> usize { fn time_zoom (&self) -> usize {
self.time_zoom() self.get_time_zoom()
} }
fn time_zoom_next (&self) -> usize { fn time_zoom_next (&self) -> usize {
self.time_zoom() + 1 self.get_time_zoom() + 1
} }
fn time_zoom_prev (&self) -> usize { fn time_zoom_prev (&self) -> usize {
self.time_zoom().get().saturating_sub(1).max(1) self.get_time_zoom().saturating_sub(1).max(1)
} }
} }
@ -277,17 +333,17 @@ impl TekCommand {
#[tengri_proc::command(Tek)] #[tengri_proc::command(Tek)]
impl InputCommand { impl InputCommand {
fn add (&self, state: &mut tek) -> option<self> { fn add (&self, state: &mut Tek) -> Option<Self> {
state.midi_in_add()?; state.midi_in_add()?;
none None
} }
} }
#[tengri_proc::command(Tek)] #[tengri_proc::command(Tek)]
impl OutputCommand { impl OutputCommand {
fn add (&self, state: &mut tek) -> option<self> { fn add (&self, state: &mut Tek) -> Option<Self> {
state.midi_out_add()?; state.midi_out_add()?;
none None
} }
} }

View file

@ -93,12 +93,13 @@ impl MidiEditor {
let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) { let (color, length) = if let Some(clip) = self.clip().as_ref().map(|p|p.read().unwrap()) {
(clip.color, clip.length) (clip.color, clip.length)
} else { (ItemTheme::G[64], 0) }; } else { (ItemTheme::G[64], 0) };
let time_pos = self.time_pos(); let time_pos = self.get_time_pos();
let time_zoom = self.time_zoom().get(); let time_zoom = self.get_time_zoom();
let time_lock = if self.time_lock().get() { "[lock]" } else { " " }; let time_lock = if self.get_time_lock() { "[lock]" } else { " " };
let note_pos = format!("{:>3}", self.note_pos()); let note_pos = self.get_note_pos();
let note_name = format!("{:4}", Note::pitch_to_name(self.note_pos())); let note_name = format!("{:4}", Note::pitch_to_name(note_pos));
let note_len = format!("{:>4}", self.note_len()); let note_pos = format!("{:>3}", note_pos);
let note_len = format!("{:>4}", self.get_note_len());
Bsp::e( Bsp::e(
FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")), FieldH(color, "Time", format!("{length}/{time_zoom}+{time_pos} {time_lock}")),
FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")), FieldH(color, "Note", format!("{note_name} {note_pos} {note_len}")),
@ -120,15 +121,12 @@ impl NoteRange for MidiEditor {
} }
impl NotePoint for MidiEditor { impl NotePoint for MidiEditor {
fn note_len (&self) -> usize { self.mode.note_len() } fn note_len (&self) -> &AtomicUsize { self.mode.note_len() }
fn set_note_len (&self, x: usize) -> usize { self.mode.set_note_len(x) } fn note_pos (&self) -> &AtomicUsize { self.mode.note_pos() }
fn note_pos (&self) -> usize { self.mode.note_pos() }
fn set_note_pos (&self, x: usize) -> usize { self.mode.set_note_pos(x) }
} }
impl TimePoint for MidiEditor { impl TimePoint for MidiEditor {
fn time_pos (&self) -> usize { self.mode.time_pos() } fn time_pos (&self) -> &AtomicUsize { self.mode.time_pos() }
fn set_time_pos (&self, x: usize) -> usize { self.mode.set_time_pos(x) }
} }
impl MidiViewer for MidiEditor { impl MidiViewer for MidiEditor {

View file

@ -39,7 +39,7 @@ impl Tek {
self.sampler().map(|s|s.view_grid()) self.sampler().map(|s|s.view_grid())
} }
fn view_sample_viewer (&self) -> impl Content<TuiOut> + use<'_> { fn view_sample_viewer (&self) -> impl Content<TuiOut> + use<'_> {
self.sampler().map(|s|s.view_sample(self.editor().unwrap().note_pos())) self.sampler().map(|s|s.view_sample(self.editor().unwrap().get_note_pos()))
} }
fn view_dialog (&self) -> impl Content<TuiOut> + use<'_> { fn view_dialog (&self) -> impl Content<TuiOut> + use<'_> {
When::new(self.dialog.is_some(), Bsp::b( When::new(self.dialog.is_some(), Bsp::b(
@ -115,69 +115,6 @@ impl Tek {
/// Default editor height. /// Default editor height.
pub(crate) const H_EDITOR: usize = 15; pub(crate) const H_EDITOR: usize = 15;
/// Width of display
pub(crate) fn w (&self) -> u16 {
self.size.w() as u16
}
pub(crate) fn w_sidebar (&self) -> u16 {
self.w() / if self.is_editing() { 16 } else { 8 } as u16
}
/// Width taken by all tracks.
pub(crate) fn w_tracks (&self) -> u16 {
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
}
/// Width available to display tracks.
pub(crate) fn w_tracks_area (&self) -> u16 {
self.w().saturating_sub(2 * self.w_sidebar())
}
/// Height of display
pub(crate) fn h (&self) -> u16 {
self.size.h() as u16
}
/// Height available to display track headers.
pub(crate) fn h_tracks_area (&self) -> u16 {
5 // FIXME
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
}
/// Height available to display tracks.
pub(crate) fn h_scenes_area (&self) -> u16 {
//15
self.h().saturating_sub(
self.h_inputs() +
self.h_outputs() +
self.h_devices() +
13 // FIXME
)
}
/// Height taken by all inputs.
pub(crate) fn h_inputs (&self) -> u16 {
self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by all outputs.
pub(crate) fn h_outputs (&self) -> u16 {
self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by visible device slots.
pub(crate) fn h_devices (&self) -> u16 {
2
//1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
}
/// Height taken by all scenes.
pub(crate) fn h_scenes (&self) -> u16 {
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
}
pub(crate) fn inputs_with_sizes (&self) -> impl PortsSizes<'_> { pub(crate) fn inputs_with_sizes (&self) -> impl PortsSizes<'_> {
let mut y = 0; let mut y = 0;
self.midi_ins.iter().enumerate().map(move|(i, input)|{ self.midi_ins.iter().enumerate().map(move|(i, input)|{
@ -1118,9 +1055,9 @@ impl PianoHorizontal {
} }
} }
fn notes (&self) -> impl Content<TuiOut> { fn notes (&self) -> impl Content<TuiOut> {
let time_start = self.time_start().get(); let time_start = self.get_time_start();
let note_lo = self.note_lo().get(); let note_lo = self.get_note_lo();
let note_hi = self.note_hi(); let note_hi = self.get_note_hi();
let buffer = self.buffer.clone(); let buffer = self.buffer.clone();
ThunkRender::new(move|to: &mut TuiOut|{ ThunkRender::new(move|to: &mut TuiOut|{
let source = buffer.read().unwrap(); let source = buffer.read().unwrap();
@ -1149,14 +1086,14 @@ impl PianoHorizontal {
}) })
} }
fn cursor (&self) -> impl Content<TuiOut> { fn cursor (&self) -> impl Content<TuiOut> {
let style = Some(Style::default().fg(self.color.lightest.rgb)); let note_hi = self.get_note_hi();
let note_hi = self.note_hi(); let note_lo = self.get_note_lo();
let note_lo = self.note_lo().get(); let note_pos = self.get_note_pos();
let note_pos = self.note_pos(); let note_len = self.get_note_len();
let note_len = self.note_len(); let time_pos = self.get_time_pos();
let time_pos = self.time_pos(); let time_start = self.get_time_start();
let time_start = self.time_start().get(); let time_zoom = self.get_time_zoom();
let time_zoom = self.time_zoom().get(); let style = Some(Style::default().fg(self.color.lightest.rgb));
ThunkRender::new(move|to: &mut TuiOut|{ ThunkRender::new(move|to: &mut TuiOut|{
let [x0, y0, w, _] = to.area().xywh(); let [x0, y0, w, _] = to.area().xywh();
for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
@ -1182,9 +1119,9 @@ impl PianoHorizontal {
fn keys (&self) -> impl Content<TuiOut> { fn keys (&self) -> impl Content<TuiOut> {
let state = self; let state = self;
let color = state.color; let color = state.color;
let note_lo = state.note_lo().get(); let note_lo = state.get_note_lo();
let note_hi = state.note_hi(); let note_hi = state.get_note_hi();
let note_pos = state.note_pos(); let note_pos = state.get_note_pos();
let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0))); let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0)));
let off_style = Some(Style::default().fg(Tui::g(255))); let off_style = Some(Style::default().fg(Tui::g(255)));
let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.rgb).bold()); let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.rgb).bold());
@ -1234,15 +1171,12 @@ impl NoteRange for PianoHorizontal {
} }
impl NotePoint for PianoHorizontal { impl NotePoint for PianoHorizontal {
fn note_len (&self) -> usize { self.point.note_len() } fn note_len (&self) -> &AtomicUsize { self.point.note_len() }
fn set_note_len (&self, x: usize) -> usize { self.point.set_note_len(x) } fn note_pos (&self) -> &AtomicUsize { self.point.note_pos() }
fn note_pos (&self) -> usize { self.point.note_pos() }
fn set_note_pos (&self, x: usize) -> usize { self.point.set_note_pos(x) }
} }
impl TimePoint for PianoHorizontal { impl TimePoint for PianoHorizontal {
fn time_pos (&self) -> usize { self.point.time_pos() } fn time_pos (&self) -> &AtomicUsize { self.point.time_pos() }
fn set_time_pos (&self, x: usize) -> usize { self.point.set_time_pos(x) }
} }
impl MidiViewer for PianoHorizontal { impl MidiViewer for PianoHorizontal {

View file

@ -93,13 +93,19 @@ impl NoteRange for Sampler {
} }
impl NotePoint for Sampler { impl NotePoint for Sampler {
fn note_len (&self) -> usize { fn note_len (&self) -> &AtomicUsize {
0 /*TODO?*/ unreachable!();
}
fn get_note_len (&self) -> usize {
0
} }
fn set_note_len (&self, x: usize) -> usize { fn set_note_len (&self, x: usize) -> usize {
0 /*TODO?*/ 0 /*TODO?*/
} }
fn note_pos (&self) -> usize { fn note_pos (&self) -> &AtomicUsize {
&self.note_pt
}
fn get_note_pos (&self) -> usize {
self.note_pt.load(Relaxed) self.note_pt.load(Relaxed)
} }
fn set_note_pos (&self, x: usize) -> usize { fn set_note_pos (&self, x: usize) -> usize {

View file

@ -56,9 +56,9 @@ impl Sampler {
pub fn view_list <'a, T: NotePoint + NoteRange> ( pub fn view_list <'a, T: NotePoint + NoteRange> (
&'a self, compact: bool, editor: &T &'a self, compact: bool, editor: &T
) -> impl Content<TuiOut> + 'a { ) -> impl Content<TuiOut> + 'a {
let note_lo = editor.note_lo().load(Relaxed); let note_lo = editor.get_note_lo();
let note_pt = editor.note_pos(); let note_pt = editor.get_note_pos();
let note_hi = editor.note_hi(); let note_hi = editor.get_note_hi();
Fixed::x(12, Map::south( Fixed::x(12, Map::south(
1, 1,
move||(note_lo..=note_hi).rev(), move||(note_lo..=note_hi).rev(),

View file

@ -11,9 +11,9 @@ pub trait MidiViewer: HasSize<TuiOut> + MidiRange + MidiPoint + Debug + Send + S
} }
/// Make sure cursor is within note range /// Make sure cursor is within note range
fn autoscroll (&self) { fn autoscroll (&self) {
let note_pos = self.note_pos().min(127); let note_pos = self.get_note_pos().min(127);
let note_lo = self.note_lo().get(); let note_lo = self.get_note_lo();
let note_hi = self.note_hi(); let note_hi = self.get_note_hi();
if note_pos < note_lo { if note_pos < note_lo {
self.note_lo().set(note_pos); self.note_lo().set(note_pos);
} else if note_pos > note_hi { } else if note_pos > note_hi {
@ -23,9 +23,9 @@ pub trait MidiViewer: HasSize<TuiOut> + MidiRange + MidiPoint + Debug + Send + S
/// Make sure time range is within display /// Make sure time range is within display
fn autozoom (&self) { fn autozoom (&self) {
if self.time_lock().get() { if self.time_lock().get() {
let time_len = self.time_len().get(); let time_len = self.get_time_len();
let time_axis = self.time_axis().get(); let time_axis = self.get_time_axis();
let time_zoom = self.time_zoom().get(); let time_zoom = self.get_time_zoom();
loop { loop {
let time_zoom = self.time_zoom().get(); let time_zoom = self.time_zoom().get();
let time_area = time_axis * time_zoom; let time_area = time_axis * time_zoom;

View file

@ -20,53 +20,60 @@ impl Default for MidiPointModel {
} }
} }
pub trait NotePoint {
/// Get the current length of the note cursor.
fn note_len (&self) -> usize;
/// Set the length of the note cursor, returning the previous value.
fn set_note_len (&self, x: usize) -> usize;
/// Get the current pitch of the note cursor.
fn note_pos (&self) -> usize;
/// Set the current pitch fo the note cursor, returning the previous value.
fn set_note_pos (&self, x: usize) -> usize;
}
pub trait TimePoint {
/// Get the current time position of the note cursor.
fn time_pos (&self) -> usize;
/// Set the current time position of the note cursor, returning the previous value.
fn set_time_pos (&self, x: usize) -> usize;
}
pub trait MidiPoint: NotePoint + TimePoint {
/// Get the current end of the note cursor.
fn note_end (&self) -> usize {
self.time_pos() + self.note_len()
}
}
impl<T: NotePoint + TimePoint> MidiPoint for T {}
impl NotePoint for MidiPointModel { impl NotePoint for MidiPointModel {
fn note_len (&self) -> usize { fn note_len (&self) -> &AtomicUsize {
self.note_len.load(Relaxed) &self.note_len
} }
fn set_note_len (&self, x: usize) -> usize { fn note_pos (&self) -> &AtomicUsize {
self.note_len.swap(x, Relaxed) &self.note_pos
}
fn note_pos (&self) -> usize {
self.note_pos.load(Relaxed).min(127)
}
fn set_note_pos (&self, x: usize) -> usize {
self.note_pos.swap(x.min(127), Relaxed)
} }
} }
impl TimePoint for MidiPointModel { impl TimePoint for MidiPointModel {
fn time_pos (&self) -> usize { fn time_pos (&self) -> &AtomicUsize {
self.time_pos.load(Relaxed) self.time_pos.as_ref()
}
fn set_time_pos (&self, x: usize) -> usize {
self.time_pos.swap(x, Relaxed)
} }
} }
pub trait NotePoint {
fn note_len (&self) -> &AtomicUsize;
/// Get the current length of the note cursor.
fn get_note_len (&self) -> usize {
self.note_len().load(Relaxed)
}
/// Set the length of the note cursor, returning the previous value.
fn set_note_len (&self, x: usize) -> usize {
self.note_len().swap(x, Relaxed)
}
fn note_pos (&self) -> &AtomicUsize;
/// Get the current pitch of the note cursor.
fn get_note_pos (&self) -> usize {
self.note_pos().load(Relaxed).min(127)
}
/// Set the current pitch fo the note cursor, returning the previous value.
fn set_note_pos (&self, x: usize) -> usize {
self.note_pos().swap(x.min(127), Relaxed)
}
}
pub trait TimePoint {
fn time_pos (&self) -> &AtomicUsize;
/// Get the current time position of the note cursor.
fn get_time_pos (&self) -> usize {
self.time_pos().load(Relaxed)
}
/// Set the current time position of the note cursor, returning the previous value.
fn set_time_pos (&self, x: usize) -> usize {
self.time_pos().swap(x, Relaxed)
}
}
pub trait MidiPoint: NotePoint + TimePoint {
/// Get the current end of the note cursor.
fn get_note_end (&self) -> usize {
self.get_time_pos() + self.get_note_len()
}
}
impl<T: NotePoint + TimePoint> MidiPoint for T {}

View file

@ -1,4 +1,5 @@
use crate::*; use crate::*;
use std::sync::atomic::Ordering;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MidiRangeModel { pub struct MidiRangeModel {
@ -28,20 +29,44 @@ from!(|data:(usize, bool)|MidiRangeModel = Self {
}); });
pub trait TimeRange { pub trait TimeRange {
fn time_len (&self) -> &AtomicUsize; fn time_len (&self) -> &AtomicUsize;
fn time_zoom (&self) -> &AtomicUsize; fn get_time_len (&self) -> usize {
fn time_lock (&self) -> &AtomicBool; self.time_len().load(Ordering::Relaxed)
}
fn time_zoom (&self) -> &AtomicUsize;
fn get_time_zoom (&self) -> usize {
self.time_zoom().load(Ordering::Relaxed)
}
fn time_lock (&self) -> &AtomicBool;
fn get_time_lock (&self) -> bool {
self.time_lock().load(Ordering::Relaxed)
}
fn time_start (&self) -> &AtomicUsize; fn time_start (&self) -> &AtomicUsize;
fn time_axis (&self) -> &AtomicUsize; fn get_time_start (&self) -> usize {
fn time_end (&self) -> usize { self.time_start().load(Ordering::Relaxed)
}
fn time_axis (&self) -> &AtomicUsize;
fn get_time_axis (&self) -> usize {
self.time_axis().load(Ordering::Relaxed)
}
fn get_time_end (&self) -> usize {
self.time_start().get() + self.time_axis().get() * self.time_zoom().get() self.time_start().get() + self.time_axis().get() * self.time_zoom().get()
} }
} }
pub trait NoteRange { pub trait NoteRange {
fn note_lo (&self) -> &AtomicUsize; fn note_lo (&self) -> &AtomicUsize;
fn note_axis (&self) -> &AtomicUsize; fn get_note_lo (&self) -> usize {
fn note_hi (&self) -> usize { self.note_lo().load(Ordering::Relaxed)
}
fn set_note_lo (&self, x: usize) -> usize {
self.note_lo().swap(x, Ordering::Relaxed)
}
fn note_axis (&self) -> &AtomicUsize;
fn get_note_axis (&self) -> usize {
self.note_axis().load(Ordering::Relaxed)
}
fn get_note_hi (&self) -> usize {
(self.note_lo().get() + self.note_axis().get().saturating_sub(1)).min(127) (self.note_lo().get() + self.note_axis().get().saturating_sub(1)).min(127)
} }
} }