1#![cfg_attr(not(test), no_std)]
2#![feature(const_trait_impl)]
3
4use core::ffi::c_int;
5use core::ffi::c_void;
6
7use sys::ffi::AudioSourceFunction;
8use sys::traits::AsRaw;
9
10extern crate sys;
11extern crate alloc;
12
13pub mod error;
14pub mod player;
15pub mod sample;
16pub mod source;
17
18pub mod prelude {
22 pub use crate::error::ApiError as SndApiError;
23 pub use crate::error::Error as SndError;
24
25 pub use crate::player;
26 pub use crate::sample;
27}
28
29
30#[derive(Debug, Clone, Copy)]
31pub struct Sound<Api = api::Default>(Api);
32
33impl Sound<api::Default> {
34 #[allow(non_snake_case)]
38 pub fn Default() -> Self { Self(Default::default()) }
39}
40
41impl Sound<api::Cache> {
42 #[allow(non_snake_case)]
46 pub fn Cached() -> Self { Self(Default::default()) }
47}
48
49impl<Api: Default + api::Api> Default for Sound<Api> {
50 fn default() -> Self { Self(Default::default()) }
51}
52
53impl<Api: Default + api::Api> Sound<Api> {
54 pub fn new() -> Self { Self(Default::default()) }
55}
56
57impl<Api: api::Api> Sound<Api> {
58 pub fn new_with(api: Api) -> Self { Self(api) }
59}
60
61impl<Api: api::Api> Sound<Api> {
62 #[doc(alias = "sys::ffi::playdate_sound::getCurrentTime")]
66 pub fn current_time(&self) -> u32 {
67 let f = self.0.get_current_time();
68 unsafe { f() }
69 }
70
71
72 #[doc(alias = "sys::ffi::playdate_sound::getHeadphoneState")]
85 #[inline(always)]
86 pub fn headphone_state(&self, headphone: Option<&mut c_int>, mic: Option<&mut c_int>) {
87 self.set_headphone_state_change_callback(headphone, mic, None)
88 }
89
90 #[doc(alias = "sys::ffi::playdate_sound::getHeadphoneState")]
101 pub fn set_headphone_state_change_callback(&self,
102 headphone: Option<&mut c_int>,
103 mic: Option<&mut c_int>,
104 change_callback: Option<unsafe extern "C" fn(headphone: c_int,
105 mic: c_int)>) {
106 use core::ptr::null_mut;
107
108 let f = self.0.get_headphone_state();
109 unsafe {
110 f(
111 headphone.map_or(null_mut() as _, |v| v as *mut _),
112 mic.map_or(null_mut() as _, |v| v as *mut _),
113 change_callback,
114 )
115 }
116 }
117
118 #[doc(alias = "sys::ffi::playdate_sound::setOutputsActive")]
122 pub fn set_outputs_active(&self, headphone: bool, speaker: bool) {
123 let f = self.0.set_outputs_active();
124 unsafe { f(headphone.into(), speaker.into()) }
125 }
126
127 #[doc(alias = "sys::ffi::playdate_sound::addSource")]
139 pub fn add_source_raw(&self,
140 callback: AudioSourceFunction,
141 context: *mut c_void,
142 stereo: bool)
143 -> source::SoundSource {
144 let f = self.0.add_source();
145 unsafe { f(callback, context, stereo.into()) }.into()
146 }
147
148 #[doc(alias = "sys::ffi::playdate_sound::removeSource")]
155 pub fn remove_source(&self, source: &source::SoundSource) -> bool {
156 let f = self.0.remove_source();
157 unsafe { f(source.as_raw()) == 1 }
158 }
159
160
161 }
202
203
204pub mod api {
205 use core::ffi::c_int;
206 use core::ffi::c_void;
207 use core::ptr::NonNull;
208 use sys::ffi::*;
209
210
211 #[derive(Debug, Clone, Copy, core::default::Default)]
215 pub struct Default;
216 impl Api for Default {}
217
218
219 #[derive(Clone, Copy)]
225 #[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
226 pub struct Cache(&'static playdate_sound);
227
228 impl core::default::Default for Cache {
229 fn default() -> Self { Self(sys::api!(sound)) }
230 }
231
232 impl From<*const playdate_sound> for Cache {
233 #[inline(always)]
234 fn from(ptr: *const playdate_sound) -> Self { Self(unsafe { ptr.as_ref() }.expect("sp")) }
235 }
236
237 impl From<&'static playdate_sound> for Cache {
238 #[inline(always)]
239 fn from(r: &'static playdate_sound) -> Self { Self(r) }
240 }
241
242 impl From<NonNull<playdate_sound>> for Cache {
243 #[inline(always)]
244 fn from(ptr: NonNull<playdate_sound>) -> Self { Self(unsafe { ptr.as_ref() }) }
245 }
246
247 impl From<&'_ NonNull<playdate_sound>> for Cache {
248 #[inline(always)]
249 fn from(ptr: &NonNull<playdate_sound>) -> Self { Self(unsafe { ptr.as_ref() }) }
250 }
251
252
253 impl Api for Cache {
254 #[inline(always)]
255 fn channel(&self) -> &'static playdate_sound_channel {
256 unsafe { self.0.channel.as_ref() }.expect("channel")
257 }
258 #[inline(always)]
259 fn fileplayer(&self) -> &'static playdate_sound_fileplayer {
260 unsafe { self.0.fileplayer.as_ref() }.expect("fileplayer")
261 }
262 #[inline(always)]
263 fn sample(&self) -> &'static playdate_sound_sample { unsafe { self.0.sample.as_ref() }.expect("sample") }
264 #[inline(always)]
265 fn sampleplayer(&self) -> &'static playdate_sound_sampleplayer {
266 unsafe { self.0.sampleplayer.as_ref() }.expect("sampleplayer")
267 }
268 #[inline(always)]
269 fn synth(&self) -> &'static playdate_sound_synth { unsafe { self.0.synth.as_ref() }.expect("synth") }
270 #[inline(always)]
271 fn sequence(&self) -> &'static playdate_sound_sequence {
272 unsafe { self.0.sequence.as_ref() }.expect("sequence")
273 }
274 #[inline(always)]
275 fn effect(&self) -> &'static playdate_sound_effect { unsafe { self.0.effect.as_ref() }.expect("effect") }
276 #[inline(always)]
277 fn lfo(&self) -> &'static playdate_sound_lfo { unsafe { self.0.lfo.as_ref() }.expect("lfo") }
278 #[inline(always)]
279 fn envelope(&self) -> &'static playdate_sound_envelope {
280 unsafe { self.0.envelope.as_ref() }.expect("envelope")
281 }
282 #[inline(always)]
283 fn source(&self) -> &'static playdate_sound_source { unsafe { self.0.source.as_ref() }.expect("source") }
284 #[inline(always)]
285 fn control_signal(&self) -> &'static playdate_control_signal {
286 unsafe { self.0.controlsignal.as_ref() }.expect("controlsignal")
287 }
288 #[inline(always)]
289 fn track(&self) -> &'static playdate_sound_track { unsafe { self.0.track.as_ref() }.expect("track") }
290 #[inline(always)]
291 fn instrument(&self) -> &'static playdate_sound_instrument {
292 unsafe { self.0.instrument.as_ref() }.expect("instrument")
293 }
294 #[inline(always)]
295 fn signal(&self) -> &'static playdate_sound_signal { unsafe { self.0.signal.as_ref() }.expect("signal") }
296
297
298 fn get_current_time(&self) -> unsafe extern "C" fn() -> u32 {
299 self.0.getCurrentTime.expect("getCurrentTime")
300 }
301
302 fn add_source(
303 &self)
304 -> unsafe extern "C" fn(callback: AudioSourceFunction,
305 context: *mut c_void,
306 stereo: c_int) -> *mut SoundSource {
307 self.0.addSource.expect("addSource")
308 }
309
310 fn get_default_channel(&self) -> unsafe extern "C" fn() -> *mut SoundChannel {
311 self.0.getDefaultChannel.expect("getDefaultChannel")
312 }
313
314 fn add_channel(&self) -> unsafe extern "C" fn(channel: *mut SoundChannel) -> c_int {
315 self.0.addChannel.expect("addChannel")
316 }
317
318 fn remove_channel(&self) -> unsafe extern "C" fn(channel: *mut SoundChannel) -> c_int {
319 self.0.removeChannel.expect("removeChannel")
320 }
321
322 fn set_mic_callback(
323 &self)
324 -> unsafe extern "C" fn(callback: RecordCallback, context: *mut c_void, source: MicSource) -> c_int {
325 self.0.setMicCallback.expect("setMicCallback")
326 }
327
328 fn get_headphone_state(
329 &self)
330 -> unsafe extern "C" fn(headphone: *mut c_int,
331 headsetmic: *mut c_int,
332 changeCallback: Option<unsafe extern "C" fn(headphone: c_int, mic: c_int)>) {
333 self.0.getHeadphoneState.expect("getHeadphoneState")
334 }
335
336 fn set_outputs_active(&self) -> unsafe extern "C" fn(headphone: c_int, speaker: c_int) {
337 self.0.setOutputsActive.expect("setOutputsActive")
338 }
339
340 fn remove_source(&self) -> unsafe extern "C" fn(source: *mut SoundSource) -> c_int {
341 self.0.removeSource.expect("removeSource")
342 }
343 }
344
345
346 pub trait Api {
347 fn channel(&self) -> &'static playdate_sound_channel { sys::api!(sound.channel) }
348 fn fileplayer(&self) -> &'static playdate_sound_fileplayer { sys::api!(sound.fileplayer) }
349 fn sample(&self) -> &'static playdate_sound_sample { sys::api!(sound.sample) }
350 fn sampleplayer(&self) -> &'static playdate_sound_sampleplayer { sys::api!(sound.sampleplayer) }
351 fn synth(&self) -> &'static playdate_sound_synth { sys::api!(sound.synth) }
352 fn sequence(&self) -> &'static playdate_sound_sequence { sys::api!(sound.sequence) }
353 fn effect(&self) -> &'static playdate_sound_effect { sys::api!(sound.effect) }
354 fn lfo(&self) -> &'static playdate_sound_lfo { sys::api!(sound.lfo) }
355 fn envelope(&self) -> &'static playdate_sound_envelope { sys::api!(sound.envelope) }
356 fn source(&self) -> &'static playdate_sound_source { sys::api!(sound.source) }
357 fn control_signal(&self) -> &'static playdate_control_signal { sys::api!(sound.controlsignal) }
358 fn track(&self) -> &'static playdate_sound_track { sys::api!(sound.track) }
359 fn instrument(&self) -> &'static playdate_sound_instrument { sys::api!(sound.instrument) }
360 fn signal(&self) -> &'static playdate_sound_signal { sys::api!(sound.signal) }
361
362 #[doc(alias = "sys::ffi::playdate_sound::getCurrentTime")]
364 fn get_current_time(&self) -> unsafe extern "C" fn() -> u32 { *sys::api!(sound.getCurrentTime) }
365
366 #[doc(alias = "sys::ffi::playdate_sound::addSource")]
368 fn add_source(
369 &self)
370 -> unsafe extern "C" fn(callback: AudioSourceFunction,
371 context: *mut c_void,
372 stereo: c_int) -> *mut SoundSource {
373 *sys::api!(sound.addSource)
374 }
375
376 #[doc(alias = "sys::ffi::playdate_sound::getDefaultChannel")]
378 fn get_default_channel(&self) -> unsafe extern "C" fn() -> *mut SoundChannel {
379 *sys::api!(sound.getDefaultChannel)
380 }
381
382 #[doc(alias = "sys::ffi::playdate_sound::addChannel")]
384 fn add_channel(&self) -> unsafe extern "C" fn(channel: *mut SoundChannel) -> c_int {
385 *sys::api!(sound.addChannel)
386 }
387
388 #[doc(alias = "sys::ffi::playdate_sound::removeChannel")]
390 fn remove_channel(&self) -> unsafe extern "C" fn(channel: *mut SoundChannel) -> c_int {
391 *sys::api!(sound.removeChannel)
392 }
393
394 #[doc(alias = "sys::ffi::playdate_sound::setMicCallback")]
396 fn set_mic_callback(
397 &self)
398 -> unsafe extern "C" fn(callback: RecordCallback, context: *mut c_void, source: MicSource) -> c_int {
399 *sys::api!(sound.setMicCallback)
400 }
401
402 #[doc(alias = "sys::ffi::playdate_sound::getHeadphoneState")]
404 fn get_headphone_state(
405 &self)
406 -> unsafe extern "C" fn(headphone: *mut c_int,
407 headsetmic: *mut c_int,
408 changeCallback: Option<unsafe extern "C" fn(headphone: c_int, mic: c_int)>) {
409 *sys::api!(sound.getHeadphoneState)
410 }
411
412 #[doc(alias = "sys::ffi::playdate_sound::setOutputsActive")]
414 fn set_outputs_active(&self) -> unsafe extern "C" fn(headphone: c_int, speaker: c_int) {
415 *sys::api!(sound.setOutputsActive)
416 }
417
418 #[doc(alias = "sys::ffi::playdate_sound::removeSource")]
420 fn remove_source(&self) -> unsafe extern "C" fn(source: *mut SoundSource) -> c_int {
421 *sys::api!(sound.removeSource)
422 }
423 }
424}