use backend::*; use cubeb_backend::{
ffi, log_enabled, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceType, Error,
InputProcessingParams, Ops, Result, Stream, StreamParams, StreamParamsRef,
}; use pulse::{self, ProplistExt}; use pulse_ffi::*; use semver; use std::cell::RefCell; use std::default::Default; use std::ffi::{CStr, CString}; use std::mem; use std::os::raw::c_void; use std::ptr;
iflet Some(info) = info { let _ = context.get_sink_info_by_name(
try_cstr_from(info.default_sink_name),
sink_info_cb,
u,
);
} else { // If info is None, then an error occured. let ctx = unsafe { &mut *(u as *mut PulseContext) };
ctx.mainloop.signal();
}
}
fn new(name: Option<&CStr>) -> Result<Box<Self>> { let name = name.map(|s| s.to_owned()); letmut ctx = PulseContext::_new(name)?;
ctx.mainloop.lock(); /* server_info_callback performs a second async query, *whichisresponsibleforinitializingdefault_sink_info
* and signalling the mainloop to end the wait. */ let user_data: *mut c_void = ctx.as_mut() as *mut _ as *mut _; iflet Some(ref context) = ctx.context { iflet Ok(o) = context.get_server_info(PulseContext::server_info_cb, user_data) {
ctx.operation_wait(None, &o);
}
}
ctx.mainloop.unlock();
/* Update `default_sink_info` when the default device changes. */ iflet Err(e) = ctx.subscribe_notifications(pulse::SubscriptionMask::SERVER) {
cubeb_log!("subscribe_notifications ignored failure: {}", e);
}
let (f, t) = (event.event_facility(), event.event_type()); if (f == pulse::SubscriptionEventFacility::Source)
| (f == pulse::SubscriptionEventFacility::Sink)
{ if (t == pulse::SubscriptionEventType::Remove)
| (t == pulse::SubscriptionEventType::New)
{ if log_enabled() { let op = if t == pulse::SubscriptionEventType::New { "Adding"
} else { "Removing"
}; let dev = if f == pulse::SubscriptionEventFacility::Sink { "sink"
} else { "source "
};
cubeb_log!("{} {} index {}", op, dev, index);
}
if f == pulse::SubscriptionEventFacility::Source { unsafe {
ctx.input_collection_changed_callback.unwrap()(
ctx as *mut _ as *mut _,
ctx.input_collection_changed_user_ptr,
);
}
} if f == pulse::SubscriptionEventFacility::Sink { unsafe {
ctx.output_collection_changed_callback.unwrap()(
ctx as *mut _ as *mut _,
ctx.output_collection_changed_user_ptr,
);
}
}
}
} elseif (f == pulse::SubscriptionEventFacility::Server)
&& (t == pulse::SubscriptionEventType::Change)
{
cubeb_log!("Server changed {}", index as i32); let user_data: *mut c_void = ctx as *mut _ as *mut _; iflet Some(ref context) = ctx.context { iflet Err(e) = context.get_server_info(PulseContext::server_info_cb, user_data)
{
cubeb_log!("Error: get_server_info ignored failure: {}", e);
}
}
}
}
fn max_channel_count(&mutself) -> Result<u32> { matchself.default_sink_info {
Some(ref info) => Ok(u32::from(info.channel_map.channels)),
None => {
cubeb_log!("Error: couldn't get the max channel count");
Err(Error::error())
}
}
}
fn min_latency(&mutself, params: StreamParams) -> Result<u32> { // According to PulseAudio developers, this is a safe minimum.
Ok(25 * params.rate() / 1000)
}
iflet Ok(o) =
context.get_server_info(default_device_names, &mut user_data as *mut _ as *mut _)
{ self.operation_wait(None, &o);
}
if devtype.contains(DeviceType::OUTPUT) { iflet Ok(o) = context
.get_sink_info_list(add_output_device, &mut user_data as *mut _ as *mut _)
{ self.operation_wait(None, &o);
}
}
if devtype.contains(DeviceType::INPUT) { iflet Ok(o) = context
.get_source_info_list(add_input_device, &mut user_data as *mut_ as *mut _)
{ self.operation_wait(None, &o);
}
}
self.mainloop.unlock();
}
// Extract the array of cubeb_device_info from // PulseDevListData and convert it into C representation. letmut tmp = Vec::new();
mem::swap(&mut user_data.devinfo, &muttmp); letmut devices = tmp.into_boxed_slice(); let coll = unsafe { &mut *collection.as_ptr() };
coll.device = devices.as_mut_ptr();
coll.count = devices.len();
// Giving away the memory owned by devices. Don't free it!
mem::forget(devices);
Ok(())
}
fn device_collection_destroy(&mutself, collection: &='color:red'>mut DeviceCollectionRef) -> Result<()> {
debug_assert!(!collection.as_ptr().is_null()); unsafe { let coll = &mut *collection.as_ptr(); letmut devices = Vec::from_raw_parts(coll.device, coll.count, coll.count); for dev in &mut devices { if !dev.group_id.is_null() { let _ = CString::from_raw(dev.group_id as *mut _);
} if !dev.vendor_name.is_null() { let _ = CString::from_raw(dev.vendor_name as *mut _);
} if !dev.friendly_name.is_null() { let _ = CString::from_raw(dev.friendly_name as *mut _);
}
}
coll.device = ptr::null_mut();
coll.count = 0;
}
Ok(())
}
letmut mask = pulse::SubscriptionMask::empty(); ifself.input_collection_changed_callback.is_some() {
mask |= pulse::SubscriptionMask::SOURCE;
} ifself.output_collection_changed_callback.is_some() {
mask |= pulse::SubscriptionMask::SINK;
} /* Default device changed, this is always registered in order to update the
* `default_sink_info` when the default device changes. */
mask |= pulse::SubscriptionMask::SERVER;
self.subscribe_notifications(mask)
}
}
impl Drop for PulseContext { fn drop(&mutself) { self.destroy();
}
}
if !connected || !self.wait_until_context_ready() { self.mainloop.unlock(); self.context_destroy();
cubeb_log!("Error: error while waiting for pulse's context to be ready"); return Err(Error::error());
}
self.mainloop.unlock();
let version_str = unsafe { CStr::from_ptr(pulse::library_version()) }; iflet Ok(version) = semver::Version::parse(&version_str.to_string_lossy()) { self.version_0_9_8 =
version >= semver::Version::parse("0.9.8").expect("Failed to parse version"); self.version_2_0_0 =
version >= semver::Version::parse("2.0.0").expect("Failed to parse version");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.