craydate/sound/sources/
sample_player.rs1use core::marker::PhantomData;
2use core::mem::ManuallyDrop;
3use core::ptr::NonNull;
4
5use super::super::audio_sample::AudioSample;
6use super::super::SoundCompletionCallback;
7use super::sound_source::{AsSoundSource, SoundSource};
8use crate::callback_builder::Constructed;
9use crate::callbacks::RegisteredCallback;
10use crate::capi_state::CApiState;
11use crate::ctypes::*;
12use crate::time::{RelativeTimeSpan, TimeDelta};
13
14#[derive(Debug)]
20pub struct SamplePlayer<'sample> {
21 source: ManuallyDrop<SoundSource>,
22 ptr: NonNull<CSamplePlayer>,
23 loop_callback: Option<RegisteredCallback>,
24 _marker: PhantomData<&'sample AudioSample>,
25}
26impl SamplePlayer<'_> {
27 pub fn new(sample: &AudioSample) -> Self {
29 let ptr = unsafe { Self::fns().newPlayer.unwrap()() };
30 unsafe { Self::fns().setSample.unwrap()(ptr, sample.cptr() as *mut _) }
32 SamplePlayer {
33 source: ManuallyDrop::new(SoundSource::from_ptr(ptr as *mut CSoundSource)),
34 ptr: NonNull::new(ptr).unwrap(),
35 loop_callback: None,
36 _marker: PhantomData,
37 }
38 }
39
40 pub fn len(&self) -> TimeDelta {
42 TimeDelta::from_seconds_lossy(unsafe { Self::fns().getLength.unwrap()(self.cptr() as *mut _) })
44 }
45
46 pub fn play(&mut self, repeat: i32, rate: f32) {
54 let r = unsafe { Self::fns().play.unwrap()(self.cptr_mut(), repeat, rate) };
56 assert!(r != 0)
57 }
58 pub fn stop(&mut self) {
59 unsafe { Self::fns().stop.unwrap()(self.cptr_mut()) };
60 }
61 pub fn pause(&mut self) {
63 unsafe { Self::fns().setPaused.unwrap()(self.cptr_mut(), 1) }
64 }
65 pub fn unpause(&mut self) {
67 unsafe { Self::fns().setPaused.unwrap()(self.cptr_mut(), 1) }
68 }
69 pub fn is_playing(&self) -> bool {
71 unsafe { Self::fns().isPlaying.unwrap()(self.cptr() as *mut _) != 0 }
73 }
74
75 pub fn set_offset(&mut self, offset: TimeDelta) {
77 unsafe { Self::fns().setOffset.unwrap()(self.cptr_mut(), offset.to_seconds()) };
78 }
79 pub fn offset(&mut self) -> TimeDelta {
81 TimeDelta::from_seconds_lossy(unsafe { Self::fns().getOffset.unwrap()(self.cptr() as *mut _) })
83 }
84
85 pub fn set_play_range(&mut self, play_range: RelativeTimeSpan) {
87 unsafe {
88 Self::fns().setPlayRange.unwrap()(
89 self.cptr_mut(),
90 play_range.start.to_sample_frames(),
91 play_range.end.to_sample_frames(),
92 )
93 };
94 }
95
96 pub fn set_rate(&mut self, rate: f32) {
100 unsafe { Self::fns().setRate.unwrap()(self.cptr_mut(), rate) }
101 }
102 pub fn rate(&self) -> f32 {
104 unsafe { Self::fns().getRate.unwrap()(self.cptr() as *mut _) }
106 }
107
108 pub fn set_loop_callback<'a, T, F: Fn(T) + 'static>(
130 &mut self,
131 loop_callback: SoundCompletionCallback<'a, T, F, Constructed>,
132 ) {
133 self.loop_callback = None;
134 let func = loop_callback.into_inner().and_then(|(callbacks, cb)| {
135 let key = unsafe { self.as_source_mut().cptr().add(1) } as usize;
137 let (func, reg) = callbacks.add_sound_source_completion(key, cb);
138 self.loop_callback = Some(reg);
139 Some(func)
140 });
141 unsafe { Self::fns().setLoopCallback.unwrap()(self.cptr_mut(), func) }
142 }
143
144 pub(crate) fn cptr(&self) -> *const CSamplePlayer {
145 self.ptr.as_ptr()
146 }
147 pub(crate) fn cptr_mut(&mut self) -> *mut CSamplePlayer {
148 self.ptr.as_ptr()
149 }
150 pub(crate) fn fns() -> &'static craydate_sys::playdate_sound_sampleplayer {
151 unsafe { &*CApiState::get().csound.sampleplayer }
152 }
153}
154
155impl Drop for SamplePlayer<'_> {
156 fn drop(&mut self) {
157 self.set_loop_callback(SoundCompletionCallback::none());
158 unsafe { ManuallyDrop::drop(&mut self.source) };
160 unsafe { Self::fns().freePlayer.unwrap()(self.cptr_mut()) }
161 }
162}
163
164impl AsRef<SoundSource> for SamplePlayer<'_> {
165 fn as_ref(&self) -> &SoundSource {
166 &self.source
167 }
168}
169impl AsMut<SoundSource> for SamplePlayer<'_> {
170 fn as_mut(&mut self) -> &mut SoundSource {
171 &mut self.source
172 }
173}