use std;
use libc;
use capi;
use std::os::raw::c_char;
use std::ffi::{CStr, CString};
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,
}
impl From<Format> for capi::pa_sample_format_t {
fn from(f: Format) -> Self {
unsafe { std::mem::transmute(f) }
}
}
impl From<capi::pa_sample_format_t> for Format {
fn from(f: capi::pa_sample_format_t) -> Self {
unsafe { std::mem::transmute(f) }
}
}
impl Default for Format {
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, PartialEq, Eq)]
pub struct Spec {
pub format: Format,
pub rate: u32,
pub channels: u8,
}
pub type Usecs = capi::sample::pa_usec_t;
pub const SPEC_PRINT_MAX: usize = capi::PA_SAMPLE_SPEC_SNPRINT_MAX;
pub const BYTES_PRINT_MAX: usize = capi::PA_BYTES_SNPRINT_MAX;
pub fn size_of_format(f: Format) -> usize {
unsafe { capi::pa_sample_size_of_format(f.into()) }
}
impl Spec {
pub fn init(&mut self) {
unsafe { capi::pa_sample_spec_init(std::mem::transmute(self)); }
}
pub fn is_valid(&self) -> bool {
unsafe { capi::pa_sample_spec_valid(std::mem::transmute(self)) != 0 }
}
pub fn equal_to(&self, to: &Self) -> bool {
unsafe { capi::pa_sample_spec_equal(std::mem::transmute(self), std::mem::transmute(to)) != 0 }
}
pub fn bytes_per_second(&self) -> usize {
unsafe { capi::pa_bytes_per_second(std::mem::transmute(self)) }
}
pub fn frame_size(&self) -> usize {
unsafe { capi::pa_frame_size(std::mem::transmute(self)) }
}
pub fn sample_size(&self) -> usize {
unsafe { capi::pa_sample_size(std::mem::transmute(self)) }
}
pub fn bytes_to_usec(&self, length: u64) -> Usecs {
unsafe { capi::pa_bytes_to_usec(length, std::mem::transmute(self)) }
}
pub fn usec_to_bytes(&self, t: Usecs) -> usize {
unsafe { capi::pa_usec_to_bytes(t, std::mem::transmute(self)) }
}
pub fn print(&self) -> Option<String> {
let tmp = unsafe { libc::malloc(SPEC_PRINT_MAX) as *mut c_char };
if tmp.is_null() {
return None;
}
unsafe {
capi::pa_sample_spec_snprint(tmp, SPEC_PRINT_MAX, std::mem::transmute(self));
let ret = Some(CStr::from_ptr(tmp).to_string_lossy().into_owned());
libc::free(tmp as *mut libc::c_void);
ret
}
}
}
pub fn format_is_valid(format: u32) -> bool {
unsafe { capi::pa_sample_format_valid(format) != 0 }
}
pub fn rate_is_valid(rate: u32) -> bool {
unsafe { capi::pa_sample_rate_valid(rate) != 0 }
}
pub fn channels_are_valid(channels: u8) -> bool {
unsafe { capi::pa_channels_valid(channels) != 0 }
}
pub fn format_to_string(f: Format) -> Option<&'static CStr> {
let ptr = unsafe { capi::pa_sample_format_to_string(f.into()) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr) })
}
pub fn parse_format(format: &str) -> Format {
let c_format = CString::new(format.clone()).unwrap();
unsafe { capi::pa_parse_sample_format(c_format.as_ptr()).into() }
}
pub fn bytes_print(bytes: u32) -> Option<String> {
let tmp = unsafe { libc::malloc(BYTES_PRINT_MAX) as *mut c_char };
if tmp.is_null() {
return None;
}
unsafe {
capi::pa_bytes_snprint(tmp, BYTES_PRINT_MAX, bytes);
let ret = Some(CStr::from_ptr(tmp).to_string_lossy().into_owned());
libc::free(tmp as *mut libc::c_void);
ret
}
}
pub fn format_is_le(f: Format) -> Option<bool> {
match unsafe { capi::pa_sample_format_is_le(f.into()) } {
0 => Some(false),
1 => Some(true),
_ => None,
}
}
pub fn format_is_be(f: Format) -> Option<bool> {
match unsafe { capi::pa_sample_format_is_be(f.into()) } {
0 => Some(false),
1 => Some(true),
_ => None,
}
}
#[cfg(target_endian = "big")]
pub fn format_is_ne(f: Format) -> Option<bool> {
format_is_be(f)
}
#[cfg(target_endian = "little")]
pub fn format_is_ne(f: Format) -> Option<bool> {
format_is_le(f)
}
#[cfg(target_endian = "big")]
pub fn format_is_re(f: Format) -> Option<bool> {
format_is_le(f)
}
#[cfg(target_endian = "little")]
pub fn format_is_re(f: Format) -> Option<bool> {
format_is_be(f)
}