1use crate::base::*;
2use crate::lock::{RwLockReadGuard, RwLockWriteGuard, SpinRwLock};
3use crate::{Error, Format, FramesMut};
4use miniaudio_sys as sys;
5use std::ffi::CString;
6use std::io;
7use std::mem::MaybeUninit;
8use std::ops::{Deref, DerefMut};
9use std::path::Path;
10use std::sync::Arc;
11
12#[repr(transparent)]
13#[derive(Clone)]
14pub struct DecoderConfig(sys::ma_decoder_config);
15
16impl DecoderConfig {
17 #[inline]
18 pub fn new(format: Format, output_channels: u32, output_sample_rate: u32) -> Self {
19 DecoderConfig(unsafe {
20 sys::ma_decoder_config_init(format as _, output_channels as _, output_sample_rate as _)
21 })
22 }
23}
24
25#[repr(transparent)]
26pub struct RawDecoder {
27 inner: sys::ma_decoder,
28}
29
30impl RawDecoder {
31 #[inline]
32 pub fn read_pcm_frames(&mut self, output: &mut FramesMut) -> u64 {
33 assert!(
34 output.format() == self.output_format(),
35 "output and decoder format did not match (output: {:?}, input: {:?}",
36 output.format(),
37 self.output_format()
38 );
39
40 unsafe {
41 sys::ma_decoder_read_pcm_frames(
42 &self.inner as *const _ as *mut _,
43 output.as_mut_ptr() as *mut _,
44 output.frame_count() as u64,
45 )
46 }
47 }
48
49 #[inline]
50 pub fn length_in_pcm_frames(&mut self) -> u64 {
51 unsafe { sys::ma_decoder_get_length_in_pcm_frames(&self.inner as *const _ as *mut _) }
52 }
53
54 #[inline]
55 pub fn seek_to_pcm_frame(&mut self, frame_index: u64) -> Result<(), Error> {
56 Error::from_c_result(unsafe {
57 sys::ma_decoder_seek_to_pcm_frame(&self.inner as *const _ as *mut _, frame_index)
58 })
59 }
60
61 pub fn output_format(&self) -> Format {
62 Format::from_c(self.inner.outputFormat)
63 }
64
65 pub fn output_channels(&self) -> u32 {
66 self.inner.outputChannels as _
67 }
68
69 pub fn output_sample_rate(&self) -> u32 {
70 self.inner.outputSampleRate as _
71 }
72}
73
74impl Drop for RawDecoder {
75 fn drop(&mut self) {
76 Error::from_c_result(unsafe { sys::ma_decoder_uninit(&mut self.inner) })
77 .expect("failed to uninit decoder");
78 }
79}
80
81pub struct SyncDecoder {
85 inner: Arc<SpinRwLock<RawDecoder>>,
86 has_reader: bool,
87}
88
89impl SyncDecoder {
90 pub fn from_file<P: AsRef<Path>>(
93 file: P,
94 config: Option<&DecoderConfig>,
95 ) -> Result<Self, Error> {
96 let decoder = Arc::new(SpinRwLock::new(MaybeUninit::<RawDecoder>::uninit()));
97
98 let filename = file
99 .as_ref()
100 .to_str()
101 .ok_or(Error::InvalidFile)
102 .and_then(|s| CString::new(s.to_string()).map_err(|_err| Error::InvalidFile))?;
103
104 let result = unsafe {
105 sys::ma_decoder_init_file(
106 filename.as_ptr() as *const _,
107 config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
108 Arc::deref(&decoder).as_ptr() as *mut _,
109 )
110 };
111
112 map_result!(
113 result,
114 SyncDecoder {
115 inner: unsafe { std::mem::transmute(decoder) },
116 has_reader: false,
117 }
118 )
119 }
120
121 pub fn from_memory<M: Into<Vec<u8>>>(
122 data: M,
123 config: Option<&DecoderConfig>,
124 ) -> Result<Self, Error> {
125 Self::from_read(std::io::Cursor::new(data.into()), config)
126 }
127
128 pub fn from_read<T: 'static + SeekRead>(
129 reader: T,
130 config: Option<&DecoderConfig>,
131 ) -> Result<Self, Error> {
132 Self::from_boxed_read(Box::new(reader), config)
133 }
134
135 pub fn from_boxed_read(
136 reader: Box<dyn SeekRead>,
137 config: Option<&DecoderConfig>,
138 ) -> Result<Self, Error> {
139 let decoder = Arc::new(SpinRwLock::new(MaybeUninit::<RawDecoder>::uninit()));
140
141 let user_data = Box::new(reader);
142
143 let result = unsafe {
144 sys::ma_decoder_init(
145 Some(decoder_read_with_reader),
146 Some(decoder_seek_with_reader),
147 Box::into_raw(user_data) as *mut _,
148 config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
149 Arc::deref(&decoder).as_ptr() as *mut _,
150 )
151 };
152
153 map_result!(
154 result,
155 SyncDecoder {
156 inner: unsafe { std::mem::transmute(decoder) },
157 has_reader: true,
158 }
159 )
160 }
161
162 #[inline]
165 pub fn read_pcm_frames(&self, output: &mut FramesMut) -> u64 {
166 self.inner.write().read_pcm_frames(output)
167 }
168
169 #[inline]
172 pub fn try_read_pcm_frames(&self, output: &mut FramesMut) -> u64 {
173 if let Some(ref mut locked) = self.inner.try_write() {
174 locked.read_pcm_frames(output)
175 } else {
176 0
177 }
178 }
179
180 #[inline]
181 pub fn seek_to_pcm_frame(&self, frame_index: u64) -> Result<(), Error> {
182 self.inner.write().seek_to_pcm_frame(frame_index)
183 }
184
185 #[inline]
186 pub fn length_in_pcm_frames(&self) -> u64 {
187 self.inner.write().length_in_pcm_frames()
188 }
189
190 #[inline]
191 pub fn output_format(&self) -> Format {
192 self.inner.read().output_format()
193 }
194
195 #[inline]
196 pub fn output_channels(&self) -> u32 {
197 self.inner.read().output_channels()
198 }
199
200 #[inline]
201 pub fn output_sample_rate(&self) -> u32 {
202 self.inner.read().output_sample_rate()
203 }
204
205 #[inline]
206 pub fn write(&self) -> RwLockWriteGuard<'_, RawDecoder> {
207 self.inner.write()
208 }
209
210 #[inline]
211 pub fn read(&self) -> RwLockReadGuard<'_, RawDecoder> {
212 self.inner.read()
213 }
214
215 #[inline]
216 pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, RawDecoder>> {
217 self.inner.try_write()
218 }
219
220 #[inline]
221 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, RawDecoder>> {
222 self.inner.try_read()
223 }
224}
225
226impl Clone for SyncDecoder {
227 fn clone(&self) -> SyncDecoder {
228 SyncDecoder {
229 inner: Arc::clone(&self.inner),
230 has_reader: self.has_reader,
231 }
232 }
233}
234
235impl Drop for SyncDecoder {
236 fn drop(&mut self) {
237 if self.has_reader {
238 if let Some(inner) = Arc::get_mut(&mut self.inner) {
239 let _reader: Box<Box<dyn SeekRead>> =
241 unsafe { Box::from_raw((*inner.as_ptr()).inner.pUserData as *mut _) };
242 unsafe { (*inner.as_ptr()).inner.pUserData = std::ptr::null_mut() };
243 self.has_reader = false;
244 }
245 }
246 }
247}
248
249unsafe impl Send for SyncDecoder {}
250unsafe impl Sync for SyncDecoder {}
251
252pub struct Decoder {
253 inner: Box<RawDecoder>,
254 has_reader: bool,
255}
256
257impl Decoder {
258 pub fn from_file<P: AsRef<Path>>(
261 file: P,
262 config: Option<&DecoderConfig>,
263 ) -> Result<Self, Error> {
264 let decoder = Box::new(MaybeUninit::<RawDecoder>::uninit());
265 let filename = file
266 .as_ref()
267 .to_str()
268 .ok_or(Error::InvalidFile)
269 .and_then(|s| CString::new(s.to_string()).map_err(|_err| Error::InvalidFile))?;
270
271 let result = unsafe {
272 sys::ma_decoder_init_file(
273 filename.as_ptr() as *const _,
274 config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
275 decoder.as_ptr() as *mut _,
276 )
277 };
278
279 map_result!(
280 result,
281 Decoder {
282 inner: unsafe { std::mem::transmute(decoder) },
283 has_reader: false,
284 }
285 )
286 }
287
288 pub fn from_memory<M: Into<Vec<u8>>>(
289 data: M,
290 config: Option<&DecoderConfig>,
291 ) -> Result<Self, Error> {
292 Self::from_read(std::io::Cursor::new(data.into()), config)
293 }
294
295 pub fn from_read<T: 'static + SeekRead>(
296 reader: T,
297 config: Option<&DecoderConfig>,
298 ) -> Result<Self, Error> {
299 Self::from_boxed_read(Box::new(reader), config)
300 }
301
302 pub fn from_boxed_read(
303 reader: Box<dyn SeekRead>,
304 config: Option<&DecoderConfig>,
305 ) -> Result<Self, Error> {
306 let decoder = Box::new(MaybeUninit::<RawDecoder>::uninit());
307 let user_data = Box::new(reader);
308
309 let result = unsafe {
310 sys::ma_decoder_init(
311 Some(decoder_read_with_reader),
312 Some(decoder_seek_with_reader),
313 Box::into_raw(user_data) as *mut _,
314 config.map(|c| &c.0 as *const _).unwrap_or(std::ptr::null()),
315 decoder.as_ptr() as *mut _,
316 )
317 };
318
319 map_result!(
320 result,
321 Decoder {
322 inner: unsafe { std::mem::transmute(decoder) },
323 has_reader: true,
324 }
325 )
326 }
327}
328
329pub trait SeekRead: io::Read + io::Seek {}
330
331impl<T> SeekRead for T where T: io::Read + io::Seek {}
334
335unsafe extern "C" fn decoder_read_with_reader(
336 decoder: *mut sys::ma_decoder,
337 buffer_out: *mut std::ffi::c_void,
338 bytes_to_read: usize,
339) -> usize {
340 if decoder.is_null() {
341 return 0;
342 }
343
344 let reader: &mut Box<dyn SeekRead> = &mut *((*decoder).pUserData as *mut _);
345 let buffer = std::slice::from_raw_parts_mut(buffer_out as _, bytes_to_read);
346
347 reader.read(buffer).ok().unwrap_or(0)
348}
349
350unsafe extern "C" fn decoder_seek_with_reader(
351 decoder: *mut sys::ma_decoder,
352 byte_offset: std::os::raw::c_int,
353 origin: sys::ma_seek_origin,
354) -> sys::ma_bool32 {
355 if decoder.is_null() {
356 return to_bool32(false);
357 }
358
359 let reader: &mut Box<dyn SeekRead> = &mut *((*decoder).pUserData as *mut _);
360 let pos = match origin {
361 sys::ma_seek_origin_start => io::SeekFrom::Start(byte_offset as _),
362 sys::ma_seek_origin_current => io::SeekFrom::Current(byte_offset as _),
363 sys::ma_seek_origin_end => io::SeekFrom::End(byte_offset as _),
364
365 _ => unreachable!("unknown seek origin"),
368 };
369
370 to_bool32(reader.seek(pos).is_ok())
371}
372
373impl Deref for Decoder {
374 type Target = RawDecoder;
375
376 fn deref(&self) -> &Self::Target {
377 &self.inner
378 }
379}
380
381impl DerefMut for Decoder {
382 fn deref_mut(&mut self) -> &mut Self::Target {
383 &mut self.inner
384 }
385}
386
387impl Drop for Decoder {
388 fn drop(&mut self) {
389 if self.has_reader {
390 let _reader: Box<Box<dyn SeekRead>> =
392 unsafe { Box::from_raw(self.inner.inner.pUserData as *mut _) };
393 self.has_reader = false;
394 self.inner.inner.pUserData = std::ptr::null_mut();
395 }
396 }
397}
398
399unsafe impl Send for Decoder {}
400unsafe impl Sync for Decoder {}