rich_sdl2_rust/audio/
spec.rs1use bitflags::bitflags;
4use std::{
5 ffi::c_void,
6 marker::PhantomData,
7 os::raw::c_int,
8 sync::{Arc, Mutex},
9};
10use typed_builder::TypedBuilder;
11
12use crate::bind;
13
14use super::format::AudioFormat;
15
16#[derive(TypedBuilder)]
18pub struct AudioSpecBuilder<'callback, T: AudioCallback<'callback>> {
19 #[builder(default = 44100)]
20 sample_freq: u32,
21 #[builder(default = AudioFormat::signed32_lsb())]
22 format: AudioFormat,
23 #[builder(default = 2)]
24 channels: u8,
25 #[builder(default = 4096)]
26 samples: u16,
27 #[builder(default, setter(strip_option))]
28 callback: Option<&'callback mut T>,
29}
30
31pub trait AudioCallback<'callback>: FnMut(&mut [u8]) + 'callback {}
33
34pub struct AudioSpec<'callback, T> {
36 raw: bind::SDL_AudioSpec,
37 _phantom: PhantomData<&'callback mut T>,
38}
39
40impl<T> std::fmt::Debug for AudioSpec<'_, T> {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 f.debug_struct("AudioSpec").finish_non_exhaustive()
43 }
44}
45
46impl<'callback, T: AudioCallback<'callback>> AudioSpec<'callback, T> {
47 #[must_use]
49 pub fn new(mut builder: AudioSpecBuilder<'callback, T>) -> Self {
50 Self {
51 raw: bind::SDL_AudioSpec {
52 freq: builder.sample_freq as c_int,
53 format: builder.format.as_raw(),
54 channels: builder.channels,
55 silence: 0,
56 samples: builder.samples,
57 padding: 0,
58 size: 0,
59 callback: builder
60 .callback
61 .as_ref()
62 .map(|_| audio_spec_wrap_handler::<T> as _),
63 userdata: builder
64 .callback
65 .map_or(std::ptr::null_mut(), |callback| (callback as *mut T).cast()),
66 },
67 _phantom: PhantomData,
68 }
69 }
70
71 pub(super) fn raw(&self) -> &bind::SDL_AudioSpec {
72 &self.raw
73 }
74
75 pub(super) fn raw_mut(&mut self) -> &mut bind::SDL_AudioSpec {
76 &mut self.raw
77 }
78}
79
80unsafe extern "C" fn audio_spec_wrap_handler<'callback, T: AudioCallback<'callback>>(
81 userdata: *mut c_void,
82 stream: *mut u8,
83 len: c_int,
84) {
85 if userdata.is_null() {
86 return;
87 }
88 let func = &mut *userdata.cast::<T>();
89 let slice = std::slice::from_raw_parts_mut(stream, len as usize);
90 slice.fill(0);
91 func(slice);
92}
93
94bitflags! {
95 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
97 pub struct FallbackFlag : u32 {
98 const FREQUENCY = 1 << 0;
100 const FORMAT = 1 << 0;
102 const CHANNELS = 1 << 0;
104 const SAMPLES = 1 << 0;
106 }
107}