use std;
use capi;
use std::ffi::{CStr, CString};
use std::borrow::Cow;
pub use capi::pa_channel_map_def_t as MapDef;
pub type PositionMask = capi::channelmap::pa_channel_position_mask_t;
pub const POSITION_MASK_ALL: PositionMask = 0xffffffffffffffffu64;
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Position {
Invalid = -1,
Mono = 0,
FrontLeft,
FrontRight,
FrontCenter,
RearCenter,
RearLeft,
RearRight,
Lfe,
FrontLeftOfCenter,
FrontRightOfCenter,
SideLeft,
SideRight,
Aux0,
Aux1,
Aux2,
Aux3,
Aux4,
Aux5,
Aux6,
Aux7,
Aux8,
Aux9,
Aux10,
Aux11,
Aux12,
Aux13,
Aux14,
Aux15,
Aux16,
Aux17,
Aux18,
Aux19,
Aux20,
Aux21,
Aux22,
Aux23,
Aux24,
Aux25,
Aux26,
Aux27,
Aux28,
Aux29,
Aux30,
Aux31,
TopCenter,
TopFrontLeft,
TopFrontRight,
TopFrontCenter,
TopRearLeft,
TopRearRight,
TopRearCenter,
}
impl Default for Position {
fn default() -> Self {
Position::Invalid
}
}
impl From<Position> for capi::pa_channel_position_t {
fn from(p: Position) -> Self {
unsafe { std::mem::transmute(p) }
}
}
impl From<capi::pa_channel_position_t> for Position {
fn from(p: capi::pa_channel_position_t) -> Self {
unsafe { std::mem::transmute(p) }
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Map {
pub channels: u8,
pub map: [Position; ::sample::CHANNELS_MAX],
}
impl Default for Map {
fn default() -> Self {
Self {
channels: 0,
map: [Position::Invalid; ::sample::CHANNELS_MAX],
}
}
}
impl PartialEq for Map {
fn eq(&self, other: &Self) -> bool {
match self.channels == other.channels {
true => self.map[..self.channels as usize] == other.map[..other.channels as usize],
false => false,
}
}
}
impl Position {
pub fn to_mask(self) -> PositionMask {
if self == Position::Invalid {
return 0;
}
(1 as PositionMask) << (self as PositionMask)
}
pub fn to_string(pos: Self) -> Option<Cow<'static, str>> {
let ptr = unsafe { capi::pa_channel_position_to_string(pos.into()) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() })
}
pub fn to_pretty_string(pos: Self) -> Option<String> {
let ptr = unsafe { capi::pa_channel_position_to_pretty_string(pos.into()) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() })
}
pub fn from_string(s: &str) -> Self {
let c_str = CString::new(s.clone()).unwrap();
unsafe { capi::pa_channel_position_from_string(c_str.as_ptr()).into() }
}
}
impl Map {
pub fn new_from_string(s: &str) -> Self {
let c_str = CString::new(s.clone()).unwrap();
let mut map: Self = Self::default();
unsafe { capi::pa_channel_map_parse(std::mem::transmute(&mut map), c_str.as_ptr()) };
map
}
pub fn init(&mut self) -> &mut Self {
unsafe { capi::pa_channel_map_init(std::mem::transmute(&self)) };
self
}
pub fn init_mono(&mut self) -> &mut Self {
unsafe { capi::pa_channel_map_init_mono(std::mem::transmute(&self)) };
self
}
pub fn init_stereo(&mut self) -> &mut Self {
unsafe { capi::pa_channel_map_init_stereo(std::mem::transmute(&self)) };
self
}
pub fn init_auto(&mut self, channels: u32, def: MapDef) -> Option<&mut Self> {
debug_assert!(channels as usize <= ::sample::CHANNELS_MAX);
unsafe {
if capi::pa_channel_map_init_auto(std::mem::transmute(&self), channels, def).is_null() {
return None;
}
};
Some(self)
}
pub fn init_extend(&mut self, channels: u32, def: MapDef) -> &mut Self {
debug_assert!(channels as usize <= ::sample::CHANNELS_MAX);
unsafe { capi::pa_channel_map_init_extend(std::mem::transmute(&self), channels, def) };
self
}
pub fn print(&self) -> String {
const PRINT_MAX: usize = capi::PA_CHANNEL_MAP_SNPRINT_MAX;
let mut tmp = Vec::with_capacity(PRINT_MAX);
unsafe {
capi::pa_channel_map_snprint(tmp.as_mut_ptr(), PRINT_MAX, std::mem::transmute(self));
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
pub fn is_equal_to(&self, to: &Self) -> bool {
unsafe { capi::pa_channel_map_equal(std::mem::transmute(self),
std::mem::transmute(to)) == 1 }
}
pub fn is_valid(&self) -> bool {
unsafe { capi::pa_channel_map_valid(std::mem::transmute(self)) != 0 }
}
pub fn is_compatible_with_sample_spec(&self, ss: &::sample::Spec) -> bool {
unsafe { capi::pa_channel_map_compatible(std::mem::transmute(self),
std::mem::transmute(ss)) != 0 }
}
pub fn is_superset_of(&self, of: &Self) -> bool {
unsafe { capi::pa_channel_map_superset(std::mem::transmute(self),
std::mem::transmute(of)) != 0 }
}
pub fn can_balance(&self) -> bool {
unsafe { capi::pa_channel_map_can_balance(std::mem::transmute(self)) != 0 }
}
pub fn can_fade(&self) -> bool {
unsafe { capi::pa_channel_map_can_fade(std::mem::transmute(self)) != 0 }
}
pub fn can_lfe_balance(&self) -> bool {
unsafe { capi::pa_channel_map_can_lfe_balance(std::mem::transmute(self)) != 0 }
}
pub fn to_name(&self) -> Option<Cow<'static, str>> {
let ptr = unsafe { capi::pa_channel_map_to_name(std::mem::transmute(self)) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() })
}
pub fn to_pretty_name(&self) -> Option<String> {
let ptr = unsafe { capi::pa_channel_map_to_pretty_name(std::mem::transmute(self)) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() })
}
pub fn has_position(&self, p: Position) -> bool {
unsafe { capi::pa_channel_map_has_position(std::mem::transmute(self), p.into()) != 0 }
}
pub fn get_mask(&self) -> PositionMask {
unsafe { capi::pa_channel_map_mask(std::mem::transmute(self)) }
}
}