playdate_sound/
source.rs

1//! Playdate sound-source API
2
3use core::ffi::c_float;
4
5use sys::ffi::sndCallbackProc;
6use sys::ffi::SoundSource as OpaqueSoundSource;
7use sys::traits::AsRaw;
8
9
10#[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
11pub struct SoundSource<Api = api::Default>(*mut OpaqueSoundSource, Api);
12
13impl<Api> AsRaw for SoundSource<Api> {
14	type Type = OpaqueSoundSource;
15	unsafe fn as_raw(&self) -> *mut Self::Type { self.0 }
16}
17
18impl<Api: Default> From<*mut OpaqueSoundSource> for SoundSource<Api> {
19	fn from(ptr: *mut OpaqueSoundSource) -> Self { Self(ptr, Default::default()) }
20}
21
22impl<Api: api::Api> SoundSource<Api> {
23	pub fn from_with(api: Api, ptr: *mut OpaqueSoundSource) -> Self { Self(ptr, api) }
24
25	/// Returns `true` if the source is currently playing.
26	///
27	/// Equivalent to [`sys::ffi::playdate_sound_source::isPlaying`]
28	#[doc(alias = "sys::ffi::playdate_sound_source::isPlaying")]
29	pub fn is_playing(&self) -> bool {
30		let f = self.1.is_playing();
31		unsafe { f(self.0) == 1 }
32	}
33
34	/// Gets the playback volume (`0.0` - `1.0`) for `left` and `right` channels of the source.
35	///
36	/// Equivalent to [`sys::ffi::playdate_sound_source::getVolume`]
37	#[doc(alias = "sys::ffi::playdate_sound_source::getVolume")]
38	pub fn get_volume(&self) -> (c_float, c_float) {
39		let mut l = 0.;
40		let mut r = 0.;
41		let f = self.1.get_volume();
42		unsafe { f(self.0, &mut l, &mut r) };
43		(l, r)
44	}
45
46	/// Sets the playback volume (`0.0` - `1.0`) for `left` and `right` channels of the source.
47	///
48	/// Equivalent to [`sys::ffi::playdate_sound_source::setVolume`]
49	#[doc(alias = "sys::ffi::playdate_sound_source::setVolume")]
50	pub fn set_volume(&self, left: c_float, right: c_float) {
51		let f = self.1.set_volume();
52		unsafe { f(self.0, left, right) }
53	}
54
55
56	/// Equivalent to [`sys::ffi::playdate_sound_source::setFinishCallback`]
57	#[doc(alias = "sys::ffi::playdate_sound_source::setFinishCallback")]
58	pub fn set_finish_callback_raw(&self, callback: sndCallbackProc) {
59		let f = self.1.set_finish_callback();
60		// TODO: use userdata
61		unsafe { f(self.0, callback, core::ptr::null_mut()) }
62	}
63}
64
65
66pub mod api {
67	use core::ffi::c_void;
68	use core::ffi::c_float;
69	use core::ptr::NonNull;
70
71	use sys::ffi::SoundSource;
72	use sys::ffi::sndCallbackProc;
73	use sys::ffi::playdate_sound_source;
74
75	/// Default sound source api end-point, ZST.
76	///
77	/// All calls approximately costs ~4 derefs.
78	#[derive(Debug, Clone, Copy, core::default::Default)]
79	pub struct Default;
80	impl Api for Default {}
81
82
83	/// Cached sound source api end-point.
84	///
85	/// Stores one reference, so size on stack is eq `usize`.
86	///
87	/// All calls approximately costs ~1 deref.
88	#[derive(Clone, Copy)]
89	#[cfg_attr(feature = "bindings-derive-debug", derive(Debug))]
90	pub struct Cache(&'static playdate_sound_source);
91
92	impl core::default::Default for Cache {
93		fn default() -> Self { Self(sys::api!(sound.source)) }
94	}
95
96	impl From<*const playdate_sound_source> for Cache {
97		#[inline(always)]
98		fn from(ptr: *const playdate_sound_source) -> Self { Self(unsafe { ptr.as_ref() }.expect("snd.src")) }
99	}
100
101	impl From<&'static playdate_sound_source> for Cache {
102		#[inline(always)]
103		fn from(r: &'static playdate_sound_source) -> Self { Self(r) }
104	}
105
106	impl From<NonNull<playdate_sound_source>> for Cache {
107		#[inline(always)]
108		fn from(ptr: NonNull<playdate_sound_source>) -> Self { Self(unsafe { ptr.as_ref() }) }
109	}
110
111	impl From<&'_ NonNull<playdate_sound_source>> for Cache {
112		#[inline(always)]
113		fn from(ptr: &NonNull<playdate_sound_source>) -> Self { Self(unsafe { ptr.as_ref() }) }
114	}
115
116
117	impl Api for Cache {
118		#[inline(always)]
119		fn set_volume(&self) -> unsafe extern "C" fn(c: *mut SoundSource, lvol: c_float, rvol: c_float) {
120			self.0.setVolume.expect("setVolume")
121		}
122
123		#[inline(always)]
124		fn get_volume(&self) -> unsafe extern "C" fn(c: *mut SoundSource, outl: *mut c_float, outr: *mut c_float) {
125			self.0.getVolume.expect("getVolume")
126		}
127
128		#[inline(always)]
129		fn is_playing(&self) -> unsafe extern "C" fn(c: *mut SoundSource) -> core::ffi::c_int {
130			self.0.isPlaying.expect("isPlaying")
131		}
132
133		#[inline(always)]
134		fn set_finish_callback(
135			&self)
136			-> unsafe extern "C" fn(c: *mut SoundSource, callback: sndCallbackProc, userdata: *mut c_void) {
137			self.0.setFinishCallback.expect("setFinishCallback")
138		}
139	}
140
141
142	pub trait Api {
143		/// Returns [`sys::ffi::playdate_sound_source::setVolume`]
144		#[doc(alias = "sys::ffi::playdate_sound_source::setVolume")]
145		#[inline(always)]
146		fn set_volume(&self) -> unsafe extern "C" fn(c: *mut SoundSource, lvol: c_float, rvol: c_float) {
147			*sys::api!(sound.source.setVolume)
148		}
149
150		/// Returns [`sys::ffi::playdate_sound_source::getVolume`]
151		#[doc(alias = "sys::ffi::playdate_sound_source::getVolume")]
152		#[inline(always)]
153		fn get_volume(&self) -> unsafe extern "C" fn(c: *mut SoundSource, outl: *mut c_float, outr: *mut c_float) {
154			*sys::api!(sound.source.getVolume)
155		}
156
157		/// Returns [`sys::ffi::playdate_sound_source::isPlaying`]
158		#[doc(alias = "sys::ffi::playdate_sound_source::isPlaying")]
159		#[inline(always)]
160		fn is_playing(&self) -> unsafe extern "C" fn(c: *mut SoundSource) -> core::ffi::c_int {
161			*sys::api!(sound.source.isPlaying)
162		}
163
164		/// Returns [`sys::ffi::playdate_sound_source::setFinishCallback`]
165		#[doc(alias = "sys::ffi::playdate_sound_source::setFinishCallback")]
166		#[inline(always)]
167		fn set_finish_callback(
168			&self)
169			-> unsafe extern "C" fn(c: *mut SoundSource, callback: sndCallbackProc, userdata: *mut c_void) {
170			*sys::api!(sound.source.setFinishCallback)
171		}
172	}
173}