// Take a look at the license at the top of the repository in the LICENSE file. use crate::AudioChannelPosition; use std::mem; use glib::translate::{from_glib, IntoGlib}; impl AudioChannelPosition { pub fn to_mask(self) -> u64 { let pos = self.into_glib(); if pos < 0 { return 0; } 1 << (pos as u32) } #[doc(alias = "gst_audio_channel_positions_to_mask")] pub fn positions_to_mask( positions: &[Self], force_order: bool, ) -> Result { assert_initialized_main_thread!(); let len = positions.len(); if len > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let positions_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { positions[i].into_glib() } }); unsafe { let mut mask = mem::MaybeUninit::uninit(); let valid: bool = from_glib(ffi::gst_audio_channel_positions_to_mask( positions_raw.as_ptr() as *mut _, len as i32, force_order.into_glib(), mask.as_mut_ptr(), )); if valid { Ok(mask.assume_init()) } else { Err(glib::bool_error!( "Couldn't convert channel positions to mask" )) } } } #[doc(alias = "gst_audio_channel_positions_from_mask")] pub fn positions_from_mask(mask: u64, positions: &mut [Self]) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); if positions.len() > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let len = positions.len(); let mut positions_raw: [ffi::GstAudioChannelPosition; 64] = [ffi::GST_AUDIO_CHANNEL_POSITION_INVALID; 64]; let valid: bool = unsafe { from_glib(ffi::gst_audio_channel_positions_from_mask( len as i32, mask, positions_raw.as_mut_ptr(), )) }; if valid { for (d, s) in positions.iter_mut().zip(positions_raw.iter()) { *d = unsafe { from_glib(*s) }; } Ok(()) } else { Err(glib::bool_error!( "Couldn't convert channel positions to mask", )) } } #[doc(alias = "gst_audio_channel_positions_to_valid_order")] pub fn positions_to_valid_order(positions: &mut [Self]) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); if positions.len() > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let len = positions.len(); let mut positions_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { positions[i].into_glib() } }); let valid: bool = unsafe { from_glib(ffi::gst_audio_channel_positions_to_valid_order( positions_raw.as_mut_ptr(), len as i32, )) }; if valid { for (d, s) in positions.iter_mut().zip(positions_raw.iter()) { *d = unsafe { from_glib(*s) }; } Ok(()) } else { Err(glib::bool_error!( "Couldn't convert channel positions to mask", )) } } #[doc(alias = "get_fallback_mask")] #[doc(alias = "gst_audio_channel_get_fallback_mask")] pub fn fallback_mask(channels: u32) -> u64 { assert_initialized_main_thread!(); unsafe { ffi::gst_audio_channel_get_fallback_mask(channels as i32) } } #[doc(alias = "gst_audio_check_valid_channel_positions")] pub fn check_valid_channel_positions(positions: &[Self], force_order: bool) -> bool { assert_initialized_main_thread!(); if positions.len() > 64 { return false; } let len = positions.len(); let positions_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { positions[i].into_glib() } }); unsafe { from_glib(ffi::gst_audio_check_valid_channel_positions( positions_raw.as_ptr() as *mut _, len as i32, force_order.into_glib(), )) } } } #[doc(alias = "gst_audio_buffer_reorder_channels")] pub fn buffer_reorder_channels( buffer: &mut gst::BufferRef, format: crate::AudioFormat, channels: u32, from: &[AudioChannelPosition], to: &[AudioChannelPosition], ) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); if from.len() != to.len() || from.len() > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let from_len = from.len(); let to_len = to.len(); let from_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= from_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { from[i].into_glib() } }); let to_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= to_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { to[i].into_glib() } }); let valid: bool = unsafe { from_glib(ffi::gst_audio_buffer_reorder_channels( buffer.as_mut_ptr(), format.into_glib(), channels as i32, from_raw.as_ptr() as *mut _, to_raw.as_ptr() as *mut _, )) }; if valid { Ok(()) } else { Err(glib::bool_error!("Failed to reorder channels")) } } #[doc(alias = "gst_audio_reorder_channels")] pub fn reorder_channels( data: &mut [u8], format: crate::AudioFormat, channels: u32, from: &[AudioChannelPosition], to: &[AudioChannelPosition], ) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); if from.len() != to.len() || from.len() > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let from_len = from.len(); let to_len = to.len(); let from_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= from_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { from[i].into_glib() } }); let to_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= to_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { to[i].into_glib() } }); let valid: bool = unsafe { from_glib(ffi::gst_audio_reorder_channels( data.as_mut_ptr() as *mut _, data.len(), format.into_glib(), channels as i32, from_raw.as_ptr() as *mut _, to_raw.as_ptr() as *mut _, )) }; if valid { Ok(()) } else { Err(glib::bool_error!("Failed to reorder channels")) } } #[doc(alias = "get_channel_reorder_map")] #[doc(alias = "gst_audio_get_channel_reorder_map")] pub fn channel_reorder_map( from: &[AudioChannelPosition], to: &[AudioChannelPosition], reorder_map: &mut [usize], ) -> Result<(), glib::BoolError> { assert_initialized_main_thread!(); if from.len() != to.len() || from.len() != reorder_map.len() || from.len() > 64 { return Err(glib::bool_error!("Invalid number of channels")); } let from_len = from.len(); let to_len = to.len(); let from_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= from_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { from[i].into_glib() } }); let to_raw: [ffi::GstAudioChannelPosition; 64] = std::array::from_fn(|i| { if i >= to_len { ffi::GST_AUDIO_CHANNEL_POSITION_INVALID } else { to[i].into_glib() } }); let mut reorder_map_raw = [0i32, 64]; let valid: bool = unsafe { from_glib(ffi::gst_audio_get_channel_reorder_map( from_len as i32, from_raw.as_ptr() as *mut _, to_raw.as_ptr() as *mut _, reorder_map_raw.as_mut_ptr(), )) }; if valid { for (d, s) in reorder_map.iter_mut().zip(reorder_map_raw.iter()) { *d = *s as usize; } Ok(()) } else { Err(glib::bool_error!("Failed to reorder channels")) } }