pub mod ext_device_manager;
pub mod ext_device_restore;
pub mod ext_stream_restore;
pub mod introspect;
pub mod scache;
pub mod subscribe;
use std;
use capi;
use std::os::raw::{c_char, c_void};
use std::ffi::{CStr, CString};
use std::ptr::{null, null_mut};
use ::mainloop::events::timer::{TimeEvent, TimeEventCb};
use ::util::unwrap_optional_callback;
use ::operation::Operation;
pub use capi::pa_context as ContextInternal;
pub struct Context {
pub ptr: *mut ContextInternal,
weak: bool,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum State {
Unconnected,
Connecting,
Authorizing,
SettingName,
Ready,
Failed,
Terminated,
}
impl From<State> for capi::pa_context_state_t {
fn from(s: State) -> Self {
unsafe { std::mem::transmute(s) }
}
}
impl From<capi::pa_context_state_t> for State {
fn from(s: capi::pa_context_state_t) -> Self {
unsafe { std::mem::transmute(s) }
}
}
impl State {
pub fn is_good(self) -> bool {
self == State::Connecting ||
self == State::Authorizing ||
self == State::SettingName ||
self == State::Ready
}
}
pub type FlagSet = capi::pa_context_flags_t;
pub mod flags {
use capi;
use super::FlagSet;
pub const NOFLAGS: FlagSet = capi::PA_CONTEXT_NOFLAGS;
pub const NOAUTOSPAWN: FlagSet = capi::PA_CONTEXT_NOAUTOSPAWN;
pub const NOFAIL: FlagSet = capi::PA_CONTEXT_NOFAIL;
}
pub type ContextNotifyCb = extern "C" fn(c: *mut ContextInternal,
userdata: *mut c_void);
pub type ContextSuccessCb = extern "C" fn(c: *mut ContextInternal, success: i32,
userdata: *mut c_void);
pub type ContextEventCb = extern "C" fn(c: *mut ContextInternal,
name: *const c_char, p: *mut ::proplist::ProplistInternal, userdata: *mut c_void);
impl Context {
pub fn new(mainloop_api: &mut ::mainloop::api::MainloopApi,
name: &str) -> Option<Self>
{
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe { capi::pa_context_new(std::mem::transmute(mainloop_api), c_name.as_ptr()) };
if ptr.is_null() {
return None;
}
Some(Self::from_raw(ptr))
}
pub fn new_with_proplist(mainloop_api: &mut ::mainloop::api::MainloopApi, name: &str,
proplist: &mut ::proplist::Proplist) -> Option<Self>
{
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe { capi::pa_context_new_with_proplist(
std::mem::transmute(mainloop_api), c_name.as_ptr(), proplist.ptr) };
if ptr.is_null() {
return None;
}
Some(Self::from_raw(ptr))
}
pub fn from_raw(ptr: *mut ContextInternal) -> Self {
assert_eq!(false, ptr.is_null());
Self { ptr: ptr, weak: false }
}
pub fn from_raw_weak(ptr: *mut ContextInternal) -> Self {
assert_eq!(false, ptr.is_null());
Self { ptr: ptr, weak: true }
}
pub fn set_state_callback(&self, cb: Option<(ContextNotifyCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<ContextNotifyCb>(cb);
unsafe { capi::pa_context_set_state_callback(self.ptr, cb_f, cb_d); }
}
pub fn set_event_callback(&self, cb: Option<(ContextEventCb, *mut c_void)>) {
let (cb_f, cb_d) = unwrap_optional_callback::<ContextEventCb>(cb);
unsafe { capi::pa_context_set_event_callback(self.ptr, cb_f, cb_d); }
}
pub fn errno(&self) -> i32 {
unsafe { capi::pa_context_errno(self.ptr) }
}
pub fn is_pending(&self) -> bool {
unsafe { capi::pa_context_is_pending(self.ptr) != 0 }
}
pub fn get_state(&self) -> State {
unsafe { capi::pa_context_get_state(self.ptr).into() }
}
pub fn connect(&self, server: Option<&str>, flags: FlagSet, api: Option<&::def::SpawnApi>
) -> Result<(), i32>
{
let c_server = match server {
Some(server) => CString::new(server.clone()).unwrap(),
None => CString::new("").unwrap(),
};
let p_api: *const capi::pa_spawn_api = match api {
Some(api) => unsafe { std::mem::transmute(api) },
None => null::<capi::pa_spawn_api>(),
};
let p_server: *const c_char = match server {
Some(_) => c_server.as_ptr(),
None => null::<c_char>(),
};
match unsafe { capi::pa_context_connect(self.ptr, p_server, flags, p_api) } {
0 => Ok(()),
e => Err(e),
}
}
pub fn disconnect(&self) {
unsafe { capi::pa_context_disconnect(self.ptr); }
}
pub fn drain(&self, cb: (ContextNotifyCb, *mut c_void)) -> Option<Operation> {
let ptr = unsafe { capi::pa_context_drain(self.ptr, Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn exit_daemon(&self, cb: (ContextSuccessCb, *mut c_void)) -> Option<Operation> {
let ptr = unsafe { capi::pa_context_exit_daemon(self.ptr, Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn set_default_sink(&self, name: &str, cb: (ContextSuccessCb, *mut c_void)
) -> Option<Operation>
{
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe { capi::pa_context_set_default_sink(self.ptr, c_name.as_ptr(), Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn set_default_source(&self, name: &str, cb: (ContextSuccessCb, *mut c_void)
) -> Option<Operation>
{
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe { capi::pa_context_set_default_source(self.ptr, c_name.as_ptr(),
Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn is_local(&self) -> Option<bool> {
match unsafe { capi::pa_context_is_local(self.ptr) } {
1 => Some(true),
0 => Some(false),
_ => None,
}
}
pub fn set_name(&self, name: &str, cb: (ContextSuccessCb, *mut c_void)) -> Option<Operation> {
let c_name = CString::new(name.clone()).unwrap();
let ptr = unsafe { capi::pa_context_set_name(self.ptr, c_name.as_ptr(), Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn get_server(&self) -> Option<String> {
let ptr = unsafe { capi::pa_context_get_server(self.ptr) };
if ptr.is_null() {
return None;
}
Some(unsafe { CStr::from_ptr(ptr).to_string_lossy().into_owned() })
}
pub fn get_protocol_version(&self) -> u32 {
unsafe { capi::pa_context_get_protocol_version(self.ptr) }
}
pub fn get_server_protocol_version(&self) -> Option<u32> {
match unsafe { capi::pa_context_get_server_protocol_version(self.ptr) } {
::def::INVALID_INDEX => None,
r => Some(r),
}
}
pub fn proplist_update(&self, mode: ::proplist::UpdateMode, p: &mut ::proplist::Proplist,
cb: (ContextSuccessCb, *mut c_void)) -> Option<Operation>
{
let ptr = unsafe { capi::pa_context_proplist_update(self.ptr, mode, p.ptr, Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn proplist_remove(&self, keys: &[&str], cb: (ContextSuccessCb, *mut c_void)
) -> Option<Operation>
{
let mut c_keys: Vec<CString> = Vec::with_capacity(keys.len());
for key in keys {
c_keys.push(CString::new(key.clone()).unwrap());
}
let mut c_key_ptrs: Vec<*const c_char> = Vec::with_capacity(c_keys.len()+1);
for c_key in c_keys {
c_key_ptrs.push(c_key.as_ptr());
}
c_key_ptrs.push(null());
let ptr = unsafe { capi::pa_context_proplist_remove(self.ptr, c_key_ptrs.as_ptr(),
Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(Operation::from_raw(ptr))
}
pub fn get_index(&self) -> Option<u32> {
match unsafe { capi::pa_context_get_index(self.ptr) } {
::def::INVALID_INDEX => None,
r => Some(r),
}
}
pub fn rttime_new<T>(&self, mainloop: &::mainloop::api::Mainloop<MI=T::MI>,
usec: ::sample::Usecs, cb: (TimeEventCb, *mut c_void)) -> Option<TimeEvent<T::MI>>
where T: ::mainloop::api::Mainloop
{
let ptr = unsafe { capi::pa_context_rttime_new(self.ptr, usec, Some(cb.0), cb.1) };
if ptr.is_null() {
return None;
}
Some(TimeEvent::<T::MI>::from_raw(ptr, mainloop.inner().clone()))
}
pub fn rttime_restart<T>(&self, e: &TimeEvent<T::MI>, usec: ::sample::Usecs)
where T: ::mainloop::api::Mainloop
{
unsafe { capi::pa_context_rttime_restart(self.ptr, e.get_ptr(), usec); }
}
pub fn get_tile_size(&self, ss: &::sample::Spec) -> Option<usize> {
match unsafe { capi::pa_context_get_tile_size(self.ptr, std::mem::transmute(ss)) } {
std::usize::MAX => None,
r => Some(r),
}
}
pub fn load_cookie_from_file(&self, cookie_file_path: &str) -> Result<(), i32> {
let c_path = CString::new(cookie_file_path.clone()).unwrap();
match unsafe { capi::pa_context_load_cookie_from_file(self.ptr, c_path.as_ptr()) } {
0 => Ok(()),
e => Err(e),
}
}
}
impl Drop for Context {
fn drop(&mut self) {
if !self.weak {
unsafe { capi::pa_context_unref(self.ptr) };
}
self.ptr = null_mut::<ContextInternal>();
}
}
impl Clone for Context {
fn clone(&self) -> Self {
unsafe { capi::pa_context_ref(self.ptr) };
Self::from_raw(self.ptr)
}
}