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() {
186 unsafe {
187 Vec::from_raw_parts(
188 self.inner.buffers_ptr,
189 self.inner.buffers_len,
190 self.inner.buffers_len,
191 );
192 }
193 }
194 if !self.block_buffer_ptr.is_null() {
196 unsafe {
197 ffi::cm_block_buffer_release(self.block_buffer_ptr);
198 }
199 }
200 }
201}
202
203impl<'a> IntoIterator for &'a AudioBufferList {
204 type Item = &'a AudioBuffer;
205 type IntoIter = AudioBufferListIter<'a>;
206
207 fn into_iter(self) -> Self::IntoIter {
208 self.iter()
209 }
210}
211
212impl fmt::Display for AudioBufferList {
213 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(f, "AudioBufferList({} buffers)", self.num_buffers())
215 }
216}
217
218impl fmt::Debug for AudioBufferList {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 f.debug_struct("AudioBufferList")
221 .field("num_buffers", &self.num_buffers())
222 .finish()
223 }
224}
225
226pub struct AudioBufferListIter<'a> {
228 list: &'a AudioBufferList,
229 index: usize,
230}
231
232impl std::fmt::Debug for AudioBufferListIter<'_> {
233 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234 f.debug_struct("AudioBufferListIter")
235 .field("total", &self.list.num_buffers())
236 .field(
237 "remaining",
238 &(self.list.num_buffers().saturating_sub(self.index)),
239 )
240 .finish()
241 }
242}
243
244impl<'a> Iterator for AudioBufferListIter<'a> {
245 type Item = &'a AudioBuffer;
246
247 fn next(&mut self) -> Option<Self::Item> {
248 if self.index < self.list.num_buffers() {
249 let buffer = self.list.get(self.index);
250 self.index += 1;
251 buffer
252 } else {
253 None
254 }
255 }
256}