#![doc(
html_logo_url = "https://github.com/jnqnfe/pulse-binding-rust/raw/master/logo.svg",
html_favicon_url = "https://github.com/jnqnfe/pulse-binding-rust/raw/master/favicon.ico"
)]
#![warn(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]
extern crate libpulse_binding as pulse;
extern crate libpulse_sys as pcapi;
extern crate libpulse_simple_sys as capi;
use std::os::raw::{c_char, c_void};
use std::{ffi::CString, ptr::null};
use std::mem;
use pulse::error::{Code, PAErr};
use pulse::time::MicroSeconds;
use pulse::{stream, sample, channelmap, def};
use capi::pa_simple as SimpleInternal;
pub struct Simple {
ptr: *mut SimpleInternal,
}
unsafe impl Send for Simple {}
unsafe impl Sync for Simple {}
impl Simple {
pub fn new(server: Option<&str>, name: &str, dir: stream::Direction, dev: Option<&str>,
stream_name: &str, ss: &sample::Spec, map: Option<&channelmap::Map>,
attr: Option<&def::BufferAttr>) -> Result<Self, PAErr>
{
let c_server = match server {
Some(server) => CString::new(server).unwrap(),
None => CString::new("").unwrap(),
};
let c_dev = match dev {
Some(dev) => CString::new(dev).unwrap(),
None => CString::new("").unwrap(),
};
let p_map = map.map_or(null::<pcapi::pa_channel_map>(), |m| m.as_ref());
let p_attr = attr.map_or(null::<pcapi::pa_buffer_attr>(), |a| a.as_ref());
let p_server = server.map_or(null::<c_char>(), |_| c_server.as_ptr() as *const c_char);
let p_dev = dev.map_or(null::<c_char>(), |_| c_dev.as_ptr() as *const c_char);
let c_name = CString::new(name).unwrap();
let c_stream_name = CString::new(stream_name).unwrap();
let mut error: i32 = 0;
let ptr = unsafe {
capi::pa_simple_new(
p_server,
c_name.as_ptr(),
dir,
p_dev,
c_stream_name.as_ptr(),
mem::transmute(ss),
p_map,
p_attr,
&mut error
)
};
match ptr.is_null() {
false => Ok(Self::from_raw(ptr)),
true => Err(PAErr(error)),
}
}
fn from_raw(ptr: *mut SimpleInternal) -> Self {
assert_eq!(false, ptr.is_null());
Self { ptr }
}
pub fn write(&self, data: &[u8]) -> Result<(), PAErr> {
let mut error: i32 = 0;
match unsafe { capi::pa_simple_write(self.ptr, data.as_ptr() as *mut c_void, data.len(),
&mut error) }
{
0 => Ok(()),
_ => Err(PAErr(error)),
}
}
pub fn drain(&self) -> Result<(), PAErr> {
let mut error: i32 = 0;
match unsafe { capi::pa_simple_drain(self.ptr, &mut error) } {
0 => Ok(()),
_ => Err(PAErr(error)),
}
}
pub fn read(&self, data: &mut [u8]) -> Result<(), PAErr> {
let mut error: i32 = 0;
match unsafe { capi::pa_simple_read(self.ptr, data.as_mut_ptr() as *mut c_void, data.len(),
&mut error) }
{
0 => Ok(()),
_ => Err(PAErr(error)),
}
}
pub fn get_latency(&self) -> Result<MicroSeconds, PAErr> {
let mut error: i32 = 0;
let ret = unsafe { capi::pa_simple_get_latency(self.ptr, &mut error) };
if error != 0 {
return Err(PAErr(error));
}
match ret {
pcapi::PA_USEC_INVALID => Err(Code::Invalid.into()),
r => Ok(MicroSeconds(r)),
}
}
pub fn flush(&self) -> Result<(), PAErr> {
let mut error: i32 = 0;
match unsafe { capi::pa_simple_flush(self.ptr, &mut error) } {
0 => Ok(()),
_ => Err(PAErr(error)),
}
}
}
impl Drop for Simple {
fn drop(&mut self) {
unsafe { capi::pa_simple_free(self.ptr) };
self.ptr = null::<SimpleInternal>() as *mut SimpleInternal;
}
}