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] {
72 if self.data_ptr.is_null() || self.data_bytes_size == 0 {
73 &mut []
74 } else {
75 unsafe {
76 std::slice::from_raw_parts_mut(
77 self.data_ptr.cast::<u8>(),
78 self.data_bytes_size as usize,
79 )
80 }
81 }
82 }
83
84 pub fn data_byte_size(&self) -> usize {
86 self.data_bytes_size as usize
87 }
88}
89
90pub struct AudioBufferRef<'a> {
92 buffer: &'a AudioBuffer,
93}
94
95impl AudioBufferRef<'_> {
96 pub fn data_byte_size(&self) -> usize {
98 self.buffer.data_byte_size()
99 }
100
101 pub fn data(&self) -> &[u8] {
103 self.buffer.data()
104 }
105}
106
107impl std::fmt::Debug for AudioBufferRef<'_> {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 f.debug_struct("AudioBufferRef")
110 .field("channels", &self.buffer.number_channels)
111 .field("data_bytes", &self.buffer.data_bytes_size)
112 .finish()
113 }
114}
115
116impl std::fmt::Debug for AudioBuffer {
117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118 f.debug_struct("AudioBuffer")
119 .field("number_channels", &self.number_channels)
120 .field("data_bytes_size", &self.data_bytes_size)
121 .finish_non_exhaustive()
122 }
123}
124
125#[repr(C)]
127#[derive(Debug)]
128pub struct AudioBufferListRaw {
129 pub(crate) num_buffers: u32,
130 pub(crate) buffers_ptr: *mut AudioBuffer,
131 pub(crate) buffers_len: usize,
132}
133
134pub struct AudioBufferList {
139 pub(crate) inner: AudioBufferListRaw,
140 pub(crate) block_buffer_ptr: *mut std::ffi::c_void,
142}
143
144impl AudioBufferList {
145 pub fn num_buffers(&self) -> usize {
147 self.inner.num_buffers as usize
148 }
149
150 pub fn get(&self, index: usize) -> Option<&AudioBuffer> {
152 if index >= self.num_buffers() {
153 None
154 } else {
155 unsafe { Some(&*self.inner.buffers_ptr.add(index)) }
156 }
157 }
158
159 pub fn buffer(&self, index: usize) -> Option<AudioBufferRef<'_>> {
161 self.get(index).map(|buffer| AudioBufferRef { buffer })
162 }
163
164 pub fn get_mut(&mut self, index: usize) -> Option<&mut AudioBuffer> {
166 if index >= self.num_buffers() {
167 None
168 } else {
169 unsafe { Some(&mut *self.inner.buffers_ptr.add(index)) }
170 }
171 }
172
173 pub fn iter(&self) -> AudioBufferListIter<'_> {
175 AudioBufferListIter {
176 list: self,
177 index: 0,
178 }
179 }
180}
181
182impl Drop for AudioBufferList {
183 fn drop(&mut self) {
184 if !self.inner.buffers_ptr.is_null() {
190 unsafe {
191 use std::alloc::{GlobalAlloc, Layout, System};
192 let layout = Layout::array::<AudioBuffer>(self.inner.buffers_len)
193 .expect("AudioBufferList layout overflow");
194 System.dealloc(self.inner.buffers_ptr.cast::<u8>(), layout);
195 }
196 }
197 if !self.block_buffer_ptr.is_null() {
199 unsafe {
200 ffi::cm_block_buffer_release(self.block_buffer_ptr);
201 }
202 }
203 }
204}
205
206impl<'a> IntoIterator for &'a AudioBufferList {
207 type Item = &'a AudioBuffer;
208 type IntoIter = AudioBufferListIter<'a>;
209
210 fn into_iter(self) -> Self::IntoIter {
211 self.iter()
212 }
213}
214
215impl fmt::Display for AudioBufferList {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "AudioBufferList({} buffers)", self.num_buffers())
218 }
219}
220
221impl fmt::Debug for AudioBufferList {
222 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223 f.debug_struct("AudioBufferList")
224 .field("num_buffers", &self.num_buffers())
225 .finish()
226 }
227}
228
229pub struct AudioBufferListIter<'a> {
231 list: &'a AudioBufferList,
232 index: usize,
233}
234
235impl std::fmt::Debug for AudioBufferListIter<'_> {
236 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237 f.debug_struct("AudioBufferListIter")
238 .field("total", &self.list.num_buffers())
239 .field(
240 "remaining",
241 &(self.list.num_buffers().saturating_sub(self.index)),
242 )
243 .finish()
244 }
245}
246
247impl<'a> Iterator for AudioBufferListIter<'a> {
248 type Item = &'a AudioBuffer;
249
250 fn next(&mut self) -> Option<Self::Item> {
251 if self.index < self.list.num_buffers() {
252 let buffer = self.list.get(self.index);
253 self.index += 1;
254 buffer
255 } else {
256 None
257 }
258 }
259}