use std;
use capi;
use std::ffi::{CStr, CString};
use std::borrow::Cow;
use time::MicroSeconds;
pub use capi::PA_CHANNELS_MAX as CHANNELS_MAX;
pub use capi::PA_RATE_MAX as RATE_MAX;
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[allow(non_camel_case_types)]
pub enum Format {
U8,
ALaw,
ULaw,
S16le,
S16be,
F32le,
F32be,
S32le,
S32be,
S24le,
S24be,
S24_32le,
S24_32be,
Invalid = -1,
}
#[test]
fn format_compare_capi(){
assert_eq!(std::mem::size_of::<Format>(), std::mem::size_of::<capi::pa_sample_format_t>());
assert_eq!(std::mem::align_of::<Format>(), std::mem::align_of::<capi::pa_sample_format_t>());
}
impl From<Format> for capi::pa_sample_format_t {
#[inline]
fn from(f: Format) -> Self {
unsafe { std::mem::transmute(f) }
}
}
impl From<capi::pa_sample_format_t> for Format {
#[inline]
fn from(f: capi::pa_sample_format_t) -> Self {
unsafe { std::mem::transmute(f) }
}
}
impl Default for Format {
#[inline(always)]
fn default() -> Self {
Format::Invalid
}
}
pub use self::ei_formats::*;
#[cfg(target_endian = "big")]
mod ei_formats {
use super::Format;
pub const SAMPLE_S16NE: Format = Format::S16be;
pub const SAMPLE_FLOAT32NE: Format = Format::F32be;
pub const SAMPLE_S32NE: Format = Format::S32be;
pub const SAMPLE_S24NE: Format = Format::S24be;
pub const SAMPLE_S24_32NE: Format = Format::S24_32be;
pub const SAMPLE_S16RE: Format = Format::S16le;
pub const SAMPLE_FLOAT32RE: Format = Format::F32le;
pub const SAMPLE_S32RE: Format = Format::S32le;
pub const SAMPLE_S24RE: Format = Format::S24le;
pub const SAMPLE_S24_32RE: Format = Format::S24_32le;
}
#[cfg(target_endian = "little")]
mod ei_formats {
use super::Format;
pub const SAMPLE_S16NE: Format = Format::S16le;
pub const SAMPLE_FLOAT32NE: Format = Format::F32le;
pub const SAMPLE_S32NE: Format = Format::S32le;
pub const SAMPLE_S24NE: Format = Format::S24le;
pub const SAMPLE_S24_32NE: Format = Format::S24_32le;
pub const SAMPLE_S16RE: Format = Format::S16be;
pub const SAMPLE_FLOAT32RE: Format = Format::F32be;
pub const SAMPLE_S32RE: Format = Format::S32be;
pub const SAMPLE_S24RE: Format = Format::S24be;
pub const SAMPLE_S24_32RE: Format = Format::S24_32be;
}
pub const SAMPLE_FLOAT32: Format = SAMPLE_FLOAT32NE;
#[repr(C)]
#[derive(Debug, Copy, Clone, Eq)]
pub struct Spec {
pub format: Format,
pub rate: u32,
pub channels: u8,
}
#[test]
fn spec_compare_capi(){
assert_eq!(std::mem::size_of::<Spec>(), std::mem::size_of::<capi::pa_sample_spec>());
assert_eq!(std::mem::align_of::<Spec>(), std::mem::align_of::<capi::pa_sample_spec>());
}
impl AsRef<capi::pa_sample_spec> for Spec {
#[inline]
fn as_ref(&self) -> &capi::pa_sample_spec {
unsafe { &*(self as *const Self as *const capi::pa_sample_spec) }
}
}
impl AsMut<capi::pa_sample_spec> for Spec {
#[inline]
fn as_mut(&mut self) -> &mut capi::pa_sample_spec {
unsafe { &mut *(self as *mut Self as *mut capi::pa_sample_spec) }
}
}
impl AsRef<Spec> for capi::pa_sample_spec {
#[inline]
fn as_ref(&self) -> &Spec {
unsafe { &*(self as *const Self as *const Spec) }
}
}
impl From<capi::pa_sample_spec> for Spec {
#[inline]
fn from(s: capi::pa_sample_spec) -> Self {
unsafe { std::mem::transmute(s) }
}
}
impl PartialEq for Spec {
#[inline]
fn eq(&self, other: &Self) -> bool {
unsafe { capi::pa_sample_spec_equal(self.as_ref(), other.as_ref()) != 0 }
}
}
impl Spec {
#[inline]
pub fn init(&mut self) {
unsafe { capi::pa_sample_spec_init(self.as_mut()); }
}
#[inline]
pub fn is_valid(&self) -> bool {
unsafe { capi::pa_sample_spec_valid(self.as_ref()) != 0 }
}
#[inline(always)]
#[deprecated(since = "2.7.0", note="use the `PartialEq` implementation instead")]
pub fn equal_to(&self, to: &Self) -> bool {
self.eq(to)
}
#[inline]
pub fn bytes_per_second(&self) -> usize {
unsafe { capi::pa_bytes_per_second(self.as_ref()) }
}
#[inline]
pub fn frame_size(&self) -> usize {
unsafe { capi::pa_frame_size(self.as_ref()) }
}
#[inline]
pub fn sample_size(&self) -> usize {
unsafe { capi::pa_sample_size(self.as_ref()) }
}
#[inline]
pub fn bytes_to_usec(&self, length: u64) -> MicroSeconds {
MicroSeconds(unsafe { capi::pa_bytes_to_usec(length, self.as_ref()) })
}
#[inline]
pub fn usec_to_bytes(&self, t: MicroSeconds) -> usize {
unsafe { capi::pa_usec_to_bytes(t.0, self.as_ref()) }
}
pub fn print(&self) -> String {
const PRINT_MAX: usize = capi::PA_SAMPLE_SPEC_SNPRINT_MAX;
let mut tmp = Vec::with_capacity(PRINT_MAX);
unsafe {
capi::pa_sample_spec_snprint(tmp.as_mut_ptr(), PRINT_MAX, self.as_ref());
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
}
#[inline]
pub fn format_is_valid(format: u32) -> bool {
unsafe { capi::pa_sample_format_valid(format) != 0 }
}
#[inline]
pub fn rate_is_valid(rate: u32) -> bool {
unsafe { capi::pa_sample_rate_valid(rate) != 0 }
}
#[inline]
pub fn channels_are_valid(channels: u8) -> bool {
unsafe { capi::pa_channels_valid(channels) != 0 }
}
pub fn bytes_print(bytes: u32) -> String {
const PRINT_MAX: usize = capi::PA_BYTES_SNPRINT_MAX;
let mut tmp = Vec::with_capacity(PRINT_MAX);
unsafe {
capi::pa_bytes_snprint(tmp.as_mut_ptr(), PRINT_MAX, bytes);
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
impl Format {
#[inline]
pub fn size(&self) -> usize {
unsafe { capi::pa_sample_size_of_format((*self).into()) }
}
pub fn to_string(&self) -> Option<Cow<'static, str>> {
let ptr = unsafe { capi::pa_sample_format_to_string((*self).into()) };
match ptr.is_null() {
false => Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() }),
true => None,
}
}
pub fn parse(format: &str) -> Self {
let c_format = CString::new(format.clone()).unwrap();
unsafe { capi::pa_parse_sample_format(c_format.as_ptr()).into() }
}
pub fn is_le(&self) -> Option<bool> {
match unsafe { capi::pa_sample_format_is_le((*self).into()) } {
0 => Some(false),
1 => Some(true),
_ => None,
}
}
pub fn is_be(&self) -> Option<bool> {
match unsafe { capi::pa_sample_format_is_be((*self).into()) } {
0 => Some(false),
1 => Some(true),
_ => None,
}
}
#[inline]
pub fn is_ne(&self) -> Option<bool> {
#[cfg(target_endian = "big")]
{ Format::is_be(self) }
#[cfg(target_endian = "little")]
{ Format::is_le(self) }
}
#[inline]
pub fn is_re(&self) -> Option<bool> {
self.is_ne().and_then(|b| Some(!b))
}
}