1use crate::ffi;
12use std::fmt;
13
14#[repr(C)]
19pub struct AudioBuffer {
20 pub number_channels: u32,
22 pub data_bytes_size: u32,
24 data_ptr: *mut std::ffi::c_void,
25}
26
27impl PartialEq for AudioBuffer {
28 fn eq(&self, other: &Self) -> bool {
29 self.number_channels == other.number_channels
30 && self.data_bytes_size == other.data_bytes_size
31 && self.data_ptr == other.data_ptr
32 }
33}
34
35impl Eq for AudioBuffer {}
36
37impl std::hash::Hash for AudioBuffer {
38 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
39 self.number_channels.hash(state);
40 self.data_bytes_size.hash(state);
41 self.data_ptr.hash(state);
42 }
43}
44
45impl fmt::Display for AudioBuffer {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(
48 f,
49 "AudioBuffer({} channels, {} bytes)",
50 self.number_channels, self.data_bytes_size
51 )
52 }
53}
54
55impl AudioBuffer {
56 #[must_use]
58 pub fn data(&self) -> &[u8] {
59 if self.data_ptr.is_null() || self.data_bytes_size == 0 {
60 &[]
61 } else {
62 unsafe {
63 std::slice::from_raw_parts(
64 self.data_ptr as *const u8,
65 self.data_bytes_size as usize,
66 )
67 }
68 }
69 }
70
71 pub fn data_mut(&mut self) -> &mut [u8] {
73 if self.data_ptr.is_null() || self.data_bytes_size == 0 {
74 &mut []
75 } else {
76 unsafe {
77 std::slice::from_raw_parts_mut(
78 self.data_ptr.cast::<u8>(),
79 self.data_bytes_size as usize,
80 )
81 }
82 }
83 }
84
85 #[must_use]
87 pub const fn data_byte_size(&self) -> usize {
88 self.data_bytes_size as usize
89 }
90}
91
92pub struct AudioBufferRef<'a> {
94 buffer: &'a AudioBuffer,
95}
96
97impl AudioBufferRef<'_> {
98 #[must_use]
100 pub const fn data_byte_size(&self) -> usize {
101 self.buffer.data_byte_size()
102 }
103
104 #[must_use]
106 pub fn data(&self) -> &[u8] {
107 self.buffer.data()
108 }
109}
110
111impl std::fmt::Debug for AudioBufferRef<'_> {
112 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113 f.debug_struct("AudioBufferRef")
114 .field("channels", &self.buffer.number_channels)
115 .field("data_bytes", &self.buffer.data_bytes_size)
116 .finish()
117 }
118}
119
120impl std::fmt::Debug for AudioBuffer {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 f.debug_struct("AudioBuffer")
123 .field("number_channels", &self.number_channels)
124 .field("data_bytes_size", &self.data_bytes_size)
125 .finish_non_exhaustive()
126 }
127}
128
129#[repr(C)]
131#[derive(Debug)]
132pub struct AudioBufferListRaw {
133 pub(crate) num_buffers: u32,
134 pub(crate) buffers_ptr: *mut AudioBuffer,
135 pub(crate) buffers_len: usize,
136}
137
138pub struct AudioBufferList {
143 pub(crate) inner: AudioBufferListRaw,
144 pub(crate) block_buffer_ptr: *mut std::ffi::c_void,
146}
147
148impl AudioBufferList {
149 #[must_use]
151 pub const fn num_buffers(&self) -> usize {
152 self.inner.num_buffers as usize
153 }
154
155 #[must_use]
157 pub fn get(&self, index: usize) -> Option<&AudioBuffer> {
158 if index >= self.num_buffers() {
159 None
160 } else {
161 unsafe { Some(&*self.inner.buffers_ptr.add(index)) }
162 }
163 }
164
165 #[must_use]
167 pub fn buffer(&self, index: usize) -> Option<AudioBufferRef<'_>> {
168 self.get(index).map(|buffer| AudioBufferRef { buffer })
169 }
170
171 pub fn get_mut(&mut self, index: usize) -> Option<&mut AudioBuffer> {
173 if index >= self.num_buffers() {
174 None
175 } else {
176 unsafe { Some(&mut *self.inner.buffers_ptr.add(index)) }
177 }
178 }
179
180 #[must_use]
182 pub const fn iter(&self) -> AudioBufferListIter<'_> {
183 AudioBufferListIter {
184 list: self,
185 index: 0,
186 }
187 }
188}
189
190impl Drop for AudioBufferList {
191 fn drop(&mut self) {
192 if !self.inner.buffers_ptr.is_null() {
198 unsafe {
199 use std::alloc::{GlobalAlloc, Layout, System};
200 let layout = Layout::array::<AudioBuffer>(self.inner.buffers_len)
201 .expect("AudioBufferList layout overflow");
202 System.dealloc(self.inner.buffers_ptr.cast::<u8>(), layout);
203 }
204 }
205 if !self.block_buffer_ptr.is_null() {
207 unsafe {
208 ffi::cm_block_buffer_release(self.block_buffer_ptr);
209 }
210 }
211 }
212}
213
214impl<'a> IntoIterator for &'a AudioBufferList {
215 type Item = &'a AudioBuffer;
216 type IntoIter = AudioBufferListIter<'a>;
217
218 fn into_iter(self) -> Self::IntoIter {
219 self.iter()
220 }
221}
222
223impl fmt::Display for AudioBufferList {
224 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
225 write!(f, "AudioBufferList({} buffers)", self.num_buffers())
226 }
227}
228
229impl fmt::Debug for AudioBufferList {
230 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231 f.debug_struct("AudioBufferList")
232 .field("num_buffers", &self.num_buffers())
233 .finish()
234 }
235}
236
237pub struct AudioBufferListIter<'a> {
239 list: &'a AudioBufferList,
240 index: usize,
241}
242
243impl std::fmt::Debug for AudioBufferListIter<'_> {
244 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
245 f.debug_struct("AudioBufferListIter")
246 .field("total", &self.list.num_buffers())
247 .field(
248 "remaining",
249 &(self.list.num_buffers().saturating_sub(self.index)),
250 )
251 .finish()
252 }
253}
254
255impl<'a> Iterator for AudioBufferListIter<'a> {
256 type Item = &'a AudioBuffer;
257
258 fn next(&mut self) -> Option<Self::Item> {
259 if self.index < self.list.num_buffers() {
260 let buffer = self.list.get(self.index);
261 self.index += 1;
262 buffer
263 } else {
264 None
265 }
266 }
267}