use crate::*; use std::sync::atomic::Ordering; #[derive(Debug, Clone)] pub struct MidiRangeModel { pub time_len: Arc, /// Length of visible time axis pub time_axis: Arc, /// Earliest time displayed pub time_start: Arc, /// Time step pub time_zoom: Arc, /// Auto rezoom to fit in time axis pub time_lock: Arc, /// Length of visible note axis pub note_axis: Arc, // Lowest note displayed pub note_lo: Arc, } from!(|data:(usize, bool)|MidiRangeModel = Self { time_len: Arc::new(0.into()), note_axis: Arc::new(0.into()), note_lo: Arc::new(0.into()), time_axis: Arc::new(0.into()), time_start: Arc::new(0.into()), time_zoom: Arc::new(data.0.into()), time_lock: Arc::new(data.1.into()), }); pub trait TimeRange { fn time_len (&self) -> &AtomicUsize; fn get_time_len (&self) -> usize { self.time_len().load(Ordering::Relaxed) } fn time_zoom (&self) -> &AtomicUsize; fn get_time_zoom (&self) -> usize { self.time_zoom().load(Ordering::Relaxed) } fn set_time_zoom (&self, value: usize) -> usize { self.time_zoom().swap(value, Ordering::Relaxed) } fn time_lock (&self) -> &AtomicBool; fn get_time_lock (&self) -> bool { self.time_lock().load(Ordering::Relaxed) } fn set_time_lock (&self, value: bool) -> bool { self.time_lock().swap(value, Ordering::Relaxed) } fn time_start (&self) -> &AtomicUsize; fn get_time_start (&self) -> usize { self.time_start().load(Ordering::Relaxed) } fn set_time_start (&self, value: usize) -> usize { self.time_start().swap(value, 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() } } pub trait NoteRange { fn note_lo (&self) -> &AtomicUsize; fn get_note_lo (&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) } } pub trait MidiRange: TimeRange + NoteRange {} impl MidiRange for T {} impl TimeRange for MidiRangeModel { fn time_len (&self) -> &AtomicUsize { &self.time_len } fn time_zoom (&self) -> &AtomicUsize { &self.time_zoom } fn time_lock (&self) -> &AtomicBool { &self.time_lock } fn time_start (&self) -> &AtomicUsize { &self.time_start } fn time_axis (&self) -> &AtomicUsize { &self.time_axis } } impl NoteRange for MidiRangeModel { fn note_lo (&self) -> &AtomicUsize { &self.note_lo } fn note_axis (&self) -> &AtomicUsize { &self.note_axis } }