#![allow(dead_code)]
use ffi;
use num::FromPrimitive;
use std::os::raw;
pub use self::sample_format_flags::SampleFormatFlags;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct DeviceIndex(pub u32);
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum DeviceKind {
Index(DeviceIndex),
UseHostApiSpecificDeviceSpecification,
}
impl From<DeviceIndex> for ffi::PaDeviceIndex {
fn from(idx: DeviceIndex) -> ffi::PaDeviceIndex {
let DeviceIndex(idx) = idx;
idx as ffi::PaDeviceIndex
}
}
impl From<DeviceIndex> for DeviceKind {
fn from(idx: DeviceIndex) -> DeviceKind {
DeviceKind::Index(idx)
}
}
impl From<DeviceKind> for ffi::PaDeviceIndex {
fn from(kind: DeviceKind) -> ffi::PaDeviceIndex {
match kind {
DeviceKind::Index(idx) => idx.into(),
DeviceKind::UseHostApiSpecificDeviceSpecification => -2,
}
}
}
pub const FRAMES_PER_BUFFER_UNSPECIFIED: u32 = 0;
pub type HostApiIndex = ffi::PaHostApiIndex;
pub type Time = ffi::PaTime;
pub type Frames = i64;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum SampleFormat {
F32,
I32,
I24,
I16,
I8,
U8,
Custom,
Unknown,
}
impl SampleFormat {
pub fn from_flags(flags: SampleFormatFlags) -> Self {
if flags.contains(sample_format_flags::FLOAT_32) {
SampleFormat::F32
} else if flags.contains(sample_format_flags::INT_32) {
SampleFormat::I32
} else if flags.contains(sample_format_flags::INT_24) {
SampleFormat::I24
} else if flags.contains(sample_format_flags::INT_16) {
SampleFormat::I16
} else if flags.contains(sample_format_flags::INT_8) {
SampleFormat::I8
} else if flags.contains(sample_format_flags::UINT_8) {
SampleFormat::U8
} else if flags.contains(sample_format_flags::CUSTOM_FORMAT) {
SampleFormat::Custom
} else {
SampleFormat::Unknown
}
}
pub fn flags(self) -> SampleFormatFlags {
match self {
SampleFormat::F32 => sample_format_flags::FLOAT_32,
SampleFormat::I32 => sample_format_flags::INT_32,
SampleFormat::I24 => sample_format_flags::INT_24,
SampleFormat::I16 => sample_format_flags::INT_16,
SampleFormat::I8 => sample_format_flags::INT_8,
SampleFormat::U8 => sample_format_flags::UINT_8,
SampleFormat::Custom => sample_format_flags::CUSTOM_FORMAT,
SampleFormat::Unknown => SampleFormatFlags::empty(),
}
}
pub fn size_in_bytes(&self) -> u8 {
match *self {
SampleFormat::F32 | SampleFormat::I32 => 4,
SampleFormat::I24 => 3,
SampleFormat::I16 => 2,
SampleFormat::I8 | SampleFormat::U8 => 1,
SampleFormat::Custom | SampleFormat::Unknown => 0,
}
}
}
pub mod sample_format_flags {
use ffi;
bitflags! {
pub flags SampleFormatFlags: ::std::os::raw::c_ulong {
const FLOAT_32 = ffi::PA_FLOAT_32,
const INT_32 = ffi::PA_INT_32,
const INT_24 = ffi::PA_INT_24,
const INT_16 = ffi::PA_INT_16,
const INT_8 = ffi::PA_INT_8,
const UINT_8 = ffi::PA_UINT_8,
const CUSTOM_FORMAT = ffi::PA_CUSTOM_FORMAT,
const NON_INTERLEAVED = ffi::PA_NON_INTERLEAVED,
}
}
impl From<ffi::SampleFormat> for SampleFormatFlags {
fn from(format: ffi::SampleFormat) -> Self {
SampleFormatFlags::from_bits(format).unwrap_or_else(|| SampleFormatFlags::empty())
}
}
impl ::std::fmt::Display for SampleFormatFlags {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(
f,
"{:?}",
match self.bits() {
ffi::PA_FLOAT_32 => "FLOAT_32",
ffi::PA_INT_32 => "INT_32",
ffi::PA_INT_16 => "INT_16",
ffi::PA_INT_8 => "INT_8",
ffi::PA_UINT_8 => "UINT_8",
ffi::PA_CUSTOM_FORMAT => "CUSTOM_FORMAT",
ffi::PA_NON_INTERLEAVED => "NON_INTERLEAVED",
_ => "<Unknown SampleFormatFlags>",
}
)
}
}
}
enum_from_primitive! {
#[repr(u32)]
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
pub enum HostApiTypeId {
InDevelopment = ffi::PaHostApiTypeId_paInDevelopment,
DirectSound = ffi::PaHostApiTypeId_paDirectSound,
MME = ffi::PaHostApiTypeId_paMME,
ASIO = ffi::PaHostApiTypeId_paASIO,
SoundManager = ffi::PaHostApiTypeId_paSoundManager,
CoreAudio = ffi::PaHostApiTypeId_paCoreAudio,
OSS = ffi::PaHostApiTypeId_paOSS,
ALSA = ffi::PaHostApiTypeId_paALSA,
AL = ffi::PaHostApiTypeId_paAL,
BeOS = ffi::PaHostApiTypeId_paBeOS,
WDMKS = ffi::PaHostApiTypeId_paWDMKS,
JACK = ffi::PaHostApiTypeId_paJACK,
WASAPI = ffi::PaHostApiTypeId_paWASAPI,
AudioScienceHPI = ffi::PaHostApiTypeId_paAudioScienceHPI,
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct HostApiInfo<'a> {
pub struct_version: i32,
pub host_type: HostApiTypeId,
pub name: &'a str,
pub device_count: u32,
pub default_input_device: Option<DeviceIndex>,
pub default_output_device: Option<DeviceIndex>,
}
impl<'a> HostApiInfo<'a> {
pub fn from_c_info(c_info: ffi::PaHostApiInfo) -> Option<HostApiInfo<'a>> {
let default_input_device = match c_info.defaultInputDevice {
idx if idx >= 0 => Some(DeviceIndex(idx as u32)),
ffi::PA_NO_DEVICE => None,
_ => return None,
};
let default_output_device = match c_info.defaultOutputDevice {
idx if idx >= 0 => Some(DeviceIndex(idx as u32)),
ffi::PA_NO_DEVICE => None,
_ => return None,
};
let device_count = match c_info.deviceCount {
n if n >= 0 => n as u32,
_ => return None,
};
let host_type = match FromPrimitive::from_u32(c_info.type_) {
Some(ty) => ty,
None => return None,
};
Some(HostApiInfo {
struct_version: c_info.structVersion,
host_type: host_type,
name: ffi::c_str_to_str(c_info.name).unwrap_or("<Failed to convert str from CStr>"),
device_count: device_count,
default_input_device: default_input_device,
default_output_device: default_output_device,
})
}
}
impl<'a> From<HostApiInfo<'a>> for ffi::PaHostApiInfo {
fn from(info: HostApiInfo<'a>) -> Self {
let default_input_device = match info.default_input_device {
Some(i) => i.into(),
None => ffi::PA_NO_DEVICE,
};
let default_output_device = match info.default_output_device {
Some(i) => i.into(),
None => ffi::PA_NO_DEVICE,
};
ffi::PaHostApiInfo {
structVersion: info.struct_version as raw::c_int,
type_: info.host_type as ffi::PaHostApiTypeId,
name: ffi::str_to_c_str(info.name),
deviceCount: info.device_count as raw::c_int,
defaultInputDevice: default_input_device,
defaultOutputDevice: default_output_device,
}
}
}
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub struct HostErrorInfo<'a> {
pub host_api_type: HostApiTypeId,
pub code: u32,
pub text: &'a str,
}
impl<'a> HostErrorInfo<'a> {
pub fn from_c_error_info(c_error: ffi::PaHostErrorInfo) -> HostErrorInfo<'a> {
HostErrorInfo {
host_api_type: FromPrimitive::from_u32(c_error.hostApiType).unwrap(),
code: c_error.errorCode as u32,
text: ffi::c_str_to_str(c_error.errorText)
.unwrap_or("<Failed to convert str from CStr>"),
}
}
}
impl<'a> From<HostErrorInfo<'a>> for ffi::PaHostErrorInfo {
fn from(error: HostErrorInfo<'a>) -> Self {
ffi::PaHostErrorInfo {
hostApiType: FromPrimitive::from_i32(error.host_api_type as i32).unwrap(),
errorCode: error.code as raw::c_long,
errorText: ffi::str_to_c_str(error.text),
}
}
}
#[derive(Clone, PartialEq, PartialOrd, Debug)]
pub struct DeviceInfo<'a> {
pub struct_version: i32,
pub name: &'a str,
pub host_api: HostApiIndex,
pub max_input_channels: i32,
pub max_output_channels: i32,
pub default_low_input_latency: Time,
pub default_low_output_latency: Time,
pub default_high_input_latency: Time,
pub default_high_output_latency: Time,
pub default_sample_rate: f64,
}
impl<'a> DeviceInfo<'a> {
pub fn from_c_info(c_info: ffi::PaDeviceInfo) -> DeviceInfo<'a> {
DeviceInfo {
struct_version: c_info.structVersion,
name: ffi::c_str_to_str(c_info.name).unwrap_or("<Failed to convert str from CStr>"),
host_api: c_info.hostApi,
max_input_channels: c_info.maxInputChannels,
max_output_channels: c_info.maxOutputChannels,
default_low_input_latency: c_info.defaultLowInputLatency,
default_low_output_latency: c_info.defaultLowOutputLatency,
default_high_input_latency: c_info.defaultHighInputLatency,
default_high_output_latency: c_info.defaultHighOutputLatency,
default_sample_rate: c_info.defaultSampleRate,
}
}
}
impl<'a> From<DeviceInfo<'a>> for ffi::PaDeviceInfo {
fn from(info: DeviceInfo<'a>) -> Self {
ffi::PaDeviceInfo {
structVersion: info.struct_version as raw::c_int,
name: ffi::str_to_c_str(info.name),
hostApi: info.host_api as ffi::PaHostApiIndex,
maxInputChannels: info.max_input_channels as raw::c_int,
maxOutputChannels: info.max_output_channels as raw::c_int,
defaultLowInputLatency: info.default_low_input_latency,
defaultLowOutputLatency: info.default_low_output_latency,
defaultHighInputLatency: info.default_high_input_latency,
defaultHighOutputLatency: info.default_high_output_latency,
defaultSampleRate: info.default_sample_rate,
}
}
}