Bug 1399009 - Update cubeb-pulse-rs to a386d91... r?kinetik
MozReview-Commit-ID: BnJpMCuDPOf
--- a/media/libcubeb/cubeb-pulse-rs/README_MOZILLA
+++ b/media/libcubeb/cubeb-pulse-rs/README_MOZILLA
@@ -1,8 +1,8 @@
The source from this directory was copied from the cubeb-pulse-rs
git repository using the update.sh script. The only changes
made were those applied by update.sh and the addition of
Makefile.in build files for the Mozilla build system.
The cubeb-pulse-rs git repository is: https://github.com/djg/cubeb-pulse-rs.git
-The git commit ID used was 3b8cfba161cec66bee6a755bce102466baa92ddb (2017-07-07 14:57:07 +1000)
+The git commit ID used was a386d91d7f34e6d3a949ee4fa44e848e29634587 (2017-09-05 13:34:32 +1000)
--- a/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs
+++ b/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs
@@ -1,12 +1,13 @@
// This code is generated.
use super::*;
+#[cfg(feature = "dlopen")]
macro_rules! cstr {
($x:expr) => { concat!($x, "\0").as_bytes().as_ptr() as *const c_char }
}
#[cfg(not(feature = "dlopen"))]
mod static_fns {
use super::*;
use std::os::raw::{c_char, c_double, c_float, c_int, c_uint, c_void};
--- a/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs
+++ b/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs
@@ -289,16 +289,21 @@ impl StreamFlags {
}
impl Into<ffi::pa_stream_flags_t> for StreamFlags {
fn into(self) -> ffi::pa_stream_flags_t {
self.bits() as ffi::pa_stream_flags_t
}
}
+pub enum StreamLatency {
+ Positive(u64),
+ Negative(u64),
+}
+
bitflags!{
pub flags SubscriptionMask : u32 {
const SUBSCRIPTION_MASK_SINK = ffi::PA_SUBSCRIPTION_MASK_SINK,
const SUBSCRIPTION_MASK_SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE,
const SUBSCRIPTION_MASK_SINK_INPUT = ffi::PA_SUBSCRIPTION_MASK_SINK_INPUT,
const SUBSCRIPTION_MASK_SOURCE_OUTPUT = ffi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT,
const SUBSCRIPTION_MASK_MODULE = ffi::PA_SUBSCRIPTION_MASK_MODULE,
const SUBSCRIPTION_MASK_CLIENT = ffi::PA_SUBSCRIPTION_MASK_CLIENT,
--- a/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs
+++ b/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs
@@ -324,21 +324,28 @@ impl Stream {
}
pub fn get_time(&self) -> Result<(u64)> {
let mut usec: u64 = 0;
let r = unsafe { ffi::pa_stream_get_time(self.raw_mut(), &mut usec) };
error_result!(usec, r)
}
- pub fn get_latency(&self) -> Result<(u64, bool)> {
+ pub fn get_latency(&self) -> Result<StreamLatency> {
let mut usec: u64 = 0;
let mut negative: i32 = 0;
let r = unsafe { ffi::pa_stream_get_latency(self.raw_mut(), &mut usec, &mut negative) };
- error_result!((usec, negative != 0), r)
+ error_result!(
+ if negative == 0 {
+ StreamLatency::Positive(usec)
+ } else {
+ StreamLatency::Negative(usec)
+ },
+ r
+ )
}
pub fn get_sample_spec(&self) -> &SampleSpec {
unsafe {
let ptr = ffi::pa_stream_get_sample_spec(self.raw_mut());
debug_assert!(!ptr.is_null());
&*ptr
}
--- a/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs
@@ -9,16 +9,17 @@ use cubeb;
use pulse::{self, ProplistExt};
use pulse_ffi::*;
use semver;
use std::default::Default;
use std::ffi::{CStr, CString};
use std::mem;
use std::os::raw::{c_char, c_void};
use std::ptr;
+use std::cell::RefCell;
fn pa_channel_to_cubeb_channel(channel: pulse::ChannelPosition) -> cubeb::Channel {
use pulse::ChannelPosition;
assert_ne!(channel, ChannelPosition::Invalid);
match channel {
ChannelPosition::Mono => cubeb::CHANNEL_MONO,
ChannelPosition::FrontLeft => cubeb::CHANNEL_LEFT,
ChannelPosition::FrontRight => cubeb::CHANNEL_RIGHT,
@@ -60,16 +61,17 @@ pub struct Context {
pub context_name: Option<CString>,
pub collection_changed_callback: cubeb::DeviceCollectionChangedCallback,
pub collection_changed_user_ptr: *mut c_void,
pub error: bool,
pub version_2_0_0: bool,
pub version_0_9_8: bool,
#[cfg(feature = "pulse-dlopen")]
pub libpulse: LibLoader,
+ devids: RefCell<Intern>,
}
impl Drop for Context {
fn drop(&mut self) {
self.destroy();
}
}
@@ -88,16 +90,17 @@ impl Context {
context: None,
default_sink_info: None,
context_name: name,
collection_changed_callback: None,
collection_changed_user_ptr: ptr::null_mut(),
error: true,
version_0_9_8: false,
version_2_0_0: false,
+ devids: RefCell::new(Intern::new()),
});
Ok(ctx)
}
#[cfg(not(feature = "pulse-dlopen"))]
fn _new(name: Option<CString>) -> Result<Box<Self>> {
Ok(Box::new(Context {
@@ -106,16 +109,17 @@ impl Context {
context: None,
default_sink_info: None,
context_name: name,
collection_changed_callback: None,
collection_changed_user_ptr: ptr::null_mut(),
error: true,
version_0_9_8: false,
version_2_0_0: false,
+ devids: RefCell::new(Intern::new()),
}))
}
pub fn new(name: *const c_char) -> Result<Box<Self>> {
fn server_info_cb(context: &pulse::Context, info: &pulse::ServerInfo, u: *mut c_void) {
fn sink_info_cb(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, u: *mut c_void) {
let mut ctx = unsafe { &mut *(u as *mut Context) };
if eol == 0 {
@@ -243,28 +247,27 @@ impl Context {
_ => ptr::null_mut(),
};
let vendor_name = match info.proplist().gets("device.vendor.name") {
Some(p) => p.to_owned().into_raw(),
_ => ptr::null_mut(),
};
- let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned();
+ let info_name = unsafe { CStr::from_ptr(info.name) };
let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned();
- let preferred = if info_name == list_data.default_sink_name {
+ let preferred = if *info_name == *list_data.default_sink_name {
cubeb::DEVICE_PREF_ALL
} else {
cubeb::DevicePref::empty()
};
let ctx = &(*list_data.context);
-
- let device_id = info_name.into_raw();
+ let device_id = ctx.devids.borrow_mut().add(info_name);
let friendly_name = info_description.into_raw();
let devinfo = cubeb::DeviceInfo {
device_id: device_id,
devid: device_id as cubeb::DeviceId,
friendly_name: friendly_name,
group_id: group_id,
vendor_name: vendor_name,
devtype: cubeb::DEVICE_TYPE_OUTPUT,
@@ -300,27 +303,27 @@ impl Context {
_ => ptr::null_mut(),
};
let vendor_name = match info.proplist().gets("device.vendor.name") {
Some(p) => p.to_owned().into_raw(),
_ => ptr::null_mut(),
};
- let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned();
+ let info_name = unsafe { CStr::from_ptr(info.name) };
let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned();
- let preferred = if info_name == list_data.default_source_name {
+ let preferred = if *info_name == *list_data.default_source_name {
cubeb::DEVICE_PREF_ALL
} else {
cubeb::DevicePref::empty()
};
let ctx = &(*list_data.context);
- let device_id = info_name.into_raw();
+ let device_id = ctx.devids.borrow_mut().add(info_name);
let friendly_name = info_description.into_raw();
let devinfo = cubeb::DeviceInfo {
device_id: device_id,
devid: device_id as cubeb::DeviceId,
friendly_name: friendly_name,
group_id: group_id,
vendor_name: vendor_name,
devtype: cubeb::DEVICE_TYPE_INPUT,
@@ -354,23 +357,23 @@ impl Context {
if let Some(ref context) = self.context {
self.mainloop.lock();
if let Ok(o) = context.get_server_info(default_device_names, &mut user_data as *mut _ as *mut _) {
self.operation_wait(None, &o);
}
- if devtype == cubeb::DEVICE_TYPE_OUTPUT {
+ if devtype.contains(cubeb::DEVICE_TYPE_OUTPUT) {
if let Ok(o) = context.get_sink_info_list(add_output_device, &mut user_data as *mut _ as *mut _) {
self.operation_wait(None, &o);
}
}
- if devtype == cubeb::DEVICE_TYPE_INPUT {
+ if devtype.contains(cubeb::DEVICE_TYPE_INPUT) {
if let 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();
}
@@ -392,19 +395,16 @@ impl Context {
pub fn device_collection_destroy(&self, collection: *mut cubeb::DeviceCollection) {
debug_assert!(!collection.is_null());
unsafe {
let coll = *collection;
let mut devices = Vec::from_raw_parts(coll.device as *mut cubeb::DeviceInfo,
coll.count,
coll.count);
for dev in devices.iter_mut() {
- if !dev.device_id.is_null() {
- let _ = CString::from_raw(dev.device_id as *mut _);
- }
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 _);
new file mode 100644
--- /dev/null
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/intern.rs
@@ -0,0 +1,58 @@
+// Copyright © 2017 Mozilla Foundation
+//
+// This program is made available under an ISC-style license. See the
+// accompanying file LICENSE for details.
+
+use std::ffi::{CStr, CString};
+use std::os::raw::c_char;
+
+#[derive(Debug)]
+pub struct Intern {
+ vec: Vec<Box<CString>>
+}
+
+impl Intern {
+ pub fn new() -> Intern {
+ Intern {
+ vec: Vec::new()
+ }
+ }
+
+ pub fn add(&mut self, string: &CStr) -> *const c_char {
+ fn eq(s1: &CStr, s2: &CStr) -> bool { s1 == s2 }
+ for s in &self.vec {
+ if eq(s, string) {
+ return s.as_ptr();
+ }
+ }
+
+ self.vec.push(Box::new(string.to_owned()));
+ self.vec.last().unwrap().as_ptr()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::ffi::CStr;
+ use super::Intern;
+
+ #[test]
+ fn intern() {
+ fn cstr(str: &[u8]) -> &CStr {
+ CStr::from_bytes_with_nul(str).unwrap()
+ }
+
+ let mut intern = Intern::new();
+
+ let foo_ptr = intern.add(cstr(b"foo\0"));
+ let bar_ptr = intern.add(cstr(b"bar\0"));
+ assert!(!foo_ptr.is_null());
+ assert!(!bar_ptr.is_null());
+ assert!(foo_ptr != bar_ptr);
+
+ assert!(foo_ptr == intern.add(cstr(b"foo\0")));
+ assert!(foo_ptr != intern.add(cstr(b"fo\0")));
+ assert!(foo_ptr != intern.add(cstr(b"fool\0")));
+ assert!(foo_ptr != intern.add(cstr(b"not foo\0")));
+ }
+}
--- a/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs
@@ -1,22 +1,24 @@
// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license. See the
// accompanying file LICENSE for details.
mod context;
mod cork_state;
mod stream;
+mod intern;
use std::os::raw::c_char;
use std::ffi::CStr;
pub type Result<T> = ::std::result::Result<T, i32>;
pub use self::context::Context;
pub use self::stream::Device;
pub use self::stream::Stream;
+use self::intern::Intern;
// helper to convert *const c_char to Option<CStr>
fn try_cstr_from<'str>(s: *const c_char) -> Option<&'str CStr> {
if s.is_null() { None } else { Some(unsafe { CStr::from_ptr(s) }) }
}
--- a/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs
+++ b/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs
@@ -1,17 +1,17 @@
// Copyright © 2017 Mozilla Foundation
//
// This program is made available under an ISC-style license. See the
// accompanying file LICENSE for details.
use backend::*;
use backend::cork_state::CorkState;
use cubeb;
-use pulse::{self, CVolumeExt, ChannelMapExt, SampleSpecExt, USecExt};
+use pulse::{self, CVolumeExt, ChannelMapExt, SampleSpecExt, StreamLatency, USecExt};
use pulse_ffi::*;
use std::ffi::{CStr, CString};
use std::os::raw::{c_long, c_void};
use std::ptr;
const PULSE_NO_GAIN: f32 = -1.0;
fn cubeb_channel_to_pa_channel(channel: cubeb::Channel) -> pa_channel_position_t {
@@ -410,21 +410,23 @@ impl<'ctx> Stream<'ctx> {
r
}
pub fn latency(&self) -> Result<u32> {
match self.output_stream {
None => Err(cubeb::ERROR),
Some(ref stm) => {
match stm.get_latency() {
- Ok((r_usec, negative)) => {
- debug_assert!(negative);
+ Ok(StreamLatency::Positive(r_usec)) => {
let latency = (r_usec * self.output_sample_spec.rate as pa_usec_t / PA_USEC_PER_SEC) as u32;
Ok(latency)
},
+ Ok(_) => {
+ panic!("Can not handle negative latency values.");
+ },
Err(_) => Err(cubeb::ERROR),
}
},
}
}
pub fn set_volume(&mut self, volume: f32) -> i32 {
match self.output_stream {
@@ -757,19 +759,19 @@ impl<'ctx> Stream<'ctx> {
let r = stm.write(buffer,
got as usize * frame_size,
0,
pulse::SeekMode::Relative);
debug_assert!(r.is_ok());
if (got as usize) < size / frame_size {
let latency = match stm.get_latency() {
- Ok((l, negative)) => {
- assert_ne!(negative, true);
- l
+ Ok(StreamLatency::Positive(l)) => l,
+ Ok(_) => {
+ panic!("Can not handle negative latency values.");
},
Err(e) => {
debug_assert_eq!(e, pulse::ErrorCode::from_error_code(PA_ERR_NODATA));
/* this needs a better guess. */
100 * PA_USEC_PER_MSEC
},
};