1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use std::{mem, slice};
4
5use 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)]
11pub 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
150unsafe impl TransparentType for AudioChannelPosition {
151 type GlibType = ffi::GstAudioChannelPosition;
152}
153
154#[doc(hidden)]
155impl 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)]
165impl 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
174impl 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
181impl glib::value::ValueType for AudioChannelPosition {
182 type Type = Self;
183}
184
185unsafe 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
195impl 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
211impl 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
219impl 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")]
338pub 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")]
369pub 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")]
402pub 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