Backed out 3 changesets (bug 1670633, bug 1866014) for causing build bustages in MediaEngineWebRTCAudio.cpp CLOSED TREE

Backed out changeset c0d256e9cde9 (bug 1866014)
Backed out changeset e7d101bd73d9 (bug 1670633)
Backed out changeset a849a8e4bd37 (bug 1670633)
This commit is contained in:
Cristian Tuns 2023-11-24 06:18:42 -05:00
parent b9197d615f
commit b54e9ee57c
45 changed files with 663 additions and 1446 deletions

View File

@ -65,9 +65,9 @@ git = "https://github.com/mozilla/audioipc"
rev = "6be424d75f1367e70f2f5ddcacd6d0237e81a6a9"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=964e14628f285ad44522bdeeb566c1864ecd2fd8"]
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=93b5c01a131f65c83c11aeb317f4583405c5eb79"]
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
rev = "964e14628f285ad44522bdeeb566c1864ecd2fd8"
rev = "93b5c01a131f65c83c11aeb317f4583405c5eb79"
replace-with = "vendored-sources"
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=cf48897be5cbe147d051ebbbe1eaf5fd8fb6bbc9"]

28
Cargo.lock generated
View File

@ -432,14 +432,14 @@ dependencies = [
name = "bindgen"
version = "0.66.999"
dependencies = [
"bindgen 0.69.1",
"bindgen 0.68.1",
]
[[package]]
name = "bindgen"
version = "0.69.1"
version = "0.68.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"
checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078"
dependencies = [
"bitflags 2.4.0",
"cexpr",
@ -584,7 +584,7 @@ dependencies = [
name = "builtins-static"
version = "0.1.0"
dependencies = [
"bindgen 0.69.1",
"bindgen 0.68.1",
"mozilla-central-workspace-hack",
"nom",
"pkcs11-bindings",
@ -885,17 +885,17 @@ dependencies = [
[[package]]
name = "coreaudio-sys"
version = "0.2.14"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3120ebb80a9de008e638ad833d4127d50ea3d3a960ea23ea69bc66d9358a028"
checksum = "d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d"
dependencies = [
"bindgen 0.69.1",
"bindgen 0.68.1",
]
[[package]]
name = "coreaudio-sys-utils"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=964e14628f285ad44522bdeeb566c1864ecd2fd8#964e14628f285ad44522bdeeb566c1864ecd2fd8"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=93b5c01a131f65c83c11aeb317f4583405c5eb79#93b5c01a131f65c83c11aeb317f4583405c5eb79"
dependencies = [
"core-foundation-sys",
"coreaudio-sys",
@ -1106,11 +1106,11 @@ dependencies = [
[[package]]
name = "cubeb-coreaudio"
version = "0.1.0"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=964e14628f285ad44522bdeeb566c1864ecd2fd8#964e14628f285ad44522bdeeb566c1864ecd2fd8"
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=93b5c01a131f65c83c11aeb317f4583405c5eb79#93b5c01a131f65c83c11aeb317f4583405c5eb79"
dependencies = [
"atomic",
"audio-mixer",
"bitflags 2.4.0",
"bitflags 1.999.999",
"coreaudio-sys-utils",
"cubeb-backend",
"float-cmp",
@ -2020,7 +2020,7 @@ name = "gecko-profiler"
version = "0.1.0"
dependencies = [
"bincode",
"bindgen 0.69.1",
"bindgen 0.68.1",
"lazy_static",
"mozbuild",
"profiler-macros",
@ -2562,7 +2562,7 @@ name = "http3server"
version = "0.1.1"
dependencies = [
"base64 0.21.3",
"bindgen 0.69.1",
"bindgen 0.68.1",
"cfg-if 1.0.0",
"http",
"hyper",
@ -3632,7 +3632,7 @@ name = "mozilla-central-workspace-hack"
version = "0.1.0"
dependencies = [
"arrayvec",
"bindgen 0.69.1",
"bindgen 0.68.1",
"bitflags 2.4.0",
"bytes",
"chrono",
@ -5234,7 +5234,7 @@ dependencies = [
"app_units",
"arrayvec",
"atomic_refcell",
"bindgen 0.69.1",
"bindgen 0.68.1",
"bitflags 2.4.0",
"byteorder",
"cssparser",

View File

@ -137,7 +137,7 @@ wasi = { path = "build/rust/wasi" }
# else we do use requires backtrace, so dummy it out for now.
backtrace = { path = "build/rust/backtrace" }
# Patch bindgen 0.63, 0.64 and 0.66 to 0.69
# Patch bindgen 0.63, 0.64 and 0.66 to 0.68
bindgen_0_63 = { package = "bindgen", path = "build/rust/bindgen-0.63" }
bindgen_0_64 = { package = "bindgen", path = "build/rust/bindgen-0.64" }
bindgen = { path = "build/rust/bindgen" }

View File

@ -8,7 +8,7 @@ license = "BSD-3-Clause"
path = "lib.rs"
[dependencies.bindgen]
version = "0.69.0"
version = "0.68.0"
default-features = false
[features]

View File

@ -52,7 +52,7 @@ uuid = { version = "1", features = ["serde", "v4"], optional = true }
scopeguard = { version = "1", optional = true }
[build-dependencies]
bindgen = { version = "0.69", default-features = false, features = ["runtime"], optional = true }
bindgen = { version = "0.68", default-features = false, features = ["runtime"], optional = true }
libc = "0.2"
memchr = { version = "2", optional = true }
nom = { version = "7", optional = true }

View File

@ -323,15 +323,8 @@ void MediaEngineWebRTCMicrophoneSource::SetTrack(
mTrack = aTrack->AsAudioProcessingTrack();
mPrincipal = aPrincipal;
#if defined(XP_MACOSX) && defined(NIGHTLY_BUILD)
mInputProcessing = MakeAndAddRef<AudioInputProcessing>(1);
#else
# if !defined(NIGHTLY_BUILD)
# error "Must remove this quick fix to bug 1866014 before reaching beta"
# endif
mInputProcessing =
MakeAndAddRef<AudioInputProcessing>(mDeviceMaxChannelCount);
#endif
NS_DispatchToMainThread(NS_NewRunnableFunction(
__func__, [track = mTrack, processing = mInputProcessing]() mutable {

View File

@ -28,7 +28,7 @@ features = ["gecko"]
# Make sure to use bindgen's runtime-loading of libclang, as it allows for a wider range of clang versions to be used
[build-dependencies]
bindgen = {version = "0.69", default-features = false, features = ["runtime"] }
bindgen = {version = "0.68", default-features = false, features = ["runtime"] }
[[bin]]
name = "http3server"

View File

@ -11,7 +11,7 @@ smallvec = { version = "1.9.0", features = ["const_new"] }
mozilla-central-workspace-hack = { version = "0.1", features = ["builtins-static"], optional = true }
[build-dependencies]
bindgen = { default-features = false, features = ["runtime"], version = "0.69" }
bindgen = { default-features = false, features = ["runtime"], version = "0.68" }
nom = "7.1.1"
[lib]

View File

@ -84,7 +84,7 @@ gecko-profiler = { path = "../../../tools/profiler/rust-api" }
[build-dependencies]
lazy_static = "1"
log = { version = "0.4", features = ["std"] }
bindgen = {version = "0.69", optional = true, default-features = false}
bindgen = {version = "0.68", optional = true, default-features = false}
regex = {version = "1.0", optional = true, default-features = false, features = ["perf", "std"]}
walkdir = "2.1.4"
toml = {version = "0.5", optional = true, default-features = false}

View File

@ -681,11 +681,6 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.66.1 -> 0.68.1"
[[audits.bindgen]]
who = "Andreas Pehrson <apehrson@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.68.1 -> 0.69.1"
[[audits.bit-set]]
who = "Aria Beingessner <a.beingessner@gmail.com>"
criteria = "safe-to-deploy"
@ -886,11 +881,6 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.2.12 -> 0.2.13"
[[audits.coreaudio-sys]]
who = "Andreas Pehrson <apehrson@mozilla.com>"
criteria = "safe-to-deploy"
delta = "0.2.13 -> 0.2.14"
[[audits.cose]]
who = "Mathew Hodson <mathew.hodson@gmail.com>"
criteria = "safe-to-deploy"

File diff suppressed because one or more lines are too long

View File

@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.60.0"
name = "bindgen"
version = "0.69.1"
version = "0.68.1"
authors = [
"Jyun-Yan You <jyyou.tw@gmail.com>",
"Emilio Cobos Álvarez <emilio@crisal.io>",
@ -41,25 +41,8 @@ repository = "https://github.com/rust-lang/rust-bindgen"
features = ["experimental"]
[package.metadata.release]
pre-release-hook = [
"../node_modules/doctoc/doctoc.js",
"../CHANGELOG.md",
]
release = true
[[package.metadata.release.pre-release-replacements]]
file = "../CHANGELOG.md"
replace = """
# Unreleased
## Added
## Changed
## Removed
## Fixed
## Security
# {{version}} ({{date}})"""
search = "# Unreleased"
[lib]
name = "bindgen"
path = "lib.rs"

View File

@ -99,9 +99,6 @@ pub trait ParseCallbacks: fmt::Debug {
None
}
/// This will be called on every header filename passed to (`Builder::header`)[`crate::Builder::header`].
fn header_file(&self, _filename: &str) {}
/// This will be called on every file inclusion, with the full path of the included file.
fn include_file(&self, _filename: &str) {}

View File

@ -1820,7 +1820,7 @@ impl TranslationUnit {
let fname = CString::new(file).unwrap();
let _c_args: Vec<CString> = cmd_args
.iter()
.map(|s| CString::new(s.as_bytes()).unwrap())
.map(|s| CString::new(s.clone().into_boxed_bytes()).unwrap())
.collect();
let c_args: Vec<*const c_char> =
_c_args.iter().map(|s| s.as_ptr()).collect();

View File

@ -14,36 +14,25 @@ pub(crate) enum Error {
/// Function ABI is not supported.
UnsupportedAbi(&'static str),
/// The pointer type size does not match the target's pointer size.
InvalidPointerSize {
ty_name: String,
ty_size: usize,
ptr_size: usize,
},
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
f.write_str(match *self {
Error::NoLayoutForOpaqueBlob => {
"Tried to generate an opaque blob, but had no layout.".fmt(f)
"Tried to generate an opaque blob, but had no layout."
}
Error::InstantiationOfOpaqueType => {
"Instantiation of opaque template type or partial template specialization."
.fmt(f)
}
Error::UnsupportedAbi(abi) => {
write!(
return write!(
f,
"{} ABI is not supported by the configured Rust target.",
abi
)
}
Error::InvalidPointerSize { ty_name, ty_size, ptr_size } => {
write!(f, "The {} pointer type has size {} but the current target's pointer size is {}.", ty_name, ty_size, ptr_size)
}
}
})
}
}

View File

@ -21,7 +21,6 @@ use self::struct_layout::StructLayoutTracker;
use super::BindgenOptions;
use crate::callbacks::{DeriveInfo, FieldInfo, TypeKind as DeriveTypeKind};
use crate::codegen::error::Error;
use crate::ir::analysis::{HasVtable, Sizedness};
use crate::ir::annotations::{
Annotations, FieldAccessorKind, FieldVisibilityKind,
@ -3924,16 +3923,6 @@ impl TryToRustTy for Type {
}
TypeKind::Opaque => self.try_to_opaque(ctx, item),
TypeKind::Pointer(inner) | TypeKind::Reference(inner) => {
// Check that this type has the same size as the target's pointer type.
let size = self.get_layout(ctx, item).size;
if size != ctx.target_pointer_size() {
return Err(Error::InvalidPointerSize {
ty_name: self.name().unwrap_or("unknown").into(),
ty_size: size,
ptr_size: ctx.target_pointer_size(),
});
}
let is_const = ctx.resolve_type(inner).is_const();
let inner =

View File

@ -322,26 +322,21 @@ impl<'a> CSerialize<'a> for Type {
}
write!(writer, ")")?;
let args = signature.argument_types();
if args.is_empty() {
write!(writer, " (void)")?;
} else {
write!(writer, " (")?;
serialize_sep(
", ",
args.iter(),
ctx,
writer,
|(name, type_id), ctx, buf| {
let mut stack = vec![];
if let Some(name) = name {
stack.push(name.clone());
}
type_id.serialize(ctx, (), &mut stack, buf)
},
)?;
write!(writer, ")")?
}
write!(writer, " (")?;
serialize_sep(
", ",
signature.argument_types().iter(),
ctx,
writer,
|(name, type_id), ctx, buf| {
let mut stack = vec![];
if let Some(name) = name {
stack.push(name.clone());
}
type_id.serialize(ctx, (), &mut stack, buf)
},
)?;
write!(writer, ")")?
}
TypeKind::ResolvedTypeRef(type_id) => {
if self.is_const() {

View File

@ -334,13 +334,20 @@ mod tests {
// Yes, what follows is a **terribly** inefficient set union
// implementation. Don't copy this code outside of this test!
let original_size = self.reachable.entry(node).or_default().len();
let original_size = self
.reachable
.entry(node)
.or_insert_with(HashSet::default)
.len();
for sub_node in self.graph.0[&node].iter() {
self.reachable.get_mut(&node).unwrap().insert(*sub_node);
let sub_reachable =
self.reachable.entry(*sub_node).or_default().clone();
let sub_reachable = self
.reachable
.entry(*sub_node)
.or_insert_with(HashSet::default)
.clone();
for transitive in sub_reachable {
self.reachable.get_mut(&node).unwrap().insert(transitive);

View File

@ -98,13 +98,13 @@ pub(crate) trait ItemAncestors {
fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
}
#[cfg(feature = "__testing_only_extra_assertions")]
#[cfg(__testing_only_extra_assertions)]
type DebugOnlyItemSet = ItemSet;
#[cfg(not(feature = "__testing_only_extra_assertions"))]
#[cfg(not(__testing_only_extra_assertions))]
struct DebugOnlyItemSet;
#[cfg(not(feature = "__testing_only_extra_assertions"))]
#[cfg(not(__testing_only_extra_assertions))]
impl DebugOnlyItemSet {
fn new() -> Self {
DebugOnlyItemSet

View File

@ -253,24 +253,11 @@ impl ObjCMethod {
let split_name: Vec<Option<Ident>> = self
.name
.split(':')
.enumerate()
.map(|(idx, name)| {
.map(|name| {
if name.is_empty() {
None
} else if idx == 0 {
// Try to parse the method name as an identifier. Having a keyword is ok
// unless it is `crate`, `self`, `super` or `Self`, so we try to add the `_`
// suffix to it and parse it.
if ["crate", "self", "super", "Self"].contains(&name) {
Some(Ident::new(
&format!("{}_", name),
Span::call_site(),
))
} else {
Some(Ident::new(name, Span::call_site()))
}
} else {
// Try to parse the current joining name as an identifier. This might fail if the name
// Try to parse the current name as an identifier. This might fail if the name
// is a keyword, so we try to "r#" to it and parse again, this could also fail
// if the name is `crate`, `self`, `super` or `Self`, so we try to add the `_`
// suffix to it and parse again. If this also fails, we panic with the first

View File

@ -325,11 +325,6 @@ impl Builder {
.map(String::into_boxed_str),
);
for header in &self.options.input_headers {
self.options
.for_each_callback(|cb| cb.header_file(header.as_ref()));
}
// Transform input headers to arguments on the clang command line.
self.options.clang_args.extend(
self.options.input_headers
@ -571,10 +566,6 @@ impl BindgenOptions {
.collect()
}
fn for_each_callback(&self, f: impl Fn(&dyn callbacks::ParseCallbacks)) {
self.parse_callbacks.iter().for_each(|cb| f(cb.as_ref()));
}
fn process_comment(&self, comment: &str) -> String {
let comment = comment::preprocess(comment);
self.parse_callbacks
@ -1241,50 +1232,9 @@ fn get_target_dependent_env_var(
/// .generate();
/// ```
#[derive(Debug)]
pub struct CargoCallbacks {
rerun_on_header_files: bool,
}
/// Create a new `CargoCallbacks` value with [`CargoCallbacks::rerun_on_header_files`] disabled.
///
/// This constructor has been deprecated in favor of [`CargoCallbacks::new`] where
/// [`CargoCallbacks::rerun_on_header_files`] is enabled by default.
#[deprecated = "Use `CargoCallbacks::new()` instead. Please, check the documentation for further information."]
pub const CargoCallbacks: CargoCallbacks = CargoCallbacks {
rerun_on_header_files: false,
};
impl CargoCallbacks {
/// Create a new `CargoCallbacks` value.
pub fn new() -> Self {
Self {
rerun_on_header_files: true,
}
}
/// Whether Cargo should re-run the build script if any of the input header files has changed.
///
/// This option is enabled by default unless the deprecated [`const@CargoCallbacks`]
/// constructor is used.
pub fn rerun_on_header_files(mut self, doit: bool) -> Self {
self.rerun_on_header_files = doit;
self
}
}
impl Default for CargoCallbacks {
fn default() -> Self {
Self::new()
}
}
pub struct CargoCallbacks;
impl callbacks::ParseCallbacks for CargoCallbacks {
fn header_file(&self, filename: &str) {
if self.rerun_on_header_files {
println!("cargo:rerun-if-changed={}", filename);
}
}
fn include_file(&self, filename: &str) {
println!("cargo:rerun-if-changed={}", filename);
}

View File

@ -1374,7 +1374,7 @@ options! {
/// or `-fno-inline-functions` if you are responsible of compiling the library to make
/// them callable.
#[cfg_attr(
feature = "experimental",
features = "experimental",
doc = "\nCheck the [`Builder::wrap_static_fns`] method for an alternative."
)]
pub fn generate_inline_functions(mut self, doit: bool) -> Self {

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"87292d055a2fc0f070f54abd549a5f79ec8ac33611ecde80ba394f256b88294c","src/aggregate_device.rs":"7d2bd5f5fd7f3d008ebb69ad81f522ca0cb73db6d7b3e50ed1a63ea26ff721f4","src/audio_object.rs":"5447179330a862659a25bceedfdc5d29a1296f63490908d1c868c6b21c5f95a1","src/audio_unit.rs":"d783878930df4923b57ad230138c0f3fd6b0b9bb80a39725092ff4c6615162d8","src/cf_mutable_dict.rs":"fc42edd270c6dfb02f123214d2d8e487bbd62b5bd923b71eec13190fd0104d2a","src/dispatch.rs":"f6267fe587217c3d3ad5fe7f3a35955221c936103bf853c477a2e44eba5f1e46","src/lib.rs":"bcc559d69ef6ed0cbea5b2a36fec89d8c011eb9da70e2f26c00f881ad97a2546","src/string.rs":"28f88b816c768bcfcc674a60d962b93f1c94e5e0f4cc8ed2a1301138b91039e7"},"package":null}
{"files":{"Cargo.toml":"d15a17e76eddf5088ad0b09544704479b3269ef1bc9060118bda7e87ed499eab","src/aggregate_device.rs":"7d2bd5f5fd7f3d008ebb69ad81f522ca0cb73db6d7b3e50ed1a63ea26ff721f4","src/audio_object.rs":"5447179330a862659a25bceedfdc5d29a1296f63490908d1c868c6b21c5f95a1","src/audio_unit.rs":"d783878930df4923b57ad230138c0f3fd6b0b9bb80a39725092ff4c6615162d8","src/cf_mutable_dict.rs":"fc42edd270c6dfb02f123214d2d8e487bbd62b5bd923b71eec13190fd0104d2a","src/dispatch.rs":"82ca429be8f930db730c7c571d6f2246e59e82ecb220b5290a3cf4a53e997053","src/lib.rs":"bcc559d69ef6ed0cbea5b2a36fec89d8c011eb9da70e2f26c00f881ad97a2546","src/string.rs":"28f88b816c768bcfcc674a60d962b93f1c94e5e0f4cc8ed2a1301138b91039e7"},"package":null}

View File

@ -20,10 +20,9 @@ license = "ISC"
version = "0.8"
[dependencies.coreaudio-sys]
version = "0.2.14"
version = "0.2"
features = [
"audio_unit",
"core_audio",
"io_kit_audio",
]
default-features = false

View File

@ -22,16 +22,6 @@ impl Queue {
queue
}
#[cfg(debug_assertions)]
pub fn debug_assert_is_current(&self) {
unsafe {
dispatch_assert_queue(self.0);
}
}
#[cfg(not(debug_assertions))]
pub fn debug_assert_is_current(&self) {}
pub fn run_async<F>(&self, work: F)
where
F: Send + FnOnce(),

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"21b0b00002a9b66a31357ddc5ac4c0f2a1702c85f6303cc7309e9dc7ffcaefd8","LICENSE":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"a8adeaf1947035175b890109b36604ac3676f887911b5b8debd216689c0b65bd","build.rs":"d109f0a043b4f62bee52674888a52595f9b0dc37345815905a12ad0723ab8de5","src/lib.rs":"22c9dbbb1dc38d6f77b9362e806a7ee59a8ca1aa9b2c9344d1a487a91287ed59"},"package":"f3120ebb80a9de008e638ad833d4127d50ea3d3a960ea23ea69bc66d9358a028"}
{"files":{"Cargo.toml":"17c9796d79b692e07056a6f6b45fcb8160c98385d9dd46c3a3d67a02865b3d33","LICENSE":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"a8adeaf1947035175b890109b36604ac3676f887911b5b8debd216689c0b65bd","build.rs":"e3d45b1a17b655996a09b1d8f5f4dabb8c574e5b803814a13494f56dfce32f4e","src/lib.rs":"22c9dbbb1dc38d6f77b9362e806a7ee59a8ca1aa9b2c9344d1a487a91287ed59"},"package":"d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d"}

View File

@ -11,7 +11,7 @@
[package]
name = "coreaudio-sys"
version = "0.2.14"
version = "0.2.13"
authors = ["Mitchell Nordine <mitchell.nordine@gmail.com>"]
build = "build.rs"
description = "Bindings for Apple's CoreAudio frameworks generated via rust-bindgen"
@ -36,7 +36,7 @@ targets = [
]
[build-dependencies.bindgen]
version = "0.69"
version = "0.68"
features = ["runtime"]
default-features = false
@ -52,5 +52,4 @@ default = [
"open_al",
"core_midi",
]
io_kit_audio = []
open_al = []

View File

@ -86,13 +86,6 @@ fn build(sdk_path: Option<&str>, target: &str) {
}
}
#[cfg(feature = "io_kit_audio")]
{
assert!(target.contains("apple-darwin"));
println!("cargo:rustc-link-lib=framework=IOKit");
headers.push("IOKit/audio/IOAudioTypes.h");
}
#[cfg(feature = "open_al")]
{
println!("cargo:rustc-link-lib=framework=OpenAL");

View File

@ -1 +1 @@
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"4d868f1f8698945fb84b9700926f5d6800d003d289d5ae773bcfaaaeb436b45e","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"d717e598c96e4911d9494b18382d6bd3a8d5038b7d68d3166ad4336e237a97d8","run_sanitizers.sh":"d6c3cde105ae0759e753cc31cab691eb417c4d0ad68f20da5e87fe0138a0d92f","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"43511107ba2a75a19340ac663c981362ca1b75b679b6c295d88b5035bd7e3619","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"314c3404f1a44f8c23856f96510779e7e64ebb7dde5abe444946c16d04af7c29","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"ed299d3954e2a823060c870a8244673a7d4bca530830cb66b964d047a80ee3af","src/backend/mod.rs":"21ca892ccd925991e7f4877a5ac1b8e70a5f4785e7d498024965c46eabdd3033","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"e3f94e118e1dd47941fbba4417de40bddc4254d9f06b1e938f58d8f1aa566a5c","src/backend/tests/api.rs":"566546bec17220641960342374516da3baf6032a8843ac7a6c1f0b1cb8911594","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"b1b4f7f71de99d07406a8a38dc67e46a43b883d4a845daaf356e72fbe0d5a08b","src/backend/tests/device_property.rs":"ea0be5f8834be494cb33f854ce9d334b5763dc5287f949bcb4bd025d8a8b2d3b","src/backend/tests/interfaces.rs":"c8ca26d0fd098b8a230d9aa8d67a062da2ab3ac0f868739485c793618fc75700","src/backend/tests/manual.rs":"8d485a6666a3f4518b03e39dab80bf2acfd760af2d2f43bad99023cb135b38ca","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"504613b1b5fa4d67cbb2560cb8d8cef0a4e8929c28b31d9d4695ac5286969f38","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"7d74298435260566838ece9a84ee42e4a02c16683f5434d7ba2671a9acf4424f","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"aa1998a3b104ad131805ca3513832cef3f65300192824f8b1efc9a5a0cc108f6",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"b82f0d73e2afde65c328c9263c7e4ff3f53fe1671e5fc9a96ced50fb12698933","LICENSE":"6e6f56aff5bbf3cbc60747e152fb1a719bd0716aaf6d711c554f57d92e96297c","README.md":"0007782a05a5330f739ad789c19c82562c82e32386b0447000fc72c0d48405bc","build-audiounit-rust-in-cubeb.sh":"d228a05985dcd02ec1ecac66a2b64dae5a530804a25a7054ccc95905aedfb7ef","install_git_hook.sh":"d38c8e51e636f6b90b489621ac34ccd1d1b1f40dccce3d178ed1da1c5068f16d","install_rustfmt_clippy.sh":"4ae90d8dcb9757cb3ae4ae142ef80e5377c0dde61c63f4a3c32418646e80ca7b","run_device_tests.sh":"cac9a7d588c2be0efa842c15d24c8cf0573bc9f9d73011662ba764dc9f6245e8","run_sanitizers.sh":"8828c73439dfd540cd21fc713c4a1011ec05baca6f282f285743f310ace39563","run_tests.sh":"916a7ae4a406d2274417d6eca939a878db5adcb6144e5680d9d148bf90178f1c","src/backend/aggregate_device.rs":"e822b4496e2ea5c6e1a288c6e92f57e598abf67cb0bdff813f859d57c63be5f9","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"314c3404f1a44f8c23856f96510779e7e64ebb7dde5abe444946c16d04af7c29","src/backend/device_property.rs":"2a63837b98b9b6bfb314b4aa6dce919412b71e13e18c7b8f3477aa1482f70b29","src/backend/mixer.rs":"ed299d3954e2a823060c870a8244673a7d4bca530830cb66b964d047a80ee3af","src/backend/mod.rs":"c1d4c753d30fc5e6f2aafcd5d34c3ae2393e0bae4aeb5bc477af396014ec1877","src/backend/resampler.rs":"8641c672d00f77be287d64f6cd4a2b2cd36f8630e2ded1eff6b39834b1b7ddc3","src/backend/tests/aggregate_device.rs":"7542cbb1c82398d00a5cba5b335842c517af2cda887946ebb5aaf512fd06b527","src/backend/tests/api.rs":"2cbae3a49f39fc78ec379c8c0c0266ad3e3552ef22b42168ac9d62d9d983a4a7","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"97555244a8081251f1447c6a677609d1e91f33c9c0f4fb3f8a4082005c68ae0c","src/backend/tests/device_property.rs":"373f76d3bee83b263db3f02be3b94b408bdf852d84e4b5153273fda34b11a374","src/backend/tests/interfaces.rs":"9ed857625147c3d13c1458e630db8a78362612e6ef679d918bfdafa6e927fe75","src/backend/tests/manual.rs":"8d485a6666a3f4518b03e39dab80bf2acfd760af2d2f43bad99023cb135b38ca","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"f9e1883660d6146b6e5075806561f5f689810e25c5e7764dfd28c9b939821a49","src/backend/tests/tone.rs":"779cc14fc2a362bf7f26ce66ad70c0639501176175655a99b7fefb3c59d56c7a","src/backend/tests/utils.rs":"3c430e519c0e7a17dda6b57c110fab725a846da39606fd99274bad20a637cf35","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}

View File

@ -28,7 +28,7 @@ crate-type = [
[dependencies]
atomic = "0.4"
audio-mixer = "0.1"
bitflags = "2"
bitflags = "1.0"
cubeb-backend = "0.10.3"
float-cmp = "0.6"
lazy_static = "1.2"
@ -39,6 +39,3 @@ triple_buffer = "5.0.5"
[dependencies.coreaudio-sys-utils]
path = "coreaudio-sys-utils"
[dev-dependencies]
itertools = "0.11"

View File

@ -24,17 +24,21 @@ cargo test test_suspend_input_stream_by_unplugging_a_nondefault_input_device --
cargo test test_destroy_input_stream_after_unplugging_a_default_input_device -- --ignored --nocapture
cargo test test_reinit_input_stream_by_unplugging_a_default_input_device -- --ignored --nocapture
cargo test test_destroy_output_stream_after_unplugging_a_nondefault_output_device -- --ignored --nocapture
cargo test test_suspend_output_stream_by_unplugging_a_nondefault_output_device -- --ignored --nocapture
# FIXME: We don't monitor the alive-status for output device currently
# cargo test test_destroy_output_stream_after_unplugging_a_nondefault_output_device -- --ignored --nocapture
# FIXME: We don't monitor the alive-status for output device currently
# cargo test test_suspend_output_stream_by_unplugging_a_nondefault_output_device -- --ignored --nocapture
cargo test test_destroy_output_stream_after_unplugging_a_default_output_device -- --ignored --nocapture
cargo test test_reinit_output_stream_by_unplugging_a_default_output_device -- --ignored --nocapture
cargo test test_destroy_duplex_stream_after_unplugging_a_nondefault_input_device -- --ignored --nocapture
cargo test test_suspend_duplex_stream_by_unplugging_a_nondefault_input_device -- --ignored --nocapture
cargo test test_suspend_duplex_stream_by_unplugging_a_nondefault_input_device
cargo test test_destroy_duplex_stream_after_unplugging_a_nondefault_output_device -- --ignored --nocapture
cargo test test_suspend_duplex_stream_by_unplugging_a_nondefault_output_device -- --ignored --nocapture
# FIXME: We don't monitor the alive-status for output device currently
# cargo test test_destroy_duplex_stream_after_unplugging_a_nondefault_output_device -- --ignored --nocapture
# FIXME: We don't monitor the alive-status for output device currently
# cargo test test_suspend_duplex_stream_by_unplugging_a_nondefault_output_device -- --ignored --nocapture
cargo test test_destroy_duplex_stream_after_unplugging_a_default_input_device -- --ignored --nocapture
cargo test test_reinit_duplex_stream_by_unplugging_a_default_input_device -- --ignored --nocapture

View File

@ -15,7 +15,8 @@ fi
# - `memory`: It doesn't works with target x86_64-apple-darwin
# - `leak`: Get some errors that are out of our control. See:
# https://github.com/mozilla/cubeb-coreaudio-rs/issues/45#issuecomment-591642931
sanitizers=("address" "thread")
# - `thread`: It's blocked by #129
sanitizers=("address")
for san in "${sanitizers[@]}"
do
San="$(tr '[:lower:]' '[:upper:]' <<< ${san:0:1})${san:1}"

View File

@ -180,7 +180,7 @@ impl AggregateDevice {
let device = Self::create_blank_device(plugin_id)?;
// Wait until the aggregate is created.
let (lock, cvar) = &*condvar_pair;
let &(ref lock, ref cvar) = &*condvar_pair;
let devices = lock.lock().unwrap();
if !devices.contains(&device) {
let (devs, timeout_res) = cvar.wait_timeout(devices, waiting_time).unwrap();
@ -203,7 +203,7 @@ impl AggregateDevice {
) -> OSStatus {
assert_eq!(id, kAudioObjectSystemObject);
let pair = unsafe { &mut *(data as *mut Arc<(Mutex<Vec<AudioObjectID>>, Condvar)>) };
let (lock, cvar) = &**pair;
let &(ref lock, ref cvar) = &**pair;
let mut devices = lock.lock().unwrap();
*devices = audiounit_get_devices();
cvar.notify_one();
@ -339,7 +339,7 @@ impl AggregateDevice {
Self::set_sub_devices(device_id, input_id, output_id)?;
// Wait until the sub devices are added.
let (lock, cvar) = &*condvar_pair;
let &(ref lock, ref cvar) = &*condvar_pair;
let device = lock.lock().unwrap();
if *device != device_id {
let (dev, timeout_res) = cvar.wait_timeout(device, waiting_time).unwrap();
@ -370,7 +370,7 @@ impl AggregateDevice {
data: *mut c_void,
) -> OSStatus {
let pair = unsafe { &mut *(data as *mut Arc<(Mutex<AudioObjectID>, Condvar)>) };
let (lock, cvar) = &**pair;
let &(ref lock, ref cvar) = &**pair;
let mut device = lock.lock().unwrap();
*device = id;
cvar.notify_one();

View File

@ -223,49 +223,13 @@ pub fn get_ranges_of_device_sample_rate(
}
}
pub fn get_stream_latency(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
assert_ne!(id, kAudioObjectUnknown);
let address = get_property_address(
Property::StreamLatency,
DeviceType::INPUT | DeviceType::OUTPUT,
);
let mut size = mem::size_of::<u32>();
let mut latency: u32 = 0;
let err = audio_object_get_property_data(id, &address, &mut size, &mut latency);
if err == NO_ERR {
Ok(latency)
} else {
Err(err)
}
}
pub fn get_stream_terminal_type(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
assert_ne!(id, kAudioObjectUnknown);
let address = get_property_address(
Property::StreamTerminalType,
DeviceType::INPUT | DeviceType::OUTPUT,
);
let mut size = mem::size_of::<u32>();
let mut terminal_type: u32 = 0;
let err = audio_object_get_property_data(id, &address, &mut size, &mut terminal_type);
if err == NO_ERR {
Ok(terminal_type)
} else {
Err(err)
}
}
pub fn get_stream_virtual_format(
id: AudioStreamID,
pub fn get_device_stream_format(
id: AudioDeviceID,
devtype: DeviceType,
) -> std::result::Result<AudioStreamBasicDescription, OSStatus> {
assert_ne!(id, kAudioObjectUnknown);
let address = get_property_address(
Property::StreamVirtualFormat,
DeviceType::INPUT | DeviceType::OUTPUT,
);
let address = get_property_address(Property::DeviceStreamFormat, devtype);
let mut size = mem::size_of::<AudioStreamBasicDescription>();
let mut format = AudioStreamBasicDescription::default();
let err = audio_object_get_property_data(id, &address, &mut size, &mut format);
@ -276,6 +240,51 @@ pub fn get_stream_virtual_format(
}
}
#[allow(clippy::cast_ptr_alignment)] // Allow casting *mut u8 to *mut AudioBufferList
pub fn get_device_stream_configuration(
id: AudioDeviceID,
devtype: DeviceType,
) -> std::result::Result<Vec<AudioBuffer>, OSStatus> {
assert_ne!(id, kAudioObjectUnknown);
let address = get_property_address(Property::DeviceStreamConfiguration, devtype);
let mut size: usize = 0;
let err = audio_object_get_property_data_size(id, &address, &mut size);
if err != NO_ERR {
return Err(err);
}
let mut data: Vec<u8> = allocate_array_by_size(size);
let ptr = data.as_mut_ptr() as *mut AudioBufferList;
let err = audio_object_get_property_data(id, &address, &mut size, ptr);
if err != NO_ERR {
return Err(err);
}
let list = unsafe { &(*ptr) };
let ptr = list.mBuffers.as_ptr() as *const AudioBuffer;
let len = list.mNumberBuffers as usize;
let buffers = unsafe { slice::from_raw_parts(ptr, len) };
Ok(buffers.to_vec())
}
pub fn get_stream_latency(
id: AudioStreamID,
devtype: DeviceType,
) -> std::result::Result<u32, OSStatus> {
assert_ne!(id, kAudioObjectUnknown);
let address = get_property_address(Property::StreamLatency, devtype);
let mut size = mem::size_of::<u32>();
let mut latency: u32 = 0;
let err = audio_object_get_property_data(id, &address, &mut size, &mut latency);
if err == NO_ERR {
Ok(latency)
} else {
Err(err)
}
}
pub fn get_clock_domain(
id: AudioStreamID,
devtype: DeviceType,
@ -303,6 +312,8 @@ pub enum Property {
DeviceSampleRates,
DeviceSource,
DeviceSourceName,
DeviceStreamConfiguration,
DeviceStreamFormat,
DeviceStreams,
DeviceUID,
HardwareDefaultInputDevice,
@ -310,8 +321,6 @@ pub enum Property {
HardwareDevices,
ModelUID,
StreamLatency,
StreamTerminalType,
StreamVirtualFormat,
TransportType,
ClockDomain,
}
@ -328,6 +337,8 @@ impl From<Property> for AudioObjectPropertySelector {
Property::DeviceSampleRates => kAudioDevicePropertyAvailableNominalSampleRates,
Property::DeviceSource => kAudioDevicePropertyDataSource,
Property::DeviceSourceName => kAudioDevicePropertyDataSourceNameForIDCFString,
Property::DeviceStreamConfiguration => kAudioDevicePropertyStreamConfiguration,
Property::DeviceStreamFormat => kAudioDevicePropertyStreamFormat,
Property::DeviceStreams => kAudioDevicePropertyStreams,
Property::DeviceUID => kAudioDevicePropertyDeviceUID,
Property::HardwareDefaultInputDevice => kAudioHardwarePropertyDefaultInputDevice,
@ -335,8 +346,6 @@ impl From<Property> for AudioObjectPropertySelector {
Property::HardwareDevices => kAudioHardwarePropertyDevices,
Property::ModelUID => kAudioDevicePropertyModelUID,
Property::StreamLatency => kAudioStreamPropertyLatency,
Property::StreamTerminalType => kAudioStreamPropertyTerminalType,
Property::StreamVirtualFormat => kAudioStreamPropertyVirtualFormat,
Property::TransportType => kAudioDevicePropertyTransportType,
Property::ClockDomain => kAudioDevicePropertyClockDomain,
}

File diff suppressed because it is too large Load Diff

View File

@ -19,13 +19,15 @@ impl Resampler {
reclock: ffi::cubeb_resampler_reclock,
) -> Self {
let raw_resampler = unsafe {
let in_params = match &mut input_params {
Some(p) => p,
None => ptr::null_mut(),
let in_params = if input_params.is_some() {
input_params.as_mut().unwrap() as *mut ffi::cubeb_stream_params
} else {
ptr::null_mut()
};
let out_params = match &mut output_params {
Some(p) => p,
None => ptr::null_mut(),
let out_params = if output_params.is_some() {
output_params.as_mut().unwrap() as *mut ffi::cubeb_stream_params
} else {
ptr::null_mut()
};
ffi::cubeb_resampler_create(
stream,

View File

@ -42,7 +42,7 @@ fn test_aggregate_set_sub_devices_for_unknown_devices() {
// application and print out the sub devices of them!
#[test]
fn test_aggregate_get_sub_devices() {
let devices = test_get_all_devices(DeviceFilter::ExcludeCubebAggregateAndVPIO);
let devices = test_get_all_devices(DeviceFilter::ExcludeCubebAggregate);
for device in devices {
// `AggregateDevice::get_sub_devices(device)` will return a single-element vector
// containing `device` itself if it's not an aggregate device. This test assumes devices
@ -108,7 +108,7 @@ fn test_aggregate_create_blank_device() {
// TODO: Test this when there is no available devices.
let plugin = AggregateDevice::get_system_plugin_id().unwrap();
let device = AggregateDevice::create_blank_device_sync(plugin).unwrap();
let devices = test_get_all_devices(DeviceFilter::IncludeAll);
let devices = test_get_all_devices(DeviceFilter::IncludeCubebAggregate);
let device = devices.into_iter().find(|dev| dev == &device).unwrap();
let uid = get_device_global_uid(device).unwrap().into_string();
assert!(uid.contains(PRIVATE_AGGREGATE_DEVICE_NAME));

View File

@ -45,8 +45,8 @@ fn test_increase_and_decrease_context_streams() {
for i in 0..STREAMS {
join_handles.push(thread::spawn(move || {
let context = unsafe { &*(context_ptr_value as *const AudioUnitContext) };
context.update_latency_by_adding_stream(i)
let global_latency = context.update_latency_by_adding_stream(i);
global_latency
}));
}
let mut latencies = vec![];
@ -227,11 +227,10 @@ fn test_add_listener_unknown_device() {
),
callback,
);
let mut res: OSStatus = 0;
stream
.queue
.run_sync(|| res = stream.add_device_listener(&listener));
assert_eq!(res, kAudioHardwareBadObjectError as OSStatus);
assert_eq!(
stream.add_device_listener(&listener),
kAudioHardwareBadObjectError as OSStatus
);
});
}
@ -258,15 +257,8 @@ fn test_add_listener_then_remove_system_device() {
),
callback,
);
let mut res: OSStatus = 0;
stream
.queue
.run_sync(|| res = stream.add_device_listener(&listener));
assert_eq!(res, NO_ERR);
stream
.queue
.run_sync(|| res = stream.remove_device_listener(&listener));
assert_eq!(res, NO_ERR);
assert_eq!(stream.add_device_listener(&listener), NO_ERR);
assert_eq!(stream.remove_device_listener(&listener), NO_ERR);
});
}
@ -291,11 +283,7 @@ fn test_remove_listener_without_adding_any_listener_before_system_device() {
),
callback,
);
let mut res: OSStatus = 0;
stream
.queue
.run_sync(|| res = stream.remove_device_listener(&listener));
assert_eq!(res, NO_ERR);
assert_eq!(stream.remove_device_listener(&listener), NO_ERR);
});
}
@ -320,11 +308,10 @@ fn test_remove_listener_unknown_device() {
),
callback,
);
let mut res: OSStatus = 0;
stream
.queue
.run_sync(|| res = stream.remove_device_listener(&listener));
assert_eq!(res, kAudioHardwareBadObjectError as OSStatus);
assert_eq!(
stream.remove_device_listener(&listener),
kAudioHardwareBadObjectError as OSStatus
);
});
}
@ -713,7 +700,7 @@ fn test_convert_channel_layout() {
}
let layout_ref = unsafe { &(*(&layout as *const TestLayout as *const AudioChannelLayout)) };
assert_eq!(
&audiounit_convert_channel_layout(layout_ref).unwrap(),
&audiounit_convert_channel_layout(layout_ref),
expected_layout
);
}
@ -724,9 +711,7 @@ fn test_convert_channel_layout() {
#[test]
fn test_get_preferred_channel_layout_output() {
match test_get_default_audiounit(Scope::Output) {
Some(unit) => assert!(!audiounit_get_preferred_channel_layout(unit.get_inner())
.unwrap()
.is_empty()),
Some(unit) => assert!(!audiounit_get_preferred_channel_layout(unit.get_inner()).is_empty()),
None => println!("No output audiounit for test."),
}
}
@ -736,9 +721,7 @@ fn test_get_preferred_channel_layout_output() {
#[test]
fn test_get_current_channel_layout_output() {
match test_get_default_audiounit(Scope::Output) {
Some(unit) => assert!(!audiounit_get_current_channel_layout(unit.get_inner())
.unwrap()
.is_empty()),
Some(unit) => assert!(!audiounit_get_current_channel_layout(unit.get_inner()).is_empty()),
None => println!("No output audiounit for test."),
}
}
@ -867,7 +850,7 @@ fn test_for_create_audiounit() {
// Check the output scope is enabled.
if device.flags.contains(device_flags::DEV_OUTPUT) && default_output.is_some() {
device.id = default_output.unwrap();
device.id = default_output.clone().unwrap();
let unit = create_audiounit(&device).unwrap();
assert!(!unit.is_null());
assert!(test_audiounit_scope_is_enabled(unit, Scope::Output));
@ -881,7 +864,7 @@ fn test_for_create_audiounit() {
// Check the input scope is enabled.
if device.flags.contains(device_flags::DEV_INPUT) && default_input.is_some() {
let device_id = default_input.unwrap();
let device_id = default_input.clone().unwrap();
device.id = device_id;
let unit = create_audiounit(&device).unwrap();
assert!(!unit.is_null());
@ -1064,12 +1047,8 @@ fn test_get_channel_count_of_inout_type() {
fn test_channel_count(scope: Scope) {
if let Some(device) = test_get_default_device(scope.clone()) {
assert_eq!(
get_channel_count(device, DeviceType::INPUT | DeviceType::OUTPUT),
get_channel_count(device, DeviceType::INPUT).map(|c| c + get_channel_count(
device,
DeviceType::OUTPUT
)
.unwrap_or(0))
get_channel_count(device, DeviceType::INPUT | DeviceType::OUTPUT).unwrap_err(),
kAudioHardwareUnknownPropertyError as OSStatus
);
} else {
println!("No device for {:?}.", scope);
@ -1387,6 +1366,7 @@ fn test_create_device_info_by_unknown_device() {
}
#[test]
#[should_panic]
fn test_create_device_info_with_unknown_type() {
test_create_device_info_with_unknown_type_by_scope(Scope::Input);
test_create_device_info_with_unknown_type_by_scope(Scope::Output);
@ -1394,6 +1374,8 @@ fn test_create_device_info_with_unknown_type() {
fn test_create_device_info_with_unknown_type_by_scope(scope: Scope) {
if let Some(device) = test_get_default_device(scope.clone()) {
assert!(create_cubeb_device_info(device, DeviceType::UNKNOWN).is_err());
} else {
panic!("Panic by default: No device for {:?}.", scope);
}
}
}
@ -1434,6 +1416,23 @@ fn test_create_device_from_hwdev_with_inout_type() {
}
}
// is_aggregate_device
// ------------------------------------
#[test]
fn test_is_aggregate_device() {
let mut aggregate_name = String::from(PRIVATE_AGGREGATE_DEVICE_NAME);
aggregate_name.push_str("_something");
let aggregate_name_cstring = CString::new(aggregate_name).unwrap();
let mut info = ffi::cubeb_device_info::default();
info.friendly_name = aggregate_name_cstring.as_ptr();
assert!(is_aggregate_device(&info));
let non_aggregate_name_cstring = CString::new("Hello World!").unwrap();
info.friendly_name = non_aggregate_name_cstring.as_ptr();
assert!(!is_aggregate_device(&info));
}
// get_devices_of_type
// ------------------------------------
#[test]
@ -1444,7 +1443,7 @@ fn test_get_devices_of_type() {
let input_devices = audiounit_get_devices_of_type(DeviceType::INPUT);
let output_devices = audiounit_get_devices_of_type(DeviceType::OUTPUT);
let mut expected_all = test_get_all_devices(DeviceFilter::ExcludeCubebAggregateAndVPIO);
let mut expected_all = test_get_all_devices(DeviceFilter::ExcludeCubebAggregate);
expected_all.sort();
assert_eq!(all_devices, expected_all);
for device in all_devices.iter() {

View File

@ -21,7 +21,8 @@ use super::utils::{
test_set_default_device, Scope, StreamType, TestDevicePlugger, TestDeviceSwitcher,
};
use super::*;
use std::sync::{LockResult, MutexGuard, WaitTimeoutResult};
use std::fmt::Debug;
use std::thread;
// Switch default devices used by the active streams, to test stream reinitialization
// ================================================================================================
@ -47,25 +48,22 @@ fn test_switch_device_in_scope(scope: Scope) {
let mut device_switcher = TestDeviceSwitcher::new(scope.clone());
let notifier = Arc::new(Notifier::new(0));
let also_notifier = notifier.clone();
let count = Arc::new(Mutex::new(0));
let also_count = Arc::clone(&count);
let listener = test_create_device_change_listener(scope.clone(), move |_addresses| {
let mut cnt = notifier.lock().unwrap();
let mut cnt = also_count.lock().unwrap();
*cnt += 1;
notifier.notify(cnt);
NO_ERR
});
listener.start();
let changed_watcher = Watcher::new(&also_notifier);
let mut changed_watcher = Watcher::new(&count);
test_get_started_stream_in_scope(scope.clone(), move |_stream| loop {
let mut guard = changed_watcher.lock().unwrap();
let start_cnt = guard.clone();
thread::sleep(Duration::from_millis(500));
changed_watcher.prepare();
device_switcher.next();
guard = changed_watcher
.wait_while(guard, |cnt| *cnt == start_cnt)
.unwrap();
if *guard >= devices.len() {
changed_watcher.wait_for_change();
if changed_watcher.current_result() >= devices.len() {
break;
}
});
@ -206,90 +204,77 @@ fn test_plug_and_unplug_device_in_scope(scope: Scope) {
let mut context = AudioUnitContext::new();
// Register the devices-changed callbacks.
#[derive(Clone, PartialEq)]
struct Counts {
input: u32,
output: u32,
}
impl Counts {
fn new() -> Self {
Self {
input: 0,
output: 0,
}
}
}
let counts = Arc::new(Notifier::new(Counts::new()));
let counts_notifier_ptr = counts.as_ref() as *const Notifier<Counts>;
let input_count = Arc::new(Mutex::new(0u32));
let also_input_count = Arc::clone(&input_count);
let input_mtx_ptr = also_input_count.as_ref() as *const Mutex<u32>;
assert!(context
.register_device_collection_changed(
DeviceType::INPUT,
Some(input_changed_callback),
counts_notifier_ptr as *mut c_void,
input_mtx_ptr as *mut c_void,
)
.is_ok());
let output_count = Arc::new(Mutex::new(0u32));
let also_output_count = Arc::clone(&output_count);
let output_mtx_ptr = also_output_count.as_ref() as *const Mutex<u32>;
assert!(context
.register_device_collection_changed(
DeviceType::OUTPUT,
Some(output_changed_callback),
counts_notifier_ptr as *mut c_void,
output_mtx_ptr as *mut c_void,
)
.is_ok());
let counts_watcher = Watcher::new(&counts);
let mut input_watcher = Watcher::new(&input_count);
let mut output_watcher = Watcher::new(&output_count);
let mut device_plugger = TestDevicePlugger::new(scope).unwrap();
{
// Simulate adding devices and monitor the devices-changed callbacks.
let mut counts_guard = counts.lock().unwrap();
let counts_start = counts_guard.clone();
// Simulate adding devices and monitor the devices-changed callbacks.
input_watcher.prepare();
output_watcher.prepare();
assert!(device_plugger.plug().is_ok());
assert!(device_plugger.plug().is_ok());
counts_guard = counts_watcher
.wait_while(counts_guard, |counts| {
(is_input && counts.input == counts_start.input)
|| (is_output && counts.output == counts_start.output)
})
.unwrap();
// Check changed count.
assert_eq!(counts_guard.input, if is_input { 1 } else { 0 });
assert_eq!(counts_guard.output, if is_output { 1 } else { 0 });
if is_input {
input_watcher.wait_for_change();
}
if is_output {
output_watcher.wait_for_change();
}
{
// Simulate removing devices and monitor the devices-changed callbacks.
let mut counts_guard = counts.lock().unwrap();
let counts_start = counts_guard.clone();
// Check changed count.
check_result(is_input, (1, 0), &input_watcher);
check_result(is_output, (1, 0), &output_watcher);
assert!(device_plugger.unplug().is_ok());
// Simulate removing devices and monitor the devices-changed callbacks.
input_watcher.prepare();
output_watcher.prepare();
counts_guard = counts_watcher
.wait_while(counts_guard, |counts| {
(is_input && counts.input == counts_start.input)
|| (is_output && counts.output == counts_start.output)
})
.unwrap();
assert!(device_plugger.unplug().is_ok());
// Check changed count.
assert_eq!(counts_guard.input, if is_input { 2 } else { 0 });
assert_eq!(counts_guard.output, if is_output { 2 } else { 0 });
if is_input {
input_watcher.wait_for_change();
}
if is_output {
output_watcher.wait_for_change();
}
check_result(is_input, (2, 0), &input_watcher);
check_result(is_output, (2, 0), &output_watcher);
extern "C" fn input_changed_callback(context: *mut ffi::cubeb, data: *mut c_void) {
println!(
"Input device collection @ {:p} is changed. Data @ {:p}",
context, data
);
let notifier = unsafe { &*(data as *const Notifier<Counts>) };
let count = unsafe { &*(data as *const Mutex<u32>) };
{
let mut counts = notifier.lock().unwrap();
counts.input += 1;
notifier.notify(counts);
let mut guard = count.lock().unwrap();
*guard += 1;
}
}
@ -298,13 +283,23 @@ fn test_plug_and_unplug_device_in_scope(scope: Scope) {
"output device collection @ {:p} is changed. Data @ {:p}",
context, data
);
let notifier = unsafe { &*(data as *const Notifier<Counts>) };
let count = unsafe { &*(data as *const Mutex<u32>) };
{
let mut counts = notifier.lock().unwrap();
counts.output += 1;
notifier.notify(counts);
let mut guard = count.lock().unwrap();
*guard += 1;
}
}
fn check_result<T: Clone + Debug + PartialEq>(
in_scope: bool,
expected: (T, T),
watcher: &Watcher<T>,
) {
assert_eq!(
watcher.current_result(),
if in_scope { expected.0 } else { expected.1 }
);
}
}
// Switch default devices used by the active streams, to test device changed callback
@ -357,15 +352,16 @@ fn test_register_device_changed_callback_to_check_default_device_changed(stm_typ
return;
}
let changed_count = Arc::new(Notifier::new(0u32));
let notifier_ptr = changed_count.as_ref() as *const Notifier<u32>;
let changed_count = Arc::new(Mutex::new(0u32));
let also_changed_count = Arc::clone(&changed_count);
let mtx_ptr = also_changed_count.as_ref() as *const Mutex<u32>;
test_get_stream_with_device_changed_callback(
"stream: test callback for default device changed",
stm_type,
None, // Use default input device.
None, // Use default output device.
notifier_ptr as *mut c_void,
mtx_ptr as *mut c_void,
state_callback,
device_changed_callback,
|stream| {
@ -375,22 +371,17 @@ fn test_register_device_changed_callback_to_check_default_device_changed(stm_typ
// be assigned to the default device, since the device list for setting
// default device is cached upon {input, output}_device_switcher is initialized.
let changed_watcher = Watcher::new(&changed_count);
let mut changed_watcher = Watcher::new(&changed_count);
if let Some(devices) = inputs {
let mut device_switcher = TestDeviceSwitcher::new(Scope::Input);
for _ in 0..devices {
// While the stream is re-initializing for the default device switch,
// switching for the default device again will be ignored.
while stream.switching_device.load(atomic::Ordering::SeqCst) {
std::hint::spin_loop()
}
let guard = changed_watcher.lock().unwrap();
let start_cnt = guard.clone();
while stream.switching_device.load(atomic::Ordering::SeqCst) {}
changed_watcher.prepare();
device_switcher.next();
changed_watcher
.wait_while(guard, |cnt| *cnt == start_cnt)
.unwrap();
changed_watcher.wait_for_change();
}
}
@ -399,15 +390,10 @@ fn test_register_device_changed_callback_to_check_default_device_changed(stm_typ
for _ in 0..devices {
// While the stream is re-initializing for the default device switch,
// switching for the default device again will be ignored.
while stream.switching_device.load(atomic::Ordering::SeqCst) {
std::hint::spin_loop()
}
let guard = changed_watcher.lock().unwrap();
let start_cnt = guard.clone();
while stream.switching_device.load(atomic::Ordering::SeqCst) {}
changed_watcher.prepare();
device_switcher.next();
changed_watcher
.wait_while(guard, |cnt| *cnt == start_cnt)
.unwrap();
changed_watcher.wait_for_change();
}
}
},
@ -424,10 +410,11 @@ fn test_register_device_changed_callback_to_check_default_device_changed(stm_typ
extern "C" fn device_changed_callback(data: *mut c_void) {
println!("Device change callback. data @ {:p}", data);
let notifier = unsafe { &*(data as *const Notifier<u32>) };
let mut count_guard = notifier.lock().unwrap();
*count_guard += 1;
notifier.notify(count_guard);
let count = unsafe { &*(data as *const Mutex<u32>) };
{
let mut guard = count.lock().unwrap();
*guard += 1;
}
}
}
@ -453,7 +440,7 @@ fn test_destroy_input_stream_after_unplugging_a_nondefault_input_device() {
#[test]
fn test_suspend_input_stream_by_unplugging_a_nondefault_input_device() {
// Expect to get an error state callback by device-changed event handler
test_unplug_a_device_on_an_active_stream(StreamType::INPUT, Scope::Input, false, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::INPUT, Scope::Input, false, 500);
}
// Unplug the default input device for an input stream
@ -472,7 +459,7 @@ fn test_destroy_input_stream_after_unplugging_a_default_input_device() {
fn test_reinit_input_stream_by_unplugging_a_default_input_device() {
// Expect to get an device-changed callback by device-changed event handler,
// which will reinitialize the stream behind the scenes
test_unplug_a_device_on_an_active_stream(StreamType::INPUT, Scope::Input, true, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::INPUT, Scope::Input, true, 500);
}
// Output-only stream
@ -480,16 +467,18 @@ fn test_reinit_input_stream_by_unplugging_a_default_input_device() {
// Unplug the non-default output device for an output stream
// ------------------------------------------------------------------------------------------------
// FIXME: We don't monitor the alive-status for output device currently
#[ignore]
#[test]
fn test_destroy_output_stream_after_unplugging_a_nondefault_output_device() {
test_unplug_a_device_on_an_active_stream(StreamType::OUTPUT, Scope::Output, false, 0);
}
// FIXME: We don't monitor the alive-status for output device currently
#[ignore]
#[test]
fn test_suspend_output_stream_by_unplugging_a_nondefault_output_device() {
test_unplug_a_device_on_an_active_stream(StreamType::OUTPUT, Scope::Output, false, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::OUTPUT, Scope::Output, false, 500);
}
// Unplug the default output device for an output stream
@ -509,7 +498,7 @@ fn test_destroy_output_stream_after_unplugging_a_default_output_device() {
fn test_reinit_output_stream_by_unplugging_a_default_output_device() {
// Expect to get an device-changed callback by device-changed event handler,
// which will reinitialize the stream behind the scenes
test_unplug_a_device_on_an_active_stream(StreamType::OUTPUT, Scope::Output, true, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::OUTPUT, Scope::Output, true, 500);
}
// Duplex stream
@ -529,22 +518,24 @@ fn test_destroy_duplex_stream_after_unplugging_a_nondefault_input_device() {
#[test]
fn test_suspend_duplex_stream_by_unplugging_a_nondefault_input_device() {
// Expect to get an error state callback by device-changed event handler
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Input, false, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Input, false, 500);
}
// Unplug the non-default output device for a duplex stream
// ------------------------------------------------------------------------------------------------
// FIXME: We don't monitor the alive-status for output device currently
#[ignore]
#[test]
fn test_destroy_duplex_stream_after_unplugging_a_nondefault_output_device() {
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Output, false, 0);
}
// FIXME: We don't monitor the alive-status for output device currently
#[ignore]
#[test]
fn test_suspend_duplex_stream_by_unplugging_a_nondefault_output_device() {
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Output, false, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Output, false, 500);
}
// Unplug the non-default in-out device for a duplex stream
@ -568,7 +559,7 @@ fn test_destroy_duplex_stream_after_unplugging_a_default_input_device() {
fn test_reinit_duplex_stream_by_unplugging_a_default_input_device() {
// Expect to get an device-changed callback by device-changed event handler,
// which will reinitialize the stream behind the scenes
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Input, true, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Input, true, 500);
}
// Unplug the default ouput device for a duplex stream
@ -588,14 +579,14 @@ fn test_destroy_duplex_stream_after_unplugging_a_default_output_device() {
fn test_reinit_duplex_stream_by_unplugging_a_default_output_device() {
// Expect to get an device-changed callback by device-changed event handler,
// which will reinitialize the stream behind the scenes
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Output, true, 2000);
test_unplug_a_device_on_an_active_stream(StreamType::DUPLEX, Scope::Output, true, 500);
}
fn test_unplug_a_device_on_an_active_stream(
stream_type: StreamType,
device_scope: Scope,
set_device_to_default: bool,
wait_up_to_ms: u64,
sleep: u64,
) {
let has_input = test_get_default_device(Scope::Input).is_some();
let has_output = test_get_default_device(Scope::Output).is_some();
@ -679,72 +670,62 @@ fn test_unplug_a_device_on_an_active_stream(
),
};
#[derive(Clone, PartialEq)]
struct Data {
changed_count: u32,
states: Vec<ffi::cubeb_state>,
struct SharedData {
changed_count: Arc<Mutex<u32>>,
states: Arc<Mutex<Vec<ffi::cubeb_state>>>,
}
impl Data {
fn new() -> Self {
Self {
changed_count: 0,
states: vec![],
}
}
}
let notifier = Arc::new(Notifier::new(Data::new()));
let notifier_ptr = notifier.as_ref() as *const Notifier<Data>;
let mut shared_data = SharedData {
changed_count: Arc::new(Mutex::new(0u32)),
states: Arc::new(Mutex::new(vec![])),
};
test_get_stream_with_device_changed_callback(
"stream: test stream reinit/destroy after unplugging a device",
stream_type,
input_device,
output_device,
notifier_ptr as *mut c_void,
&mut shared_data as *mut SharedData as *mut c_void,
state_callback,
device_changed_callback,
|stream| {
let mut changed_watcher = Watcher::new(&shared_data.changed_count);
changed_watcher.prepare();
stream.start();
let changed_watcher = Watcher::new(&notifier);
let mut data_guard = notifier.lock().unwrap();
assert_eq!(data_guard.states.last().unwrap(), &ffi::CUBEB_STATE_STARTED);
// Wait for stream data callback.
thread::sleep(Duration::from_millis(200));
println!(
"Stream runs on the device {} for {:?}",
plugger.get_device_id(),
device_scope
);
let dev = plugger.get_device_id();
let start_changed_count = data_guard.changed_count.clone();
assert!(plugger.unplug().is_ok());
if set_device_to_default {
// The stream will be reinitialized if it follows the default input or output device.
println!("Waiting for default device to change and reinit");
data_guard = changed_watcher
.wait_while(data_guard, |data| {
data.changed_count == start_changed_count
|| data.states.last().unwrap_or(&ffi::CUBEB_STATE_ERROR)
!= &ffi::CUBEB_STATE_STARTED
})
.unwrap();
} else if wait_up_to_ms > 0 {
// stream can be dropped immediately before device-changed callback
// so we only check the states if we wait for it explicitly.
println!("Waiting for non-default device to enter error state");
let (new_guard, timeout_res) = changed_watcher
.wait_timeout_while(data_guard, Duration::from_millis(wait_up_to_ms), |data| {
data.states.last().unwrap_or(&ffi::CUBEB_STATE_STARTED)
!= &ffi::CUBEB_STATE_ERROR
})
.unwrap();
assert!(!timeout_res.timed_out());
data_guard = new_guard;
changed_watcher.wait_for_change();
}
if sleep > 0 {
println!(
"Wait {} ms for stream re-initialization, or state callback",
sleep
);
thread::sleep(Duration::from_millis(sleep));
if !set_device_to_default {
// stream can be dropped immediately before device-changed callback
// so we only check the states if we wait for it explicitly.
let guard = shared_data.states.lock().unwrap();
assert!(guard.last().is_some());
assert_eq!(guard.last().unwrap(), &ffi::CUBEB_STATE_ERROR);
}
} else {
println!("Destroy the stream immediately");
if set_device_to_default {
println!("Stream re-initialization may run at the same time when stream is being destroyed");
}
}
println!(
@ -764,7 +745,6 @@ fn test_unplug_a_device_on_an_active_stream(
user_ptr: *mut c_void,
state: ffi::cubeb_state,
) {
println!("Device change callback. user_ptr @ {:p}", user_ptr);
assert!(!stream.is_null());
println!(
"state: {}",
@ -776,79 +756,52 @@ fn test_unplug_a_device_on_an_active_stream(
_ => "unknown",
}
);
let notifier = unsafe { &mut *(user_ptr as *mut Notifier<Data>) };
let mut data_guard = notifier.lock().unwrap();
data_guard.states.push(state);
notifier.notify(data_guard);
}
extern "C" fn device_changed_callback(user_ptr: *mut c_void) {
println!("Device change callback. user_ptr @ {:p}", user_ptr);
let notifier = unsafe { &mut *(user_ptr as *mut Notifier<Data>) };
let mut data_guard = notifier.lock().unwrap();
data_guard.changed_count += 1;
notifier.notify(data_guard);
}
}
struct Notifier<T> {
value: Mutex<T>,
cvar: Condvar,
}
impl<T> Notifier<T> {
fn new(value: T) -> Self {
Self {
value: Mutex::new(value),
cvar: Condvar::new(),
let shared_data = unsafe { &mut *(user_ptr as *mut SharedData) };
{
let mut guard = shared_data.states.lock().unwrap();
guard.push(state);
}
}
fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
self.value.lock()
}
fn notify(&self, _guard: MutexGuard<'_, T>) {
self.cvar.notify_all();
extern "C" fn device_changed_callback(data: *mut c_void) {
println!("Device change callback. data @ {:p}", data);
let shared_data = unsafe { &mut *(data as *mut SharedData) };
{
let mut guard = shared_data.changed_count.lock().unwrap();
*guard += 1;
}
}
}
struct Watcher<T: Clone + PartialEq> {
notifier: Arc<Notifier<T>>,
watching: Arc<Mutex<T>>,
current: Option<T>,
}
impl<T: Clone + PartialEq> Watcher<T> {
fn new(value: &Arc<Notifier<T>>) -> Self {
fn new(value: &Arc<Mutex<T>>) -> Self {
Self {
notifier: Arc::clone(value),
watching: Arc::clone(value),
current: None,
}
}
fn lock(&self) -> LockResult<MutexGuard<'_, T>> {
self.notifier.lock()
fn prepare(&mut self) {
self.current = Some(self.current_result());
}
fn wait_while<'a, F>(
&self,
guard: MutexGuard<'a, T>,
condition: F,
) -> LockResult<MutexGuard<'a, T>>
where
F: FnMut(&mut T) -> bool,
{
self.notifier.cvar.wait_while(guard, condition)
fn wait_for_change(&self) {
loop {
if self.current_result() != self.current.clone().unwrap() {
break;
}
thread::sleep(Duration::from_millis(1));
}
}
fn wait_timeout_while<'a, F>(
&self,
guard: MutexGuard<'a, T>,
dur: Duration,
condition: F,
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)>
where
F: FnMut(&mut T) -> bool,
{
self.notifier.cvar.wait_timeout_while(guard, dur, condition)
fn current_result(&self) -> T {
let guard = self.watching.lock().unwrap();
guard.clone()
}
}

View File

@ -282,7 +282,6 @@ fn test_get_device_streams() {
if let Some(device) = test_get_default_device(Scope::Input) {
let streams = get_device_streams(device, DeviceType::INPUT).unwrap();
println!("streams on the input device: {:?}", streams);
assert!(!streams.is_empty());
} else {
println!("No input device.");
}
@ -290,7 +289,6 @@ fn test_get_device_streams() {
if let Some(device) = test_get_default_device(Scope::Output) {
let streams = get_device_streams(device, DeviceType::OUTPUT).unwrap();
println!("streams on the output device: {:?}", streams);
assert!(!streams.is_empty());
} else {
println!("No output device.");
}
@ -352,6 +350,56 @@ fn test_get_ranges_of_device_sample_rate_by_unknown_device() {
assert!(get_ranges_of_device_sample_rate(kAudioObjectUnknown, DeviceType::INPUT).is_err());
}
// get_device_stream_format
// ------------------------------------
#[test]
fn test_get_device_stream_format() {
if let Some(device) = test_get_default_device(Scope::Input) {
let format = get_device_stream_format(device, DeviceType::INPUT).unwrap();
println!("input stream format: {:?}", format);
} else {
println!("No input device.");
}
if let Some(device) = test_get_default_device(Scope::Output) {
let format = get_device_stream_format(device, DeviceType::OUTPUT).unwrap();
println!("output stream format: {:?}", format);
} else {
println!("No output device.");
}
}
#[test]
#[should_panic]
fn test_get_device_stream_format_by_unknown_device() {
assert!(get_device_stream_format(kAudioObjectUnknown, DeviceType::INPUT).is_err());
}
// get_device_stream_configuration
// ------------------------------------
#[test]
fn test_get_device_stream_configuration() {
if let Some(device) = test_get_default_device(Scope::Input) {
let buffers = get_device_stream_configuration(device, DeviceType::INPUT).unwrap();
println!("input stream config: {:?}", buffers);
} else {
println!("No input device.");
}
if let Some(device) = test_get_default_device(Scope::Output) {
let buffers = get_device_stream_configuration(device, DeviceType::OUTPUT).unwrap();
println!("output stream config: {:?}", buffers);
} else {
println!("No output device.");
}
}
#[test]
#[should_panic]
fn test_get_device_stream_configuration_by_unknown_device() {
assert!(get_device_stream_configuration(kAudioObjectUnknown, DeviceType::INPUT).is_err());
}
// get_stream_latency
// ------------------------------------
#[test]
@ -359,7 +407,7 @@ fn test_get_stream_latency() {
if let Some(device) = test_get_default_device(Scope::Input) {
let streams = get_device_streams(device, DeviceType::INPUT).unwrap();
for stream in streams {
let latency = get_stream_latency(stream).unwrap();
let latency = get_stream_latency(stream, DeviceType::INPUT).unwrap();
println!("latency of the input stream {} is {}", stream, latency);
}
} else {
@ -369,7 +417,7 @@ fn test_get_stream_latency() {
if let Some(device) = test_get_default_device(Scope::Output) {
let streams = get_device_streams(device, DeviceType::OUTPUT).unwrap();
for stream in streams {
let latency = get_stream_latency(stream).unwrap();
let latency = get_stream_latency(stream, DeviceType::OUTPUT).unwrap();
println!("latency of the output stream {} is {}", stream, latency);
}
} else {
@ -380,94 +428,5 @@ fn test_get_stream_latency() {
#[test]
#[should_panic]
fn test_get_stream_latency_by_unknown_device() {
assert!(get_stream_latency(kAudioObjectUnknown).is_err());
}
// get_stream_virtual_format
// ------------------------------------
#[test]
fn test_get_stream_virtual_format() {
if let Some(device) = test_get_default_device(Scope::Input) {
let streams = get_device_streams(device, DeviceType::INPUT).unwrap();
let formats = streams
.iter()
.map(|s| get_stream_virtual_format(*s))
.collect::<Vec<std::result::Result<AudioStreamBasicDescription, OSStatus>>>();
println!("input stream formats: {:?}", formats);
assert!(!formats.is_empty());
} else {
println!("No input device.");
}
if let Some(device) = test_get_default_device(Scope::Output) {
let streams = get_device_streams(device, DeviceType::OUTPUT).unwrap();
let formats = streams
.iter()
.map(|s| get_stream_virtual_format(*s))
.collect::<Vec<std::result::Result<AudioStreamBasicDescription, OSStatus>>>();
println!("output stream formats: {:?}", formats);
assert!(!formats.is_empty());
} else {
println!("No output device.");
}
}
#[test]
#[should_panic]
fn test_get_stream_virtual_format_by_unknown_stream() {
assert!(get_stream_virtual_format(kAudioObjectUnknown).is_err());
}
// get_stream_terminal_type
// ------------------------------------
#[test]
fn test_get_stream_terminal_type() {
fn terminal_type_to_device_type(terminal_type: u32) -> Option<DeviceType> {
#[allow(non_upper_case_globals)]
match terminal_type {
kAudioStreamTerminalTypeMicrophone
| kAudioStreamTerminalTypeHeadsetMicrophone
| kAudioStreamTerminalTypeReceiverMicrophone => Some(DeviceType::INPUT),
kAudioStreamTerminalTypeSpeaker
| kAudioStreamTerminalTypeHeadphones
| kAudioStreamTerminalTypeLFESpeaker
| kAudioStreamTerminalTypeReceiverSpeaker => Some(DeviceType::OUTPUT),
t if t > INPUT_UNDEFINED && t < OUTPUT_UNDEFINED => Some(DeviceType::INPUT),
t if t > OUTPUT_UNDEFINED && t < BIDIRECTIONAL_UNDEFINED => Some(DeviceType::OUTPUT),
t => {
println!("UNKNOWN TerminalType {:#06x}", t);
None
}
}
}
if let Some(device) = test_get_default_device(Scope::Input) {
let streams = get_device_streams(device, DeviceType::INPUT).unwrap();
for stream in streams {
assert_eq!(
terminal_type_to_device_type(get_stream_terminal_type(stream).unwrap()),
Some(DeviceType::INPUT)
);
}
} else {
println!("No input device.");
}
if let Some(device) = test_get_default_device(Scope::Output) {
let streams = get_device_streams(device, DeviceType::OUTPUT).unwrap();
for stream in streams {
assert_eq!(
terminal_type_to_device_type(get_stream_terminal_type(stream).unwrap()),
Some(DeviceType::OUTPUT)
);
}
} else {
println!("No output device.");
}
}
#[test]
#[should_panic]
fn test_get_stream_terminal_type_by_unknown_stream() {
assert!(get_stream_terminal_type(kAudioObjectUnknown).is_err());
assert!(get_stream_latency(kAudioObjectUnknown, DeviceType::INPUT).is_err());
}

View File

@ -1,9 +1,5 @@
extern crate itertools;
use self::itertools::iproduct;
use super::utils::{
noop_data_callback, test_get_default_device, test_ops_context_operation,
test_ops_stream_operation, Scope,
test_get_default_device, test_ops_context_operation, test_ops_stream_operation, Scope,
};
use super::*;
@ -453,192 +449,6 @@ fn test_ops_context_register_device_collection_changed_manual() {
);
}
#[test]
fn test_ops_context_stream_init_no_stream_params() {
let name = "context: stream_init with no stream params";
test_ops_context_operation(name, |context_ptr| {
let mut stream: *mut ffi::cubeb_stream = ptr::null_mut();
let stream_name = CString::new(name).expect("Failed to create stream name");
assert_eq!(
unsafe {
OPS.stream_init.unwrap()(
context_ptr,
&mut stream,
stream_name.as_ptr(),
ptr::null_mut(), // Use default input device.
ptr::null_mut(), // No input parameters.
ptr::null_mut(), // Use default output device.
ptr::null_mut(), // No output parameters.
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
},
ffi::CUBEB_ERROR_INVALID_PARAMETER
);
assert!(stream.is_null());
});
}
#[test]
fn test_ops_context_stream_init_no_input_stream_params() {
let name = "context: stream_init with no input stream params";
let input_device = test_get_default_device(Scope::Input);
if input_device.is_none() {
println!("No input device to perform input tests for \"{}\".", name);
return;
}
test_ops_context_operation(name, |context_ptr| {
let mut stream: *mut ffi::cubeb_stream = ptr::null_mut();
let stream_name = CString::new(name).expect("Failed to create stream name");
assert_eq!(
unsafe {
OPS.stream_init.unwrap()(
context_ptr,
&mut stream,
stream_name.as_ptr(),
input_device.unwrap() as ffi::cubeb_devid,
ptr::null_mut(), // No input parameters.
ptr::null_mut(), // Use default output device.
ptr::null_mut(), // No output parameters.
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
},
ffi::CUBEB_ERROR_INVALID_PARAMETER
);
assert!(stream.is_null());
});
}
#[test]
fn test_ops_context_stream_init_no_output_stream_params() {
let name = "context: stream_init with no output stream params";
let output_device = test_get_default_device(Scope::Output);
if output_device.is_none() {
println!("No output device to perform output tests for \"{}\".", name);
return;
}
test_ops_context_operation(name, |context_ptr| {
let mut stream: *mut ffi::cubeb_stream = ptr::null_mut();
let stream_name = CString::new(name).expect("Failed to create stream name");
assert_eq!(
unsafe {
OPS.stream_init.unwrap()(
context_ptr,
&mut stream,
stream_name.as_ptr(),
ptr::null_mut(), // Use default input device.
ptr::null_mut(), // No input parameters.
output_device.unwrap() as ffi::cubeb_devid,
ptr::null_mut(), // No output parameters.
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
},
ffi::CUBEB_ERROR_INVALID_PARAMETER
);
assert!(stream.is_null());
});
}
#[test]
fn test_ops_context_stream_init_no_data_callback() {
let name = "context: stream_init with no data callback";
test_ops_context_operation(name, |context_ptr| {
let mut stream: *mut ffi::cubeb_stream = ptr::null_mut();
let stream_name = CString::new(name).expect("Failed to create stream name");
let mut output_params = ffi::cubeb_stream_params::default();
output_params.format = ffi::CUBEB_SAMPLE_FLOAT32NE;
output_params.rate = 44100;
output_params.channels = 2;
output_params.layout = ffi::CUBEB_LAYOUT_UNDEFINED;
output_params.prefs = ffi::CUBEB_STREAM_PREF_NONE;
assert_eq!(
unsafe {
OPS.stream_init.unwrap()(
context_ptr,
&mut stream,
stream_name.as_ptr(),
ptr::null_mut(), // Use default input device.
ptr::null_mut(), // No input parameters.
ptr::null_mut(), // Use default output device.
&mut output_params,
4096, // TODO: Get latency by get_min_latency instead ?
None, // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
},
ffi::CUBEB_ERROR_INVALID_PARAMETER
);
assert!(stream.is_null());
});
}
#[test]
fn test_ops_context_stream_init_channel_rate_combinations() {
let name = "context: stream_init with various channels and rates";
test_ops_context_operation(name, |context_ptr| {
let mut stream: *mut ffi::cubeb_stream = ptr::null_mut();
let stream_name = CString::new(name).expect("Failed to create stream name");
const MAX_NUM_CHANNELS: u32 = 32;
let channel_values: Vec<u32> = vec![1, 2, 3, 4, 6];
let freq_values: Vec<u32> = vec![16000, 24000, 44100, 48000];
let is_float_values: Vec<bool> = vec![false, true];
for (channels, freq, is_float) in iproduct!(channel_values, freq_values, is_float_values) {
assert!(channels < MAX_NUM_CHANNELS);
println!("--------------------------");
println!(
"Testing {} channel(s), {} Hz, {}\n",
channels,
freq,
if is_float { "float" } else { "short" }
);
let mut output_params = ffi::cubeb_stream_params::default();
output_params.format = if is_float {
ffi::CUBEB_SAMPLE_FLOAT32NE
} else {
ffi::CUBEB_SAMPLE_S16NE
};
output_params.rate = freq;
output_params.channels = channels;
output_params.layout = ffi::CUBEB_LAYOUT_UNDEFINED;
output_params.prefs = ffi::CUBEB_STREAM_PREF_NONE;
assert_eq!(
unsafe {
OPS.stream_init.unwrap()(
context_ptr,
&mut stream,
stream_name.as_ptr(),
ptr::null_mut(), // Use default input device.
ptr::null_mut(), // No input parameters.
ptr::null_mut(), // Use default output device.
&mut output_params,
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback), // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
},
ffi::CUBEB_OK
);
assert!(!stream.is_null());
}
});
}
// Stream Operations
// ------------------------------------------------------------------------------------------------
fn test_default_output_stream_operation<F>(name: &'static str, operation: F)
@ -660,8 +470,8 @@ where
ptr::null_mut(), // No input parameters.
ptr::null_mut(), // Use default output device.
&mut output_params,
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
4096, // TODO: Get latency by get_min_latency instead ?
None, // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
operation,
@ -694,8 +504,8 @@ where
&mut input_params,
ptr::null_mut(), // Use default output device.
&mut output_params,
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
4096, // TODO: Get latency by get_min_latency instead ?
None, // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
operation,

View File

@ -1,6 +1,6 @@
use super::utils::{
noop_data_callback, test_audiounit_get_buffer_frame_size, test_get_default_audiounit,
test_get_default_device, test_ops_context_operation, PropertyScope, Scope,
test_audiounit_get_buffer_frame_size, test_get_default_audiounit, test_get_default_device,
test_ops_context_operation, PropertyScope, Scope,
};
use super::*;
use std::thread;
@ -232,7 +232,7 @@ fn create_streams_by_ops_in_parallel_with_different_latency<F>(
ptr::null_mut()
},
latency_frames,
Some(noop_data_callback),
None, // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)
@ -468,7 +468,7 @@ fn create_streams_in_parallel_with_different_latency<F>(
None
},
latency_frames,
Some(noop_data_callback),
None, // No data callback.
None, // No state callback.
ptr::null_mut(), // No user data pointer.
)

View File

@ -2,29 +2,6 @@ use super::*;
// Common Utils
// ------------------------------------------------------------------------------------------------
pub extern "C" fn noop_data_callback(
stream: *mut ffi::cubeb_stream,
_user_ptr: *mut c_void,
_input_buffer: *const c_void,
output_buffer: *mut c_void,
nframes: i64,
) -> i64 {
assert!(!stream.is_null());
// Feed silence data to output buffer
if !output_buffer.is_null() {
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
let channels = stm.core_stream_data.output_stream_params.channels();
let samples = nframes as usize * channels as usize;
let sample_size = cubeb_sample_size(stm.core_stream_data.output_stream_params.format());
unsafe {
ptr::write_bytes(output_buffer, 0, samples * sample_size);
}
}
nframes
}
#[derive(Clone, Debug, PartialEq)]
pub enum Scope {
Input,
@ -212,7 +189,11 @@ fn test_enable_audiounit_in_scope(
}
pub fn test_get_source_name(device: AudioObjectID, scope: Scope) -> Option<String> {
test_get_source_data(device, scope).map(u32_to_string)
if let Some(source) = test_get_source_data(device, scope) {
Some(u32_to_string(source))
} else {
None
}
}
pub fn test_get_source_data(device: AudioObjectID, scope: Scope) -> Option<u32> {
@ -257,8 +238,8 @@ fn u32_to_string(data: u32) -> String {
}
pub enum DeviceFilter {
ExcludeCubebAggregateAndVPIO,
IncludeAll,
ExcludeCubebAggregate,
IncludeCubebAggregate,
}
pub fn test_get_all_devices(filter: DeviceFilter) -> Vec<AudioObjectID> {
let mut devices = Vec::new();
@ -303,12 +284,11 @@ pub fn test_get_all_devices(filter: DeviceFilter) -> Vec<AudioObjectID> {
}
match filter {
DeviceFilter::ExcludeCubebAggregateAndVPIO => {
DeviceFilter::ExcludeCubebAggregate => {
devices.retain(|&device| {
if let Ok(uid) = get_device_global_uid(device) {
let uid = uid.into_string();
!uid.contains(PRIVATE_AGGREGATE_DEVICE_NAME)
&& !uid.contains(VOICEPROCESSING_AGGREGATE_DEVICE_NAME)
} else {
true
}
@ -321,7 +301,7 @@ pub fn test_get_all_devices(filter: DeviceFilter) -> Vec<AudioObjectID> {
}
pub fn test_get_devices_in_scope(scope: Scope) -> Vec<AudioObjectID> {
let mut devices = test_get_all_devices(DeviceFilter::ExcludeCubebAggregateAndVPIO);
let mut devices = test_get_all_devices(DeviceFilter::ExcludeCubebAggregate);
devices.retain(|device| test_device_in_scope(*device, scope.clone()));
devices
}
@ -343,7 +323,7 @@ pub fn get_devices_info_in_scope(scope: Scope) -> Vec<TestDeviceInfo> {
infos.push(TestDeviceInfo::new(device, scope.clone()));
print_info(infos.last().unwrap());
}
println!();
println!("");
infos
}
@ -625,10 +605,7 @@ pub fn test_set_default_device(
&device as *const AudioObjectID as *const c_void,
)
};
let new_default = test_get_default_device(scope.clone()).unwrap();
if new_default == default {
Err(-1)
} else if status == NO_ERR {
if status == NO_ERR {
Ok(default)
} else {
Err(status)
@ -651,8 +628,8 @@ impl TestDeviceSwitcher {
.position(|device| *device == current)
.unwrap();
Self {
scope,
devices,
scope: scope,
devices: devices,
current_device_index: index,
}
}
@ -665,19 +642,9 @@ impl TestDeviceSwitcher {
"Switch device for {:?}: {} -> {}",
self.scope, current, next
);
match self.set_device(next) {
Ok(prev) => {
assert_eq!(prev, current);
self.current_device_index = next_index;
}
_ => {
self.devices.remove(next_index);
if next_index < self.current_device_index {
self.current_device_index -= 1;
}
self.next();
}
}
let prev = self.set_device(next).unwrap();
assert_eq!(prev, current);
self.current_device_index = next_index;
}
fn set_device(&self, device: AudioObjectID) -> std::result::Result<AudioObjectID, OSStatus> {
@ -921,9 +888,8 @@ impl TestDevicePlugger {
);
CFRelease(device_uid as *const c_void);
// Make this device NOT private to the process creating it.
// On MacOS 14 devicechange events are not triggered when it is private.
let private_value: i32 = 0;
// This device is private to the process creating it.
let private_value: i32 = 1;
let device_private_key = CFNumberCreate(
kCFAllocatorDefault,
i64::from(kCFNumberIntType),
@ -1037,7 +1003,9 @@ impl TestDevicePlugger {
// AggregateDevice::get_sub_devices and audiounit_set_aggregate_sub_device_list.
fn get_sub_devices(scope: Scope) -> Option<CFArrayRef> {
let device = test_get_default_device(scope);
device?;
if device.is_none() {
return None;
}
let device = device.unwrap();
let uid = get_device_global_uid(device);
if uid.is_err() {
@ -1240,9 +1208,9 @@ pub fn test_get_stream_with_default_data_callback_by_type<F>(
bitflags! {
pub struct StreamType: u8 {
const INPUT = 0x01;
const OUTPUT = 0x02;
const DUPLEX = 0x03;
const INPUT = 0b01;
const OUTPUT = 0b10;
const DUPLEX = Self::INPUT.bits | Self::OUTPUT.bits;
}
}
@ -1284,9 +1252,32 @@ fn test_ops_stream_operation_with_default_data_callback<F>(
output_device,
output_stream_params,
4096, // TODO: Get latency by get_min_latency instead ?
Some(noop_data_callback),
Some(data_callback),
Some(state_callback),
data,
operation,
);
extern "C" fn data_callback(
stream: *mut ffi::cubeb_stream,
_user_ptr: *mut c_void,
_input_buffer: *const c_void,
output_buffer: *mut c_void,
nframes: i64,
) -> i64 {
assert!(!stream.is_null());
// Feed silence data to output buffer
if !output_buffer.is_null() {
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
let channels = stm.core_stream_data.output_stream_params.channels();
let samples = nframes as usize * channels as usize;
let sample_size = cubeb_sample_size(stm.core_stream_data.output_stream_params.format());
unsafe {
ptr::write_bytes(output_buffer, 0, samples * sample_size);
}
}
nframes
}
}

View File

@ -22,7 +22,7 @@ static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
mozurl = { path = "../../../../netwerk/base/mozurl" }
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "964e14628f285ad44522bdeeb566c1864ecd2fd8", optional = true }
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "93b5c01a131f65c83c11aeb317f4583405c5eb79", optional = true }
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="cf48897be5cbe147d051ebbbe1eaf5fd8fb6bbc9", optional = true, features=["pulse-dlopen"] }
cubeb-sys = { version = "0.10.3", optional = true, features=["gecko-in-tree"] }
audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "6be424d75f1367e70f2f5ddcacd6d0237e81a6a9", optional = true }

View File

@ -14,7 +14,7 @@ mozbuild = "0.1"
[build-dependencies]
lazy_static = "1"
bindgen = {version = "0.69", default-features = false}
bindgen = {version = "0.68", default-features = false}
mozbuild = "0.1"
[features]