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,
135 pub(crate) buffers_ptr: *mut AudioBuffer,
137 pub(crate) buffers_len: usize,
139}
140
141pub struct AudioBufferList {
146 pub(crate) inner: AudioBufferListRaw,
148 pub(crate) block_buffer_ptr: *mut std::ffi::c_void,
150}
151
152impl AudioBufferList {
153 #[must_use]
155 pub const fn num_buffers(&self) -> usize {
156 self.inner.num_buffers as usize
157 }
158
159 #[must_use]
161 pub fn get(&self, index: usize) -> Option<&AudioBuffer> {
162 if index >= self.num_buffers() {
163 None
164 } else {
165 unsafe { Some(&*self.inner.buffers_ptr.add(index)) }
166 }
167 }
168
169 #[must_use]
171 pub fn buffer(&self, index: usize) -> Option<AudioBufferRef<'_>> {
172 self.get(index).map(|buffer| AudioBufferRef { buffer })
173 }
174
175 pub fn get_mut(&mut self, index: usize) -> Option<&mut AudioBuffer> {
177 if index >= self.num_buffers() {
178 None
179 } else {
180 unsafe { Some(&mut *self.inner.buffers_ptr.add(index)) }
181 }
182 }
183
184 #[must_use]
186 pub const fn iter(&self) -> AudioBufferListIter<'_> {
187 AudioBufferListIter {
188 list: self,
189 index: 0,
190 }
191 }
192}
193
194impl Drop for AudioBufferList {
195 fn drop(&mut self) {
196 if !self.inner.buffers_ptr.is_null() {
202 unsafe {
203 use std::alloc::{GlobalAlloc, Layout, System};
204 let layout = Layout::array::<AudioBuffer>(self.inner.buffers_len)
205 .expect("AudioBufferList layout overflow");
206 System.dealloc(self.inner.buffers_ptr.cast::<u8>(), layout);
207 }
208 }
209 if !self.block_buffer_ptr.is_null() {
211 unsafe {
212 ffi::cm_block_buffer_release(self.block_buffer_ptr);
213 }
214 }
215 }
216}
217
218impl<'a> IntoIterator for &'a AudioBufferList {
219 type Item = &'a AudioBuffer;
220 type IntoIter = AudioBufferListIter<'a>;
221
222 fn into_iter(self) -> Self::IntoIter {
223 self.iter()
224 }
225}
226
227impl fmt::Display for AudioBufferList {
228 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(f, "AudioBufferList({} buffers)", self.num_buffers())
230 }
231}
232
233impl fmt::Debug for AudioBufferList {
234 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 f.debug_struct("AudioBufferList")
236 .field("num_buffers", &self.num_buffers())
237 .finish()
238 }
239}
240
241pub struct AudioBufferListIter<'a> {
243 list: &'a AudioBufferList,
244 index: usize,
245}
246
247impl std::fmt::Debug for AudioBufferListIter<'_> {
248 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249 f.debug_struct("AudioBufferListIter")
250 .field("total", &self.list.num_buffers())
251 .field(
252 "remaining",
253 &(self.list.num_buffers().saturating_sub(self.index)),
254 )
255 .finish()
256 }
257}
258
259impl<'a> Iterator for AudioBufferListIter<'a> {
260 type Item = &'a AudioBuffer;
261
262 fn next(&mut self) -> Option<Self::Item> {
263 if self.index < self.list.num_buffers() {
264 let buffer = self.list.get(self.index);
265 self.index += 1;
266 buffer
267 } else {
268 None
269 }
270 }
271}