mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-10-08 18:56:42 +02:00
147 lines
4.6 KiB
Rust
147 lines
4.6 KiB
Rust
use crate::*;
|
|
|
|
#[derive(Default, Debug)] pub struct Pool<T>(pub Arc<RwLock<Vec<Slot<T>>>>);
|
|
pub type SamplePool = Pool<Sample>;
|
|
pub type ClipPool = Pool<MidiClip>;
|
|
impl<T> Clone for Pool<T> { fn clone (&self) -> Self { Pool(self.0.clone()) } }
|
|
impl<T> Pool<T> {
|
|
pub fn slot (&self, index: usize) -> Slot<T> {
|
|
let mut state = self.0.write();
|
|
while index >= state.len() {
|
|
state.push(Slot::new(None));
|
|
}
|
|
state[index].clone()
|
|
}
|
|
pub fn delete (&self, index: usize) -> Option<Arc<RwLock<T>>> {
|
|
let mut none = None;
|
|
let mut slot = self.slot(index).write();
|
|
std::mem::swap(&mut none, &mut slot);
|
|
none
|
|
}
|
|
pub fn len (&self) -> usize {
|
|
self.0.read().len()
|
|
}
|
|
pub fn get (&self, index: usize) -> Option<ArcRwLockReadGuard<RawRwLock, Option<Arc<RwLock<T>>>>> {
|
|
self.0.read_arc().get(index).map(|clip|clip.read())
|
|
}
|
|
pub fn set (&self, index: usize, value: Option<T>) {
|
|
self.write()[index] = Slot::new(value);
|
|
}
|
|
pub fn read (&self) -> ArcRwLockReadGuard<RawRwLock, Vec<Slot<T>>> {
|
|
self.0.read_arc()
|
|
}
|
|
pub fn write (&self) -> ArcRwLockWriteGuard<RawRwLock, Vec<Slot<T>>> {
|
|
self.0.write_arc()
|
|
}
|
|
pub fn append (&self, value: Option<T>) -> Slot<T> {
|
|
let slot = Slot::new(value);
|
|
self.0.write().push(slot.clone());
|
|
slot
|
|
}
|
|
}
|
|
|
|
impl Pool<MidiClip> {
|
|
pub fn eval <'a, T> (_: &T, _: impl Language) -> Perhaps<ClipPool> {
|
|
todo!()
|
|
}
|
|
pub fn remove (&self, filter: &MidiClip) {
|
|
let mut iter = self.0.write();
|
|
iter.retain(|x|if let Some(x) = &*x.0.read() {
|
|
&*x.read() != filter
|
|
} else {
|
|
true
|
|
})
|
|
}
|
|
}
|
|
|
|
impl Pool<Sample> {
|
|
pub fn eval <'a> (_: &App, _: impl Language) -> Perhaps<SamplePool> {
|
|
todo!()
|
|
}
|
|
}
|
|
|
|
impl<T> From<Vec<Option<T>>> for Pool<T> {
|
|
fn from (values: Vec<Option<T>>) -> Self {
|
|
Self(Arc::new(RwLock::new(values.into_iter().map(Slot::new).collect())))
|
|
}
|
|
}
|
|
|
|
#[derive(Default, Debug)] pub struct Slot<T>(pub Arc<RwLock<Option<Arc<RwLock<T>>>>>);
|
|
pub type SampleSlot = Slot<Sample>;
|
|
pub type ClipSlot = Slot<MidiClip>;
|
|
|
|
impl<T> Clone for Slot<T> {
|
|
fn clone (&self) -> Self {
|
|
Slot(self.0.clone())
|
|
}
|
|
}
|
|
|
|
impl<T> Slot<T> {
|
|
pub fn new (value: impl Into<Option<T>>) -> Self {
|
|
Self(Arc::new(RwLock::new(value.into().map(|value|Arc::new(RwLock::new(value))))))
|
|
}
|
|
pub fn read (&self) -> ArcRwLockReadGuard<RawRwLock, Option<Arc<RwLock<T>>>> {
|
|
self.0.read_arc()
|
|
}
|
|
pub fn write (&self) -> ArcRwLockWriteGuard<RawRwLock, Option<Arc<RwLock<T>>>> {
|
|
self.0.write_arc()
|
|
}
|
|
pub fn set_to (&mut self, value: Self) {
|
|
self.0 = value.0;
|
|
}
|
|
pub fn set (&self, value: Option<T>) -> Option<Arc<RwLock<T>>> {
|
|
let mut value = value.map(|value|Arc::new(RwLock::new(value)));
|
|
std::mem::swap(&mut*self.0.write(), &mut value);
|
|
value
|
|
}
|
|
}
|
|
pub trait SlotExt<T> {
|
|
fn map_inner <U> (&self, cb: impl FnOnce(&T)->U) -> Option<U>;
|
|
fn map_inner_mut <U> (&self, cb: impl FnOnce(&mut T)->U) -> Option<U>;
|
|
}
|
|
impl<T> SlotExt<T> for Slot<T> {
|
|
fn map_inner <U> (&self, cb: impl FnOnce(&T)->U) -> Option<U> {
|
|
self.read().as_ref().map(|x|cb(&*x.read()))
|
|
}
|
|
fn map_inner_mut <U> (&self, cb: impl FnOnce(&mut T)->U) -> Option<U> {
|
|
self.read().as_ref().map(|x|cb(&mut*x.write()))
|
|
}
|
|
}
|
|
impl<T> SlotExt<T> for Option<Slot<T>> {
|
|
fn map_inner <U> (&self, cb: impl FnOnce(&T)->U) -> Option<U> {
|
|
self.as_ref().map(|x|x.map_inner(cb))?
|
|
}
|
|
fn map_inner_mut <U> (&self, cb: impl FnOnce(&mut T)->U) -> Option<U> {
|
|
self.as_ref().map(|x|x.map_inner_mut(cb))?
|
|
}
|
|
}
|
|
|
|
impl Slot<MidiClip> {
|
|
pub fn eval <'a> (state: &App, src: impl Language) -> Perhaps<ClipSlot> {
|
|
eval_word(src, |word|Ok(match word {
|
|
|
|
":selected" if let Selection::TrackClip { track, scene } = state.selection() => {
|
|
state.scenes()[*scene].clips.slot(*track)
|
|
},
|
|
|
|
//":selected-or-create" if let Selection::TrackClip {
|
|
//track, scene
|
|
//} = state.selection() => Some(if let Some(Some(clip)) = state.scenes()[*scene].clips.get(*track) {
|
|
//clip.clone()
|
|
//} else {
|
|
//let clip: Arc<RwLock<MidiClip>> = Arc::new(RwLock::new(Default::default()));
|
|
//state.scenes()[*scene].clips[*track] = Some(clip.clone());
|
|
//clip
|
|
//}),
|
|
|
|
_ => return err!("not a clip: {word}")
|
|
|
|
}))
|
|
}
|
|
}
|
|
|
|
impl Slot<Sample> {
|
|
pub fn eval <'a> (_: &App, _: impl Language) -> Perhaps<SampleSlot> {
|
|
todo!()
|
|
}
|
|
}
|