use alloc::rc::Rc;
use core::ptr::NonNull;
use super::synth_signal::{SynthSignal, SynthSignalSubclass};
use crate::capi_state::CApiState;
use crate::{ctypes::*, TimeTicks};
struct EnvelopeSubclass {
ptr: NonNull<CSynthEnvelope>,
}
impl Drop for EnvelopeSubclass {
fn drop(&mut self) {
unsafe { Envelope::fns().freeEnvelope.unwrap()(self.ptr.as_ptr()) }
}
}
impl SynthSignalSubclass for EnvelopeSubclass {}
pub struct Envelope {
signal: SynthSignal,
subclass: Rc<EnvelopeSubclass>,
}
impl Envelope {
fn from_ptr(ptr: *mut CSynthEnvelope) -> Self {
let subclass = Rc::new(EnvelopeSubclass {
ptr: NonNull::new(ptr).unwrap(),
});
let signal = SynthSignal::new(ptr as *mut CSynthSignalValue, subclass.clone());
Envelope { signal, subclass }
}
pub fn new(attack: TimeTicks, decay: TimeTicks, sustain: f32, release: TimeTicks) -> Self {
let ptr = unsafe {
Self::fns().newEnvelope.unwrap()(
attack.to_seconds(),
decay.to_seconds(),
sustain,
release.to_seconds(),
)
};
Self::from_ptr(ptr)
}
pub fn set_attack(&mut self, attack: TimeTicks) {
unsafe { Self::fns().setAttack.unwrap()(self.cptr_mut(), attack.to_seconds()) }
}
pub fn set_decay(&mut self, decay: TimeTicks) {
unsafe { Self::fns().setDecay.unwrap()(self.cptr_mut(), decay.to_seconds()) }
}
pub fn set_sustain_level(&mut self, sustain: f32) {
unsafe { Self::fns().setSustain.unwrap()(self.cptr_mut(), sustain) }
}
pub fn set_release(&mut self, release: TimeTicks) {
unsafe { Self::fns().setRelease.unwrap()(self.cptr_mut(), release.to_seconds()) }
}
pub fn set_legato(&mut self, legato: bool) {
unsafe { Self::fns().setLegato.unwrap()(self.cptr_mut(), legato as i32) }
}
pub fn set_retrigger(&mut self, retrigger: bool) {
unsafe { Self::fns().setRetrigger.unwrap()(self.cptr_mut(), retrigger as i32) }
}
pub fn get_value(&self) -> f32 {
unsafe { Self::fns().getValue.unwrap()(self.cptr() as *mut _) }
}
pub(crate) fn cptr(&self) -> *const CSynthEnvelope {
self.subclass.ptr.as_ptr()
}
pub(crate) fn cptr_mut(&mut self) -> *mut CSynthEnvelope {
self.subclass.ptr.as_ptr()
}
pub(crate) fn fns() -> &'static craydate_sys::playdate_sound_envelope {
unsafe { &*CApiState::get().csound.envelope }
}
}
impl AsRef<SynthSignal> for Envelope {
fn as_ref(&self) -> &SynthSignal {
&self.signal
}
}
impl AsMut<SynthSignal> for Envelope {
fn as_mut(&mut self) -> &mut SynthSignal {
&mut self.signal
}
}