use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr::NonNull;
use super::super::audio_sample::AudioSample;
use super::super::SoundCompletionCallback;
use super::sound_source::{AsSoundSource, SoundSource};
use crate::callback_builder::Constructed;
use crate::callbacks::RegisteredCallback;
use crate::capi_state::CApiState;
use crate::ctypes::*;
use crate::time::{RelativeTimeSpan, TimeDelta};
#[derive(Debug)]
pub struct SamplePlayer<'sample> {
source: ManuallyDrop<SoundSource>,
ptr: NonNull<CSamplePlayer>,
loop_callback: Option<RegisteredCallback>,
_marker: PhantomData<&'sample AudioSample>,
}
impl SamplePlayer<'_> {
pub fn new(sample: &AudioSample) -> Self {
let ptr = unsafe { Self::fns().newPlayer.unwrap()() };
unsafe { Self::fns().setSample.unwrap()(ptr, sample.cptr() as *mut _) }
SamplePlayer {
source: ManuallyDrop::new(SoundSource::from_ptr(ptr as *mut CSoundSource)),
ptr: NonNull::new(ptr).unwrap(),
loop_callback: None,
_marker: PhantomData,
}
}
pub fn len(&self) -> TimeDelta {
TimeDelta::from_seconds_lossy(unsafe { Self::fns().getLength.unwrap()(self.cptr() as *mut _) })
}
pub fn play(&mut self, repeat: i32, rate: f32) {
let r = unsafe { Self::fns().play.unwrap()(self.cptr_mut(), repeat, rate) };
assert!(r != 0)
}
pub fn stop(&mut self) {
unsafe { Self::fns().stop.unwrap()(self.cptr_mut()) };
}
pub fn pause(&mut self) {
unsafe { Self::fns().setPaused.unwrap()(self.cptr_mut(), 1) }
}
pub fn unpause(&mut self) {
unsafe { Self::fns().setPaused.unwrap()(self.cptr_mut(), 1) }
}
pub fn is_playing(&self) -> bool {
unsafe { Self::fns().isPlaying.unwrap()(self.cptr() as *mut _) != 0 }
}
pub fn set_offset(&mut self, offset: TimeDelta) {
unsafe { Self::fns().setOffset.unwrap()(self.cptr_mut(), offset.to_seconds()) };
}
pub fn offset(&mut self) -> TimeDelta {
TimeDelta::from_seconds_lossy(unsafe { Self::fns().getOffset.unwrap()(self.cptr() as *mut _) })
}
pub fn set_play_range(&mut self, play_range: RelativeTimeSpan) {
unsafe {
Self::fns().setPlayRange.unwrap()(
self.cptr_mut(),
play_range.start.to_sample_frames(),
play_range.end.to_sample_frames(),
)
};
}
pub fn set_rate(&mut self, rate: f32) {
unsafe { Self::fns().setRate.unwrap()(self.cptr_mut(), rate) }
}
pub fn rate(&self) -> f32 {
unsafe { Self::fns().getRate.unwrap()(self.cptr() as *mut _) }
}
pub fn set_loop_callback<'a, T, F: Fn(T) + 'static>(
&mut self,
loop_callback: SoundCompletionCallback<'a, T, F, Constructed>,
) {
self.loop_callback = None;
let func = loop_callback.into_inner().and_then(|(callbacks, cb)| {
let key = unsafe { self.as_source_mut().cptr().add(1) } as usize;
let (func, reg) = callbacks.add_sound_source_completion(key, cb);
self.loop_callback = Some(reg);
Some(func)
});
unsafe { Self::fns().setLoopCallback.unwrap()(self.cptr_mut(), func) }
}
pub(crate) fn cptr(&self) -> *const CSamplePlayer {
self.ptr.as_ptr()
}
pub(crate) fn cptr_mut(&mut self) -> *mut CSamplePlayer {
self.ptr.as_ptr()
}
pub(crate) fn fns() -> &'static craydate_sys::playdate_sound_sampleplayer {
unsafe { &*CApiState::get().csound.sampleplayer }
}
}
impl Drop for SamplePlayer<'_> {
fn drop(&mut self) {
self.set_loop_callback(SoundCompletionCallback::none());
unsafe { ManuallyDrop::drop(&mut self.source) };
unsafe { Self::fns().freePlayer.unwrap()(self.cptr_mut()) }
}
}
impl AsRef<SoundSource> for SamplePlayer<'_> {
fn as_ref(&self) -> &SoundSource {
&self.source
}
}
impl AsMut<SoundSource> for SamplePlayer<'_> {
fn as_mut(&mut self) -> &mut SoundSource {
&mut self.source
}
}