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,
}
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,
}
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) -> MicroSeconds {
MicroSeconds(unsafe { capi::pa_bytes_to_usec(length, std::mem::transmute(self)) })
}
pub fn usec_to_bytes(&self, t: MicroSeconds) -> usize {
unsafe { capi::pa_usec_to_bytes(t.0, std::mem::transmute(self)) }
}
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, std::mem::transmute(self));
CStr::from_ptr(tmp.as_mut_ptr()).to_string_lossy().into_owned()
}
}
}
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 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 {
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()) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy() })
}
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,
}
}
#[cfg(target_endian = "big")]
pub fn is_ne(&self) -> Option<bool> {
Format::is_be(self)
}
#[cfg(target_endian = "little")]
pub fn is_ne(&self) -> Option<bool> {
Format::is_le(self)
}
#[cfg(target_endian = "big")]
pub fn is_re(&self) -> Option<bool> {
Format::is_le(self)
}
#[cfg(target_endian = "little")]
pub fn is_re(&self) -> Option<bool> {
Format::is_be(self)
}
}