1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::{mem, slice}; |
4 | |
5 | use glib::{translate::*, value::FromValue, StaticType, ToValue, Type}; |
6 | |
7 | #[derive (Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] |
8 | #[non_exhaustive ] |
9 | #[doc (alias = "GstAudioChannelPosition" )] |
10 | #[repr (i32)] |
11 | pub enum AudioChannelPosition { |
12 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_NONE" )] |
13 | None = ffi::GST_AUDIO_CHANNEL_POSITION_NONE, |
14 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_MONO" )] |
15 | Mono, |
16 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_INVALID" )] |
17 | Invalid, |
18 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT" )] |
19 | FrontLeft, |
20 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT" )] |
21 | FrontRight, |
22 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER" )] |
23 | FrontCenter, |
24 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_LFE1" )] |
25 | Lfe1, |
26 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_REAR_LEFT" )] |
27 | RearLeft, |
28 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT" )] |
29 | RearRight, |
30 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER" )] |
31 | FrontLeftOfCenter, |
32 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER" )] |
33 | FrontRightOfCenter, |
34 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_REAR_CENTER" )] |
35 | RearCenter, |
36 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_LFE2" )] |
37 | Lfe2, |
38 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT" )] |
39 | SideLeft, |
40 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT" )] |
41 | SideRight, |
42 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT" )] |
43 | TopFrontLeft, |
44 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT" )] |
45 | TopFrontRight, |
46 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER" )] |
47 | TopFrontCenter, |
48 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_CENTER" )] |
49 | TopCenter, |
50 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT" )] |
51 | TopRearLeft, |
52 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT" )] |
53 | TopRearRight, |
54 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT" )] |
55 | TopSideLeft, |
56 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT" )] |
57 | TopSideRight, |
58 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER" )] |
59 | TopRearCenter, |
60 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER" )] |
61 | BottomFrontCenter, |
62 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT" )] |
63 | BottomFrontLeft, |
64 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT" )] |
65 | BottomFrontRight, |
66 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT" )] |
67 | WideLeft, |
68 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT" )] |
69 | WideRight, |
70 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT" )] |
71 | SurroundLeft, |
72 | #[doc (alias = "GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT" )] |
73 | SurroundRight = ffi::GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT, |
74 | #[doc (hidden)] |
75 | UnknownChannel28 = 28, |
76 | #[doc (hidden)] |
77 | UnknownChannel29 = 29, |
78 | #[doc (hidden)] |
79 | UnknownChannel30 = 30, |
80 | #[doc (hidden)] |
81 | UnknownChannel31 = 31, |
82 | #[doc (hidden)] |
83 | UnknownChannel32 = 32, |
84 | #[doc (hidden)] |
85 | UnknownChannel33 = 33, |
86 | #[doc (hidden)] |
87 | UnknownChannel34 = 34, |
88 | #[doc (hidden)] |
89 | UnknownChannel35 = 35, |
90 | #[doc (hidden)] |
91 | UnknownChannel36 = 36, |
92 | #[doc (hidden)] |
93 | UnknownChannel37 = 37, |
94 | #[doc (hidden)] |
95 | UnknownChannel38 = 38, |
96 | #[doc (hidden)] |
97 | UnknownChannel39 = 39, |
98 | #[doc (hidden)] |
99 | UnknownChannel40 = 40, |
100 | #[doc (hidden)] |
101 | UnknownChannel41 = 41, |
102 | #[doc (hidden)] |
103 | UnknownChannel42 = 42, |
104 | #[doc (hidden)] |
105 | UnknownChannel43 = 43, |
106 | #[doc (hidden)] |
107 | UnknownChannel44 = 44, |
108 | #[doc (hidden)] |
109 | UnknownChannel45 = 45, |
110 | #[doc (hidden)] |
111 | UnknownChannel46 = 46, |
112 | #[doc (hidden)] |
113 | UnknownChannel47 = 47, |
114 | #[doc (hidden)] |
115 | UnknownChannel48 = 48, |
116 | #[doc (hidden)] |
117 | UnknownChannel49 = 49, |
118 | #[doc (hidden)] |
119 | UnknownChannel50 = 50, |
120 | #[doc (hidden)] |
121 | UnknownChannel51 = 51, |
122 | #[doc (hidden)] |
123 | UnknownChannel52 = 52, |
124 | #[doc (hidden)] |
125 | UnknownChannel53 = 53, |
126 | #[doc (hidden)] |
127 | UnknownChannel54 = 54, |
128 | #[doc (hidden)] |
129 | UnknownChannel55 = 55, |
130 | #[doc (hidden)] |
131 | UnknownChannel56 = 56, |
132 | #[doc (hidden)] |
133 | UnknownChannel57 = 57, |
134 | #[doc (hidden)] |
135 | UnknownChannel58 = 58, |
136 | #[doc (hidden)] |
137 | UnknownChannel59 = 59, |
138 | #[doc (hidden)] |
139 | UnknownChannel60 = 60, |
140 | #[doc (hidden)] |
141 | UnknownChannel61 = 61, |
142 | #[doc (hidden)] |
143 | UnknownChannel62 = 62, |
144 | #[doc (hidden)] |
145 | UnknownChannel63 = 63, |
146 | #[doc (hidden)] |
147 | UnknownChannel64 = 64, |
148 | } |
149 | |
150 | unsafe impl TransparentType for AudioChannelPosition { |
151 | type GlibType = ffi::GstAudioChannelPosition; |
152 | } |
153 | |
154 | #[doc (hidden)] |
155 | impl IntoGlib for AudioChannelPosition { |
156 | type GlibType = ffi::GstAudioChannelPosition; |
157 | |
158 | #[inline ] |
159 | fn into_glib(self) -> ffi::GstAudioChannelPosition { |
160 | self as ffi::GstAudioChannelPosition |
161 | } |
162 | } |
163 | |
164 | #[doc (hidden)] |
165 | impl FromGlib<ffi::GstAudioChannelPosition> for AudioChannelPosition { |
166 | #[inline ] |
167 | unsafe fn from_glib(value: ffi::GstAudioChannelPosition) -> Self { |
168 | skip_assert_initialized!(); |
169 | debug_assert!((ffi::GST_AUDIO_CHANNEL_POSITION_NONE..=64).contains(&value)); |
170 | mem::transmute::<ffi::GstAudioChannelPosition, AudioChannelPosition>(src:value) |
171 | } |
172 | } |
173 | |
174 | impl StaticType for AudioChannelPosition { |
175 | #[inline ] |
176 | fn static_type() -> Type { |
177 | unsafe { from_glib(val:ffi::gst_audio_channel_position_get_type()) } |
178 | } |
179 | } |
180 | |
181 | impl glib::value::ValueType for AudioChannelPosition { |
182 | type Type = Self; |
183 | } |
184 | |
185 | unsafe impl<'a> FromValue<'a> for AudioChannelPosition { |
186 | type Checker = glib::value::GenericValueTypeChecker<Self>; |
187 | |
188 | #[inline ] |
189 | unsafe fn from_value(value: &'a glib::Value) -> Self { |
190 | skip_assert_initialized!(); |
191 | from_glib(val:glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0)) |
192 | } |
193 | } |
194 | |
195 | impl ToValue for AudioChannelPosition { |
196 | #[inline ] |
197 | fn to_value(&self) -> glib::Value { |
198 | let mut value: Value = glib::Value::for_value_type::<Self>(); |
199 | unsafe { |
200 | glib::gobject_ffi::g_value_set_enum(value:value.to_glib_none_mut().0, self.into_glib()); |
201 | } |
202 | value |
203 | } |
204 | |
205 | #[inline ] |
206 | fn value_type(&self) -> glib::Type { |
207 | Self::static_type() |
208 | } |
209 | } |
210 | |
211 | impl From<AudioChannelPosition> for glib::Value { |
212 | #[inline ] |
213 | fn from(v: AudioChannelPosition) -> Self { |
214 | skip_assert_initialized!(); |
215 | ToValue::to_value(&v) |
216 | } |
217 | } |
218 | |
219 | impl AudioChannelPosition { |
220 | pub fn to_mask(self) -> u64 { |
221 | let pos = self.into_glib(); |
222 | if pos < 0 { |
223 | return 0; |
224 | } |
225 | |
226 | 1 << (pos as u32) |
227 | } |
228 | |
229 | #[doc (alias = "gst_audio_channel_positions_to_mask" )] |
230 | pub fn positions_to_mask( |
231 | positions: &[Self], |
232 | force_order: bool, |
233 | ) -> Result<u64, glib::error::BoolError> { |
234 | assert_initialized_main_thread!(); |
235 | |
236 | let len = positions.len(); |
237 | if len > 64 { |
238 | return Err(glib::bool_error!("Invalid number of channels" )); |
239 | } |
240 | |
241 | unsafe { |
242 | let mut mask = mem::MaybeUninit::uninit(); |
243 | let valid: bool = from_glib(ffi::gst_audio_channel_positions_to_mask( |
244 | positions.as_ptr() as *mut _, |
245 | len as i32, |
246 | force_order.into_glib(), |
247 | mask.as_mut_ptr(), |
248 | )); |
249 | if valid { |
250 | Ok(mask.assume_init()) |
251 | } else { |
252 | Err(glib::bool_error!( |
253 | "Couldn't convert channel positions to mask" |
254 | )) |
255 | } |
256 | } |
257 | } |
258 | |
259 | #[doc (alias = "gst_audio_channel_positions_from_mask" )] |
260 | pub fn positions_from_mask(mask: u64, positions: &mut [Self]) -> Result<(), glib::BoolError> { |
261 | assert_initialized_main_thread!(); |
262 | |
263 | if positions.len() > 64 { |
264 | return Err(glib::bool_error!("Invalid number of channels" )); |
265 | } |
266 | |
267 | let len = positions.len(); |
268 | let valid: bool = unsafe { |
269 | from_glib(ffi::gst_audio_channel_positions_from_mask( |
270 | len as i32, |
271 | mask, |
272 | positions.as_mut_ptr() as *mut _, |
273 | )) |
274 | }; |
275 | |
276 | if valid { |
277 | Ok(()) |
278 | } else { |
279 | Err(glib::bool_error!( |
280 | "Couldn't convert channel positions to mask" , |
281 | )) |
282 | } |
283 | } |
284 | |
285 | #[doc (alias = "gst_audio_channel_positions_to_valid_order" )] |
286 | pub fn positions_to_valid_order(positions: &mut [Self]) -> Result<(), glib::BoolError> { |
287 | assert_initialized_main_thread!(); |
288 | |
289 | if positions.len() > 64 { |
290 | return Err(glib::bool_error!("Invalid number of channels" )); |
291 | } |
292 | |
293 | let len = positions.len(); |
294 | let valid: bool = unsafe { |
295 | from_glib(ffi::gst_audio_channel_positions_to_valid_order( |
296 | positions.as_mut_ptr() as *mut _, |
297 | len as i32, |
298 | )) |
299 | }; |
300 | |
301 | if valid { |
302 | Ok(()) |
303 | } else { |
304 | Err(glib::bool_error!( |
305 | "Couldn't convert channel positions to mask" , |
306 | )) |
307 | } |
308 | } |
309 | |
310 | #[doc (alias = "get_fallback_mask" )] |
311 | #[doc (alias = "gst_audio_channel_get_fallback_mask" )] |
312 | pub fn fallback_mask(channels: u32) -> u64 { |
313 | assert_initialized_main_thread!(); |
314 | |
315 | unsafe { ffi::gst_audio_channel_get_fallback_mask(channels as i32) } |
316 | } |
317 | |
318 | #[doc (alias = "gst_audio_check_valid_channel_positions" )] |
319 | pub fn check_valid_channel_positions(positions: &[Self], force_order: bool) -> bool { |
320 | assert_initialized_main_thread!(); |
321 | |
322 | if positions.len() > 64 { |
323 | return false; |
324 | } |
325 | |
326 | let len = positions.len(); |
327 | unsafe { |
328 | from_glib(ffi::gst_audio_check_valid_channel_positions( |
329 | positions.as_ptr() as *mut _, |
330 | len as i32, |
331 | force_order.into_glib(), |
332 | )) |
333 | } |
334 | } |
335 | } |
336 | |
337 | #[doc (alias = "gst_audio_buffer_reorder_channels" )] |
338 | pub fn buffer_reorder_channels( |
339 | buffer: &mut gst::BufferRef, |
340 | format: crate::AudioFormat, |
341 | channels: u32, |
342 | from: &[AudioChannelPosition], |
343 | to: &[AudioChannelPosition], |
344 | ) -> Result<(), glib::BoolError> { |
345 | skip_assert_initialized!(); |
346 | |
347 | if from.len() != to.len() || from.len() > 64 { |
348 | return Err(glib::bool_error!("Invalid number of channels" )); |
349 | } |
350 | |
351 | let valid: bool = unsafe { |
352 | from_glib(val:ffi::gst_audio_buffer_reorder_channels( |
353 | buffer:buffer.as_mut_ptr(), |
354 | format:format.into_glib(), |
355 | channels as i32, |
356 | from:from.as_ptr() as *mut _, |
357 | to:to.as_ptr() as *mut _, |
358 | )) |
359 | }; |
360 | |
361 | if valid { |
362 | Ok(()) |
363 | } else { |
364 | Err(glib::bool_error!("Failed to reorder channels" )) |
365 | } |
366 | } |
367 | |
368 | #[doc (alias = "gst_audio_reorder_channels" )] |
369 | pub fn reorder_channels( |
370 | data: &mut [u8], |
371 | format: crate::AudioFormat, |
372 | channels: u32, |
373 | from: &[AudioChannelPosition], |
374 | to: &[AudioChannelPosition], |
375 | ) -> Result<(), glib::BoolError> { |
376 | assert_initialized_main_thread!(); |
377 | |
378 | if from.len() != to.len() || from.len() > 64 { |
379 | return Err(glib::bool_error!("Invalid number of channels" )); |
380 | } |
381 | |
382 | let valid: bool = unsafe { |
383 | from_glib(val:ffi::gst_audio_reorder_channels( |
384 | data:data.as_mut_ptr() as *mut _, |
385 | size:data.len(), |
386 | format:format.into_glib(), |
387 | channels as i32, |
388 | from:from.as_ptr() as *mut _, |
389 | to:to.as_ptr() as *mut _, |
390 | )) |
391 | }; |
392 | |
393 | if valid { |
394 | Ok(()) |
395 | } else { |
396 | Err(glib::bool_error!("Failed to reorder channels" )) |
397 | } |
398 | } |
399 | |
400 | #[doc (alias = "get_channel_reorder_map" )] |
401 | #[doc (alias = "gst_audio_get_channel_reorder_map" )] |
402 | pub fn channel_reorder_map( |
403 | from: &[AudioChannelPosition], |
404 | to: &[AudioChannelPosition], |
405 | reorder_map: &mut [usize], |
406 | ) -> Result<(), glib::BoolError> { |
407 | assert_initialized_main_thread!(); |
408 | |
409 | if from.len() != to.len() || from.len() != reorder_map.len() || from.len() > 64 { |
410 | return Err(glib::bool_error!("Invalid number of channels" )); |
411 | } |
412 | |
413 | let mut reorder_map_raw = mem::MaybeUninit::<[i32; 64]>::uninit(); |
414 | let valid: bool = unsafe { |
415 | from_glib(ffi::gst_audio_get_channel_reorder_map( |
416 | from.len() as i32, |
417 | from.as_ptr() as *mut _, |
418 | to.as_ptr() as *mut _, |
419 | reorder_map_raw.as_mut_ptr() as *mut i32, |
420 | )) |
421 | }; |
422 | |
423 | if valid { |
424 | let reorder_map_raw = |
425 | unsafe { slice::from_raw_parts(reorder_map_raw.as_ptr() as *const i32, from.len()) }; |
426 | for (d, s) in reorder_map.iter_mut().zip(reorder_map_raw.iter()) { |
427 | *d = *s as usize; |
428 | } |
429 | Ok(()) |
430 | } else { |
431 | Err(glib::bool_error!("Failed to reorder channels" )) |
432 | } |
433 | } |
434 | |