Backed out 2 changesets (bug 1670633) as requested for causing Bug 1866014. CLOSED TREE

Backed out changeset be8e9a8eaa80 (bug 1670633)
Backed out changeset bace8b9c91dc (bug 1670633)
This commit is contained in:
Stanca Serban
2023-11-23 20:03:07 +02:00
parent c632408159
commit 074535d4da
44 changed files with 663 additions and 1439 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

@@ -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]