use std;
use capi;
use std::os::raw::{c_char, c_void};
use std::ffi::{CStr, CString};
use std::borrow::Cow;
use std::ptr::{null, null_mut};
use super::{ContextInternal, Context};
use callbacks::ListResult;
use capi::pa_ext_stream_restore_info as InfoInternal;
#[derive(Debug)]
pub struct Info<'a> {
pub name: Option<Cow<'a, str>>,
pub channel_map: ::channelmap::Map,
pub volume: ::volume::ChannelVolumes,
pub device: Option<Cow<'a, str>>,
pub mute: bool,
}
impl<'a> Info<'a> {
fn new_from_raw(p: *const InfoInternal) -> Self {
assert!(!p.is_null());
let src = unsafe { p.as_ref().unwrap() };
unsafe {
Info {
name: match src.name.is_null() {
false => Some(CStr::from_ptr(src.name).to_string_lossy()),
true => None,
},
channel_map: std::mem::transmute(src.channel_map),
volume: std::mem::transmute(src.volume),
device: match src.name.is_null() {
false => Some(CStr::from_ptr(src.device).to_string_lossy()),
true => None,
},
mute: match src.mute { 0 => false, _ => true },
}
}
}
}
pub struct StreamRestore {
context: *mut ContextInternal,
cb_ptrs: CallbackPointers,
}
#[derive(Default)]
struct CallbackPointers {
subscribe: SubscribeCb,
}
type SubscribeCb = ::callbacks::MultiUseCallback<FnMut(),
extern "C" fn(*mut ContextInternal, *mut c_void)>;
impl Context {
pub fn stream_restore(&self) -> StreamRestore {
unsafe { capi::pa_context_ref(self.ptr) };
StreamRestore::from_raw(self.ptr)
}
}
impl StreamRestore {
fn from_raw(context: *mut ContextInternal) -> Self {
Self { context: context, cb_ptrs: Default::default() }
}
pub fn test<F>(&mut self, callback: F) -> ::operation::Operation
where F: FnMut(u32) + 'static
{
let cb_data: *mut c_void = {
let boxed: *mut Box<FnMut(u32)> =
Box::into_raw(Box::new(Box::new(callback)));
boxed as *mut c_void
};
let ptr = unsafe { capi::pa_ext_stream_restore_test(self.context,
Some(super::ext_test_cb_proxy), cb_data) };
assert!(!ptr.is_null());
::operation::Operation::from_raw(ptr)
}
pub fn read<F>(&mut self, callback: F) -> ::operation::Operation
where F: FnMut(ListResult<&Info>) + 'static
{
let cb_data: *mut c_void = {
let boxed: *mut Box<FnMut(ListResult<&Info>)> =
Box::into_raw(Box::new(Box::new(callback)));
boxed as *mut c_void
};
let ptr = unsafe { capi::pa_ext_stream_restore_read(self.context, Some(read_list_cb_proxy),
cb_data) };
assert!(!ptr.is_null());
::operation::Operation::from_raw(ptr)
}
pub fn write<F>(&mut self, mode: ::proplist::UpdateMode, data: &[&Info],
apply_immediately: bool, callback: F) -> ::operation::Operation
where F: FnMut(bool) + 'static
{
let cb_data: *mut c_void = {
let boxed: *mut Box<FnMut(bool)> = Box::into_raw(Box::new(Box::new(callback)));
boxed as *mut c_void
};
let ptr = unsafe {
capi::pa_ext_stream_restore_write(self.context, mode,
std::mem::transmute(data.as_ptr()), data.len() as u32, apply_immediately as i32,
Some(super::success_cb_proxy), cb_data)
};
assert!(!ptr.is_null());
::operation::Operation::from_raw(ptr)
}
pub fn delete<F>(&mut self, streams: &[&str], callback: F) -> ::operation::Operation
where F: FnMut(bool) + 'static
{
let mut c_streams: Vec<CString> = Vec::with_capacity(streams.len());
for stream in streams {
c_streams.push(CString::new(stream.clone()).unwrap());
}
let mut c_stream_ptrs: Vec<*const c_char> = Vec::with_capacity(c_streams.len() + 1);
for c_stream in c_streams {
c_stream_ptrs.push(c_stream.as_ptr());
}
c_stream_ptrs.push(null());
let cb_data: *mut c_void = {
let boxed: *mut Box<FnMut(bool)> = Box::into_raw(Box::new(Box::new(callback)));
boxed as *mut c_void
};
let ptr = unsafe { capi::pa_ext_stream_restore_delete(self.context, c_stream_ptrs.as_ptr(),
Some(super::success_cb_proxy), cb_data) };
assert!(!ptr.is_null());
::operation::Operation::from_raw(ptr)
}
pub fn subscribe<F>(&mut self, enable: bool, callback: F) -> ::operation::Operation
where F: FnMut(bool) + 'static
{
let cb_data: *mut c_void = {
let boxed: *mut Box<FnMut(bool)> = Box::into_raw(Box::new(Box::new(callback)));
boxed as *mut c_void
};
let ptr = unsafe { capi::pa_ext_stream_restore_subscribe(self.context, enable as i32,
Some(super::success_cb_proxy), cb_data) };
assert!(!ptr.is_null());
::operation::Operation::from_raw(ptr)
}
pub fn set_subscribe_cb<F>(&mut self, callback: F)
where F: FnMut() + 'static
{
let saved = &mut self.cb_ptrs.subscribe;
*saved = SubscribeCb::new(Some(Box::new(callback)));
let (cb_fn, cb_data) = saved.get_capi_params(super::ext_subscribe_cb_proxy);
unsafe { capi::pa_ext_stream_restore_set_subscribe_cb(self.context, cb_fn, cb_data); }
}
}
impl Drop for StreamRestore {
fn drop(&mut self) {
unsafe { capi::pa_context_unref(self.context) };
self.context = null_mut::<ContextInternal>();
}
}
extern "C"
fn read_list_cb_proxy(_: *mut ContextInternal, i: *const InfoInternal, eol: i32,
userdata: *mut c_void)
{
assert!(!userdata.is_null());
match eol {
0 => { assert!(!i.is_null());
let callback = unsafe { &mut *(userdata as *mut Box<FnMut(ListResult<&Info>)>) };
let obj = Info::new_from_raw(i);
callback(ListResult::Item(&obj));
},
_ => { let mut callback = unsafe {
Box::from_raw(userdata as *mut Box<FnMut(ListResult<&Info>)>)
};
callback(match eol < 0 { false => ListResult::End, true => ListResult::Error });
},
}
}