1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::AudioChannelPosition;
4 
5 use std::mem;
6 
7 use glib::translate::{from_glib, IntoGlib};
8 
9 impl AudioChannelPosition {
to_mask(self) -> u6410     pub fn to_mask(self) -> u64 {
11         let pos = self.into_glib();
12         if pos < 0 {
13             return 0;
14         }
15 
16         1 << (pos as u32)
17     }
18 
19     #[doc(alias = "gst_audio_channel_positions_to_mask")]
positions_to_mask( positions: &[Self], force_order: bool, ) -> Result<u64, glib::error::BoolError>20     pub fn positions_to_mask(
21         positions: &[Self],
22         force_order: bool,
23     ) -> Result<u64, glib::error::BoolError> {
24         assert_initialized_main_thread!();
25 
26         let len = positions.len();
27         if len > 64 {
28             return Err(glib::bool_error!("Invalid number of channels"));
29         }
30 
31         let positions_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
32             if i >= len as usize {
33                 ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
34             } else {
35                 positions[i].into_glib()
36             }
37         });
38 
39         unsafe {
40             let mut mask = mem::MaybeUninit::uninit();
41             let valid: bool = from_glib(ffi::gst_audio_channel_positions_to_mask(
42                 positions_raw.as_ptr() as *mut _,
43                 len as i32,
44                 force_order.into_glib(),
45                 mask.as_mut_ptr(),
46             ));
47             if valid {
48                 Ok(mask.assume_init())
49             } else {
50                 Err(glib::bool_error!(
51                     "Couldn't convert channel positions to mask"
52                 ))
53             }
54         }
55     }
56 
57     #[doc(alias = "gst_audio_channel_positions_from_mask")]
positions_from_mask(mask: u64, positions: &mut [Self]) -> Result<(), glib::BoolError>58     pub fn positions_from_mask(mask: u64, positions: &mut [Self]) -> Result<(), glib::BoolError> {
59         assert_initialized_main_thread!();
60 
61         if positions.len() > 64 {
62             return Err(glib::bool_error!("Invalid number of channels"));
63         }
64 
65         let len = positions.len();
66         let mut positions_raw: [ffi::GstAudioChannelPosition; 64] =
67             [ffi::GST_AUDIO_CHANNEL_POSITION_INVALID; 64];
68         let valid: bool = unsafe {
69             from_glib(ffi::gst_audio_channel_positions_from_mask(
70                 len as i32,
71                 mask,
72                 positions_raw.as_mut_ptr(),
73             ))
74         };
75 
76         if valid {
77             for (d, s) in positions.iter_mut().zip(positions_raw.iter()) {
78                 *d = unsafe { from_glib(*s) };
79             }
80             Ok(())
81         } else {
82             Err(glib::bool_error!(
83                 "Couldn't convert channel positions to mask",
84             ))
85         }
86     }
87 
88     #[doc(alias = "gst_audio_channel_positions_to_valid_order")]
positions_to_valid_order(positions: &mut [Self]) -> Result<(), glib::BoolError>89     pub fn positions_to_valid_order(positions: &mut [Self]) -> Result<(), glib::BoolError> {
90         assert_initialized_main_thread!();
91 
92         if positions.len() > 64 {
93             return Err(glib::bool_error!("Invalid number of channels"));
94         }
95 
96         let len = positions.len();
97         let mut positions_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
98             if i >= len as usize {
99                 ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
100             } else {
101                 positions[i].into_glib()
102             }
103         });
104 
105         let valid: bool = unsafe {
106             from_glib(ffi::gst_audio_channel_positions_to_valid_order(
107                 positions_raw.as_mut_ptr(),
108                 len as i32,
109             ))
110         };
111 
112         if valid {
113             for (d, s) in positions.iter_mut().zip(positions_raw.iter()) {
114                 *d = unsafe { from_glib(*s) };
115             }
116             Ok(())
117         } else {
118             Err(glib::bool_error!(
119                 "Couldn't convert channel positions to mask",
120             ))
121         }
122     }
123 
124     #[doc(alias = "get_fallback_mask")]
125     #[doc(alias = "gst_audio_channel_get_fallback_mask")]
fallback_mask(channels: u32) -> u64126     pub fn fallback_mask(channels: u32) -> u64 {
127         assert_initialized_main_thread!();
128 
129         unsafe { ffi::gst_audio_channel_get_fallback_mask(channels as i32) }
130     }
131 
132     #[doc(alias = "gst_audio_check_valid_channel_positions")]
check_valid_channel_positions(positions: &[Self], force_order: bool) -> bool133     pub fn check_valid_channel_positions(positions: &[Self], force_order: bool) -> bool {
134         assert_initialized_main_thread!();
135 
136         if positions.len() > 64 {
137             return false;
138         }
139 
140         let len = positions.len();
141         let positions_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
142             if i >= len as usize {
143                 ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
144             } else {
145                 positions[i].into_glib()
146             }
147         });
148 
149         unsafe {
150             from_glib(ffi::gst_audio_check_valid_channel_positions(
151                 positions_raw.as_ptr() as *mut _,
152                 len as i32,
153                 force_order.into_glib(),
154             ))
155         }
156     }
157 }
158 
159 #[doc(alias = "gst_audio_buffer_reorder_channels")]
buffer_reorder_channels( buffer: &mut gst::BufferRef, format: crate::AudioFormat, channels: u32, from: &[AudioChannelPosition], to: &[AudioChannelPosition], ) -> Result<(), glib::BoolError>160 pub fn buffer_reorder_channels(
161     buffer: &mut gst::BufferRef,
162     format: crate::AudioFormat,
163     channels: u32,
164     from: &[AudioChannelPosition],
165     to: &[AudioChannelPosition],
166 ) -> Result<(), glib::BoolError> {
167     assert_initialized_main_thread!();
168 
169     if from.len() != to.len() || from.len() > 64 {
170         return Err(glib::bool_error!("Invalid number of channels"));
171     }
172 
173     let from_len = from.len();
174     let to_len = to.len();
175 
176     let from_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
177         if i >= from_len as usize {
178             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
179         } else {
180             from[i].into_glib()
181         }
182     });
183 
184     let to_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
185         if i >= to_len as usize {
186             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
187         } else {
188             to[i].into_glib()
189         }
190     });
191 
192     let valid: bool = unsafe {
193         from_glib(ffi::gst_audio_buffer_reorder_channels(
194             buffer.as_mut_ptr(),
195             format.into_glib(),
196             channels as i32,
197             from_raw.as_ptr() as *mut _,
198             to_raw.as_ptr() as *mut _,
199         ))
200     };
201 
202     if valid {
203         Ok(())
204     } else {
205         Err(glib::bool_error!("Failed to reorder channels"))
206     }
207 }
208 
209 #[doc(alias = "gst_audio_reorder_channels")]
reorder_channels( data: &mut [u8], format: crate::AudioFormat, channels: u32, from: &[AudioChannelPosition], to: &[AudioChannelPosition], ) -> Result<(), glib::BoolError>210 pub fn reorder_channels(
211     data: &mut [u8],
212     format: crate::AudioFormat,
213     channels: u32,
214     from: &[AudioChannelPosition],
215     to: &[AudioChannelPosition],
216 ) -> Result<(), glib::BoolError> {
217     assert_initialized_main_thread!();
218 
219     if from.len() != to.len() || from.len() > 64 {
220         return Err(glib::bool_error!("Invalid number of channels"));
221     }
222 
223     let from_len = from.len();
224     let to_len = to.len();
225 
226     let from_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
227         if i >= from_len as usize {
228             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
229         } else {
230             from[i].into_glib()
231         }
232     });
233 
234     let to_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
235         if i >= to_len as usize {
236             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
237         } else {
238             to[i].into_glib()
239         }
240     });
241 
242     let valid: bool = unsafe {
243         from_glib(ffi::gst_audio_reorder_channels(
244             data.as_mut_ptr() as *mut _,
245             data.len(),
246             format.into_glib(),
247             channels as i32,
248             from_raw.as_ptr() as *mut _,
249             to_raw.as_ptr() as *mut _,
250         ))
251     };
252 
253     if valid {
254         Ok(())
255     } else {
256         Err(glib::bool_error!("Failed to reorder channels"))
257     }
258 }
259 
260 #[doc(alias = "get_channel_reorder_map")]
261 #[doc(alias = "gst_audio_get_channel_reorder_map")]
channel_reorder_map( from: &[AudioChannelPosition], to: &[AudioChannelPosition], reorder_map: &mut [usize], ) -> Result<(), glib::BoolError>262 pub fn channel_reorder_map(
263     from: &[AudioChannelPosition],
264     to: &[AudioChannelPosition],
265     reorder_map: &mut [usize],
266 ) -> Result<(), glib::BoolError> {
267     assert_initialized_main_thread!();
268 
269     if from.len() != to.len() || from.len() != reorder_map.len() || from.len() > 64 {
270         return Err(glib::bool_error!("Invalid number of channels"));
271     }
272 
273     let from_len = from.len();
274     let to_len = to.len();
275 
276     let from_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
277         if i >= from_len as usize {
278             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
279         } else {
280             from[i].into_glib()
281         }
282     });
283 
284     let to_raw: [ffi::GstAudioChannelPosition; 64] = array_init::array_init(|i| {
285         if i >= to_len as usize {
286             ffi::GST_AUDIO_CHANNEL_POSITION_INVALID
287         } else {
288             to[i].into_glib()
289         }
290     });
291 
292     let mut reorder_map_raw = [0i32, 64];
293     let valid: bool = unsafe {
294         from_glib(ffi::gst_audio_get_channel_reorder_map(
295             from_len as i32,
296             from_raw.as_ptr() as *mut _,
297             to_raw.as_ptr() as *mut _,
298             reorder_map_raw.as_mut_ptr(),
299         ))
300     };
301 
302     if valid {
303         for (d, s) in reorder_map.iter_mut().zip(reorder_map_raw.iter()) {
304             *d = *s as usize;
305         }
306         Ok(())
307     } else {
308         Err(glib::bool_error!("Failed to reorder channels"))
309     }
310 }
311