screencapturekit/cm/
audio.rs1use super::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 pub fn data(&self) -> &[u8] {
58 if self.data_ptr.is_null() || self.data_bytes_size == 0 {
59 &[]
60 } else {
61 unsafe {
62 std::slice::from_raw_parts(
63 self.data_ptr as *const u8,
64 self.data_bytes_size as usize,
65 )
66 }
67 }
68 }
69
70 pub fn data_mut(&mut self) -> &mut [u8] {
82 if self.data_ptr.is_null() || self.data_bytes_size == 0 {
83 &mut []
84 } else {
85 unsafe {
86 std::slice::from_raw_parts_mut(
87 self.data_ptr.cast::<u8>(),
88 self.data_bytes_size as usize,
89 )
90 }
91 }
92 }
93
94 pub fn data_byte_size(&self) -> usize {
96 self.data_bytes_size as usize
97 }
98}
99
100pub struct AudioBufferRef<'a> {
102 buffer: &'a AudioBuffer,
103}
104
105impl<'a> AudioBufferRef<'a> {
106 pub fn data_byte_size(&self) -> usize {
108 self.buffer.data_byte_size()
109 }
110
111 pub fn data(&self) -> &'a [u8] {
118 self.buffer.data()
119 }
120}
121
122impl std::fmt::Debug for AudioBufferRef<'_> {
123 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124 f.debug_struct("AudioBufferRef")
125 .field("channels", &self.buffer.number_channels)
126 .field("data_bytes", &self.buffer.data_bytes_size)
127 .finish()
128 }
129}
130
131impl std::fmt::Debug for AudioBuffer {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 f.debug_struct("AudioBuffer")
134 .field("number_channels", &self.number_channels)
135 .field("data_bytes_size", &self.data_bytes_size)
136 .finish_non_exhaustive()
137 }
138}
139
140#[repr(C)]
142#[derive(Debug)]
143pub struct AudioBufferListRaw {
144 pub(crate) num_buffers: u32,
145 pub(crate) buffers_ptr: *mut AudioBuffer,
146 pub(crate) buffers_len: usize,
147}
148
149pub struct AudioBufferList {
154 pub(crate) inner: AudioBufferListRaw,
155 pub(crate) block_buffer_ptr: *mut std::ffi::c_void,
157}
158
159impl AudioBufferList {
160 pub fn num_buffers(&self) -> usize {
162 self.inner.num_buffers as usize
163 }
164
165 pub fn get(&self, index: usize) -> Option<&AudioBuffer> {
167 if index >= self.num_buffers() {
168 None
169 } else {
170 unsafe { Some(&*self.inner.buffers_ptr.add(index)) }
171 }
172 }
173
174 pub fn buffer(&self, index: usize) -> Option<AudioBufferRef<'_>> {
176 self.get(index).map(|buffer| AudioBufferRef { buffer })
177 }
178
179 pub fn get_mut(&mut self, index: usize) -> Option<&mut AudioBuffer> {
181 if index >= self.num_buffers() {
182 None
183 } else {
184 unsafe { Some(&mut *self.inner.buffers_ptr.add(index)) }
185 }
186 }
187
188 pub fn iter(&self) -> AudioBufferListIter<'_> {
190 AudioBufferListIter {
191 list: self,
192 index: 0,
193 }
194 }
195}
196
197impl Drop for AudioBufferList {
198 fn drop(&mut self) {
199 if !self.inner.buffers_ptr.is_null() {
205 unsafe {
206 use std::alloc::{GlobalAlloc, Layout, System};
207 let layout = Layout::array::<AudioBuffer>(self.inner.buffers_len)
208 .expect("AudioBufferList layout overflow");
209 System.dealloc(self.inner.buffers_ptr.cast::<u8>(), layout);
210 }
211 }
212 if !self.block_buffer_ptr.is_null() {
214 unsafe {
215 ffi::cm_block_buffer_release(self.block_buffer_ptr);
216 }
217 }
218 }
219}
220
221impl<'a> IntoIterator for &'a AudioBufferList {
222 type Item = &'a AudioBuffer;
223 type IntoIter = AudioBufferListIter<'a>;
224
225 fn into_iter(self) -> Self::IntoIter {
226 self.iter()
227 }
228}
229
230impl fmt::Display for AudioBufferList {
231 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
232 write!(f, "AudioBufferList({} buffers)", self.num_buffers())
233 }
234}
235
236impl fmt::Debug for AudioBufferList {
237 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238 f.debug_struct("AudioBufferList")
239 .field("num_buffers", &self.num_buffers())
240 .finish()
241 }
242}
243
244pub struct AudioBufferListIter<'a> {
246 list: &'a AudioBufferList,
247 index: usize,
248}
249
250impl std::fmt::Debug for AudioBufferListIter<'_> {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 f.debug_struct("AudioBufferListIter")
253 .field("total", &self.list.num_buffers())
254 .field(
255 "remaining",
256 &(self.list.num_buffers().saturating_sub(self.index)),
257 )
258 .finish()
259 }
260}
261
262impl<'a> Iterator for AudioBufferListIter<'a> {
263 type Item = &'a AudioBuffer;
264
265 fn next(&mut self) -> Option<Self::Item> {
266 if self.index < self.list.num_buffers() {
267 let buffer = self.list.get(self.index);
268 self.index += 1;
269 buffer
270 } else {
271 None
272 }
273 }
274}