use std::{ptr, mem};
use std::mem::{transmute};
use std::num::{FromPrimitive};
use std::vec::{Vec};
use libc::{c_double, c_void, malloc};
use libc::types::os::arch::c95::size_t;
use ffi;
pub use self::error::Error;
pub use self::types::{
HostApiInfo,
DeviceInfo,
SampleFormat,
StreamFlags,
StreamParameters,
HostErrorInfo,
Time,
Frames,
StreamInfo,
CallbackFunction,
DeviceIndex,
HostApiIndex,
StreamCallbackFlags,
StreamCallbackTimeInfo,
StreamCallbackResult,
PA_NO_DEVICE,
HostApiTypeId,
PA_USE_HOST_API_SPECIFIC_DEVICE_SPECIFICATION,
};
pub mod error;
mod types;
pub mod device;
pub mod host;
pub fn get_version() -> i32 {
unsafe {
ffi::Pa_GetVersion()
}
}
pub fn get_version_text() -> String {
unsafe {
ffi::c_str_to_string(&ffi::Pa_GetVersionText())
}
}
pub fn get_error_text(error_code: Error) -> String {
unsafe {
ffi::c_str_to_string(&ffi::Pa_GetErrorText(error_code))
}
}
pub fn initialize() -> Result<(), Error> {
unsafe {
match ffi::Pa_Initialize() {
Error::NoError => Ok(()),
err => Err(err),
}
}
}
pub fn terminate() -> Result<(), Error> {
unsafe {
match ffi::Pa_Terminate() {
Error::NoError => Ok(()),
err => Err(err),
}
}
}
pub fn get_last_host_error_info() -> HostErrorInfo {
let c_error = unsafe { ffi::Pa_GetLastHostErrorInfo() };
HostErrorInfo::wrap(c_error)
}
pub fn is_format_supported(input_parameters: &StreamParameters,
output_parameters: &StreamParameters,
sample_rate : f64) -> Result<(), Error> {
let c_input = input_parameters.unwrap();
let c_output = output_parameters.unwrap();
match unsafe {
ffi::Pa_IsFormatSupported(&c_input, &c_output, sample_rate as c_double)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn get_sample_size(format: SampleFormat) -> Result<(), Error> {
match unsafe {
ffi::Pa_GetSampleSize(format as u64)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn sleep(m_sec : i32) -> () {
unsafe {
ffi::Pa_Sleep(m_sec)
}
}
mod private {
use std::num::{FromPrimitive, ToPrimitive};
use std::ops::{Add, Sub, Mul, Div};
use super::types::SampleFormat;
pub trait SamplePrivate: ::std::default::Default + Copy + Clone + ::std::fmt::Debug
+ ToPrimitive + FromPrimitive + Add + Sub + Mul + Div {
fn size<S: SamplePrivate>() -> usize {
::std::mem::size_of::<S>()
}
fn to_sample_format(&self) -> SampleFormat;
}
}
impl private::SamplePrivate for f32 {
fn to_sample_format(&self) -> SampleFormat { SampleFormat::Float32 }
}
impl private::SamplePrivate for i32 {
fn to_sample_format(&self) -> SampleFormat { SampleFormat::Int32 }
}
impl private::SamplePrivate for u8 {
fn to_sample_format(&self) -> SampleFormat { SampleFormat::UInt8 }
}
impl private::SamplePrivate for i8 {
fn to_sample_format(&self) -> SampleFormat { SampleFormat::Int8 }
}
pub trait Sample: private::SamplePrivate {
fn sample_format_for<S: Sample>() -> SampleFormat {
let s: S = ::std::default::Default::default();
s.sample_format()
}
fn sample_format(&self) -> SampleFormat { self.to_sample_format() }
}
impl Sample for f32 {}
impl Sample for i32 {}
impl Sample for i8 {}
impl Sample for u8 {}
pub struct Stream<I: Sample, O: Sample> {
c_pa_stream : *mut ffi::C_PaStream,
c_input : Option<ffi::C_PaStreamParameters>,
c_output : Option<ffi::C_PaStreamParameters>,
unsafe_buffer : *mut c_void,
callback_function : Option<CallbackFunction>,
num_input_channels : i32,
phantom_data_input : ::std::marker::PhantomData<I>,
phantom_data_output : ::std::marker::PhantomData<O>,
}
impl<I: Sample, O: Sample> Stream<I, O> {
pub fn new() -> Stream<I, O> {
Stream {
c_pa_stream : ptr::null_mut(),
c_input : None,
c_output : None,
unsafe_buffer : ptr::null_mut(),
callback_function : None,
num_input_channels : 0,
phantom_data_input : ::std::marker::PhantomData,
phantom_data_output : ::std::marker::PhantomData,
}
}
pub fn open(&mut self,
input_parameters: Option<&StreamParameters>,
output_parameters: Option<&StreamParameters>,
sample_rate: f64,
frames_per_buffer: u32,
stream_flags: StreamFlags) -> Result<(), Error> {
if input_parameters.is_some() {
self.c_input = Some(input_parameters.unwrap().unwrap());
self.num_input_channels = input_parameters.unwrap().channel_count;
self.unsafe_buffer = unsafe {
malloc(mem::size_of::<I>() as size_t *
frames_per_buffer as size_t *
input_parameters.unwrap().channel_count as size_t) as *mut c_void};
}
if output_parameters.is_some() {
self.c_output = Some(output_parameters.unwrap().unwrap());
}
unsafe {
if self.c_input.is_some() &&
self.c_output.is_some() {
let err = ffi::Pa_OpenStream(&mut self.c_pa_stream,
&(self.c_input.unwrap()),
&(self.c_output.unwrap()),
sample_rate as c_double,
frames_per_buffer,
stream_flags as u64,
None,
ptr::null_mut());
match err {
Error::NoError => Ok(()),
_ => Err(err),
}
}
else if self.c_input.is_some() {
let err = ffi::Pa_OpenStream(&mut self.c_pa_stream,
&(self.c_input.unwrap()),
ptr::null(),
sample_rate as c_double,
frames_per_buffer,
stream_flags as u64,
None,
ptr::null_mut());
match err {
Error::NoError => Ok(()),
_ => Err(err),
}
}
else if self.c_output.is_some() {
let err = ffi::Pa_OpenStream(&mut self.c_pa_stream,
ptr::null(),
&(self.c_output.unwrap()),
sample_rate as c_double,
frames_per_buffer,
stream_flags as u64,
None,
ptr::null_mut());
match err {
Error::NoError => Ok(()),
_ => Err(err),
}
}
else {
Err(Error::BadStreamPtr)
}
}
}
pub fn open_default(&mut self,
sample_rate: f64,
frames_per_buffer: u32,
num_input_channels: i32,
num_output_channels: i32,
sample_format: SampleFormat) -> Result<(), Error> {
if num_input_channels > 0 {
self.c_input = None;
self.num_input_channels = num_input_channels;
self.unsafe_buffer = unsafe {
malloc(mem::size_of::<I>() as size_t *
frames_per_buffer as size_t *
num_input_channels as size_t) as *mut c_void };
}
match unsafe {
ffi::Pa_OpenDefaultStream(&mut self.c_pa_stream,
num_input_channels,
num_output_channels,
sample_format as u64,
sample_rate as c_double,
frames_per_buffer,
None,
ptr::null_mut())
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn close(&mut self) -> Result<(), Error> {
match unsafe {
ffi::Pa_CloseStream(self.c_pa_stream)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn start(&mut self) -> Result<(), Error> {
match unsafe {
ffi::Pa_StartStream(self.c_pa_stream)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn stop(&mut self) -> Result<(), Error> {
match unsafe {
ffi::Pa_StopStream(self.c_pa_stream)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn abort(&mut self) -> Result<(), Error> {
match unsafe {
ffi::Pa_AbortStream(self.c_pa_stream)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn is_stopped(&self) -> Result<(), Error> {
match unsafe {
ffi::Pa_IsStreamStopped(self.c_pa_stream)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn is_active(&self) -> Result<bool, Error> {
let err = unsafe { ffi::Pa_IsStreamActive(self.c_pa_stream) };
match err {
0 => Ok(false),
1 => Ok(true),
_ => Err(unsafe { transmute::<i32, Error>(err) })
}
}
pub fn get_stream_time(&self) -> Time {
unsafe {
ffi::Pa_GetStreamTime(self.c_pa_stream)
}
}
pub fn get_stream_cpu_load(&self) -> f64 {
unsafe {
ffi::Pa_GetStreamCpuLoad(self.c_pa_stream)
}
}
pub fn get_stream_read_available(&self) -> Result<Option<Frames>, Error> {
match unsafe { ffi::Pa_GetStreamReadAvailable(self.c_pa_stream) } {
0 => Ok(None),
n if n > 0 => Ok(Some(n)),
n => Err(FromPrimitive::from_i64(n).expect("Undefined error code.")),
}
}
pub fn get_stream_write_available(&self) -> Result<Option<Frames>, Error> {
match unsafe { ffi::Pa_GetStreamWriteAvailable(self.c_pa_stream) } {
0 => Ok(None),
n if n > 0 => Ok(Some(n)),
n => Err(FromPrimitive::from_i64(n).expect("Undefined error code.")),
}
}
#[doc(hidden)]
#[cfg(target_os="macos")]
pub fn read(&self, frames_per_buffer: u32) -> Result<Vec<I>, Error> {
unsafe {
ffi::Pa_ReadStream(self.c_pa_stream,
self.unsafe_buffer,
frames_per_buffer)
};
Ok(unsafe {
Vec::from_raw_buf(self.unsafe_buffer as *const I,
(frames_per_buffer as usize) * (self.num_input_channels as usize)) })
}
#[cfg(any(target_os="win32", target_os="linux"))]
pub fn read(&self, frames_per_buffer: u32) -> Result<Vec<I>, Error> {
let err = unsafe {
ffi::Pa_ReadStream(self.c_pa_stream, self.unsafe_buffer, frames_per_buffer)
};
match err {
Error::NoError => Ok(unsafe {
Vec::from_raw_buf(self.unsafe_buffer as *const I,
(frames_per_buffer * self.num_input_channels as u32) as usize) }),
_ => Err(err)
}
}
pub fn write<T> (&self, output_buffer: T, frames_per_buffer : u32) -> Result<(), Error>
where T: AsSlice<O> {
match unsafe {
ffi::Pa_WriteStream(self.c_pa_stream,
output_buffer.as_slice().as_ptr() as *mut c_void,
frames_per_buffer)
} {
Error::NoError => Ok(()),
err => Err(err),
}
}
pub fn get_stream_info(&self) -> StreamInfo {
unsafe {
*ffi::Pa_GetStreamInfo(self.c_pa_stream)
}
}
#[doc(hidden)]
pub fn get_c_pa_stream(&self) -> *mut ffi::C_PaStream {
self.c_pa_stream
}
}