use crate::*; use std::sync::atomic::Ordering; //pub trait MaybeHas: Send + Sync { //fn get (&self) -> Option<&T>; //} pub trait HasN: Send + Sync { fn get_nth (&self, key: usize) -> &T; fn get_nth_mut (&mut self, key: usize) -> &mut T; } pub trait Gettable { /// Returns current value fn get (&self) -> T; } pub trait Mutable: Gettable { /// Sets new value, returns old fn set (&mut self, value: T) -> T; } pub trait InteriorMutable: Gettable { /// Sets new value, returns old fn set (&self, value: T) -> T; } 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() } } 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 {} /// A unit of time, represented as an atomic 64-bit float. /// /// According to https://stackoverflow.com/a/873367, as per IEEE754, /// every integer between 1 and 2^53 can be represented exactly. /// This should mean that, even at 192kHz sampling rate, over 1 year of audio /// can be clocked in microseconds with f64 without losing precision. pub trait TimeUnit: InteriorMutable {}