tek/engine/engine_traits.rs
stop screaming 37068784cb refactor(engine): flatten
- add `just stats`
- add basic doctests
2026-02-21 00:03:06 +02:00

129 lines
4 KiB
Rust

use crate::*;
use std::sync::atomic::Ordering;
//pub trait MaybeHas<T>: Send + Sync {
//fn get (&self) -> Option<&T>;
//}
pub trait HasN<T>: Send + Sync {
fn get_nth (&self, key: usize) -> &T;
fn get_nth_mut (&mut self, key: usize) -> &mut T;
}
pub trait Gettable<T> {
/// Returns current value
fn get (&self) -> T;
}
pub trait Mutable<T>: Gettable<T> {
/// Sets new value, returns old
fn set (&mut self, value: T) -> T;
}
pub trait InteriorMutable<T>: Gettable<T> {
/// 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<f64> {}