diff --git a/.cargo/config.in b/.cargo/config.in index c6e2e00ad1a7..7ecbfaa6595c 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -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"] diff --git a/Cargo.lock b/Cargo.lock index e0e2d6213cd6..6c856239e802 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index ad343862ebf1..27886bd8ff1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/build/rust/bindgen/Cargo.toml b/build/rust/bindgen/Cargo.toml index 12cce0af3feb..83d1951c76d9 100644 --- a/build/rust/bindgen/Cargo.toml +++ b/build/rust/bindgen/Cargo.toml @@ -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] diff --git a/build/workspace-hack/Cargo.toml b/build/workspace-hack/Cargo.toml index 9d23dd6d4bdc..5c8d488fb057 100644 --- a/build/workspace-hack/Cargo.toml +++ b/build/workspace-hack/Cargo.toml @@ -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 } diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp index 9de8cf5e54a4..c3a9356ee89a 100644 --- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -323,15 +323,8 @@ void MediaEngineWebRTCMicrophoneSource::SetTrack( mTrack = aTrack->AsAudioProcessingTrack(); mPrincipal = aPrincipal; -#if defined(XP_MACOSX) && defined(NIGHTLY_BUILD) - mInputProcessing = MakeAndAddRef(1); -#else -# if !defined(NIGHTLY_BUILD) -# error "Must remove this quick fix to bug 1866014 before reaching beta" -# endif mInputProcessing = MakeAndAddRef(mDeviceMaxChannelCount); -#endif NS_DispatchToMainThread(NS_NewRunnableFunction( __func__, [track = mTrack, processing = mInputProcessing]() mutable { diff --git a/netwerk/test/http3server/Cargo.toml b/netwerk/test/http3server/Cargo.toml index fe436ad15c85..1010d5f14c08 100644 --- a/netwerk/test/http3server/Cargo.toml +++ b/netwerk/test/http3server/Cargo.toml @@ -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" diff --git a/security/manager/ssl/builtins/Cargo.toml b/security/manager/ssl/builtins/Cargo.toml index b3f2e9c7b8cb..7065147cc92e 100644 --- a/security/manager/ssl/builtins/Cargo.toml +++ b/security/manager/ssl/builtins/Cargo.toml @@ -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] diff --git a/servo/components/style/Cargo.toml b/servo/components/style/Cargo.toml index 058ec115933b..51a0b5147596 100644 --- a/servo/components/style/Cargo.toml +++ b/servo/components/style/Cargo.toml @@ -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} diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index bfd8d4032afc..0980710b197c 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -681,11 +681,6 @@ who = "Mike Hommey " criteria = "safe-to-deploy" delta = "0.66.1 -> 0.68.1" -[[audits.bindgen]] -who = "Andreas Pehrson " -criteria = "safe-to-deploy" -delta = "0.68.1 -> 0.69.1" - [[audits.bit-set]] who = "Aria Beingessner " criteria = "safe-to-deploy" @@ -886,11 +881,6 @@ who = "Mike Hommey " criteria = "safe-to-deploy" delta = "0.2.12 -> 0.2.13" -[[audits.coreaudio-sys]] -who = "Andreas Pehrson " -criteria = "safe-to-deploy" -delta = "0.2.13 -> 0.2.14" - [[audits.cose]] who = "Mathew Hodson " criteria = "safe-to-deploy" diff --git a/third_party/rust/bindgen/.cargo-checksum.json b/third_party/rust/bindgen/.cargo-checksum.json index 7c2b890889ea..f5ef6db69d28 100644 --- a/third_party/rust/bindgen/.cargo-checksum.json +++ b/third_party/rust/bindgen/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e42a53f0727990f7c85c9faa0ba1934e51ce0f42ead43729cf25431b681a6e76","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"b2334e4077a9bc329516e3e0c7f89887c4f073647d95fb71b6917edf4c310ba3","build.rs":"4a9c4ac3759572e17de312a9d3f4ced3b6fd3c71811729e5a8d06bfbd1ac8f82","callbacks.rs":"cd5a1b0fc665b034d97615d0b6817cbef299dbf5276254c7e63f1c29674993ad","clang.rs":"5865e207df0c182c7433a08515cf1049d7885eb1273911cb2ea6155638b469a7","codegen/bitfield_unit.rs":"fddeaeab5859f4e82081865595b7705f5c0774d997df95fa5c655b81b9cae125","codegen/bitfield_unit_tests.rs":"9df86490de5e9d66ccea583dcb686dd440375dc1a3c3cf89a89d5de3883bf28a","codegen/dyngen.rs":"6d8bed53c6de66bc658b3186041c2b75549f49b0f0363ff18b87c8dcf2f5a05b","codegen/error.rs":"0c3d198f4866ccbbcd8b1136fc5cfd2507a9eca5ab85934af29a7e2a7d8d8c2a","codegen/helpers.rs":"0c28751565c90b4ab385ae2113cde02afa34225d85ae48fd296817aac36c5940","codegen/impl_debug.rs":"80df6136327b1ca8c7d1c2961290b5ab00b85b49b22c02f26a590bc68fb230af","codegen/impl_partialeq.rs":"db739d7ba6f5ba4033d6bf62c276f35217c20eab27230cf07dadf59e8b2f71bb","codegen/mod.rs":"d7f28d62feba79278ec2196c2fd23a9fbf28f28fcce55d209c5d8d6ea88e9673","codegen/postprocessing/merge_extern_blocks.rs":"284457a3c75e945217bab4e5a4280fef0fcc03c31e12cc5010aab87f34c0b6c7","codegen/postprocessing/mod.rs":"160a6d6701cabf2514e23570df1bd1b648c909cc27b7c583f21d98fe0c16722e","codegen/postprocessing/sort_semantically.rs":"f465d1e8cc119082eb79c164b5cd780a370821e8bf56585b287dd3b51fc4a542","codegen/serialize.rs":"c39112e01686f741eca4a89dca83a10e66c611b3d21d7c9548ba76f8c2d43a2b","codegen/struct_layout.rs":"07007251c91e0d4eb1e46535068d8c22881d248baa2e38cab96d72691927c2e4","deps.rs":"af3dd24a7808b5abf0c4ed4b10bbceb8eef32be980ff085b8a766d8f089af1a4","diagnostics.rs":"dc40cd5e9710922422c5c9420e2351f5d976e7a1d7275e4f4ce742cad9eb53f8","extra_assertions.rs":"fb4484c0e9fcbea9ec7265f5fbd01e2b33ac022b2b17e060dce7886819d57e40","features.rs":"29f2df89716a47a7d9dbd33b1ff4da61645e729a92772530bed3a04163afc08f","ir/analysis/derive.rs":"cba290e9c4ba271e90524149ad3b874f37843bfdfab12d513cc85d2665447fd5","ir/analysis/has_destructor.rs":"e7e95c3b0989b6375cd3eabaac85a36ecc2915a1fd3700c7d26fe04e8dc83ba3","ir/analysis/has_float.rs":"a56b97bf913f132c2c63dc202b45c692c416a8c9fdc6b2baeee30362fb0d4405","ir/analysis/has_type_param_in_array.rs":"788ebb4ba2cf46a22f1e4ff3005d51f38d414b72e95355f7ff4125521e2d9525","ir/analysis/has_vtable.rs":"83efa40ae89147170eabdff1387e60aba574ca4cd4cdef22692753594f09d6c6","ir/analysis/mod.rs":"9d949c27451da4ed72994b31c04ddeb89eeb342fd23ea572d3962d4ccf774841","ir/analysis/sizedness.rs":"f0a9302f3c6ad694d76cfab11dbaf5392ecaf7f04bc7b211a5a003776b963896","ir/analysis/template_params.rs":"3ff27e2198e292a348876aa1faba39cc4b1870a24a7e173feac0b3c592001e13","ir/annotations.rs":"5ed03d025862d0d21852a76c86a993772624e123fdc3752415d588a0b4e643ab","ir/comment.rs":"4c9c20b5a3da086211e92adec0822831dbc0b7ebee98fee313edcae9ae8d55ec","ir/comp.rs":"fb32715ed8fc14bee51c344a41c1f7a8a802d4a6dceb2775034ea33a88670df7","ir/context.rs":"a1c591532b44bc532c18f8e5afa0ba4aa94934db2de23f2c71dbdfcb384fd333","ir/derive.rs":"c21e470bb0091f20bfa366110880d48984fc3cf7071fdf36eccfa64f3eca231c","ir/dot.rs":"75bdfd83d9e754ba726f6a5529ba1d9ff46f5bf49bf237452985eb008fed0854","ir/enum_ty.rs":"f4bfa6d18ba4977fb66f5d5e4a7674eded93b761404d91cdd6fdd50029db455a","ir/function.rs":"8acde871c277069d94c96cf4dea68497b2d6253e66014db9655dd825906b19cc","ir/int.rs":"601736f0ad0949e40684a9ce89bafbfefa71743df6ee6c342e44888a0f141ae0","ir/item.rs":"0a58e318959266630e7e3b94d631c8a64b9a0eeaeae5a510c345fb6c3f6b088b","ir/item_kind.rs":"33e21104b0bb824a696a52cd520567ae56158010a1df14777e68ac5f8ad7e8fa","ir/layout.rs":"8fbafc0eeee17abb703a18613be1066e38838d4b67f5916f714bf545e545bc1a","ir/mod.rs":"a3b98b1732111a980a795c72eaf1e09101e842ef2de76b4f2d4a7857f8d4cee4","ir/module.rs":"b2961ffa4acb0c19f084c5db084b8a17bda7158066782a73b80ee7d838789bf9","ir/objc.rs":"8f57a9180d57a690449f20ed1be80209db5f8a410bb067ae8bf5e0ecab16a5e4","ir/template.rs":"3f59efa9670ca90215d4374be869c9dbecb98a8d1041e7c6e4ab69a62bb982c2","ir/traversal.rs":"a4ec73d3533d4b93386153baf6a2ca846ee51228c76ed51105229d3ddcd74466","ir/ty.rs":"69300e7f8255627da1a3fe641ffe7215f7889d4b3c0fcbf7c366b78e3849d5cb","ir/var.rs":"40d18226706de0ee5f002d0b5617dbcba35de0605edd531c75e3a76d000f0f4f","lib.rs":"1c5b0c2f6e71895059a0c0bf3b9bc0d6ff1c32cf296c8547e1b63d58fe589319","log_stubs.rs":"9f974e041e35c8c7e29985d27ae5cd0858d68f8676d1dc005c6388d7d011707f","options/as_args.rs":"76efa4e662cc7f89ef1c1fe089d03a3c1c019ffe2aa0a30a4d49ed41e987d1c7","options/helpers.rs":"f4a7681e29b2dcc3be9249478c499d685b9e29d4f4ca4ae8bff7a91668cd8f15","options/mod.rs":"2df5cd073da0f5fc68707551f6c86a9795225195da8e630a7670e49d205dc05d","parse.rs":"fce3616e0464aa7414888e5d00d4df18c83bb3034a1c807d36a07a3c586e475a","regex_set.rs":"b411d64bc803947a3f69dcedcd7d03716aacbc7b1c5148b82de1cc469d9336d9","time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"} \ No newline at end of file +{"files":{"Cargo.toml":"112e4ba01bb44e00e6ecc4a7408954b040424eeae34ad701030ef1b11cab0d36","LICENSE":"c23953d9deb0a3312dbeaf6c128a657f3591acee45067612fa68405eaa4525db","README.md":"b2334e4077a9bc329516e3e0c7f89887c4f073647d95fb71b6917edf4c310ba3","build.rs":"4a9c4ac3759572e17de312a9d3f4ced3b6fd3c71811729e5a8d06bfbd1ac8f82","callbacks.rs":"52211e15fa94fd0c8c5bab822dbf3e6a1e5500c6cd8c5b45c6c3b35627e2a416","clang.rs":"f7dc9c6eed9138075c0c26567e40269183192f9d04ff1701046ed3ac73d10b69","codegen/bitfield_unit.rs":"fddeaeab5859f4e82081865595b7705f5c0774d997df95fa5c655b81b9cae125","codegen/bitfield_unit_tests.rs":"9df86490de5e9d66ccea583dcb686dd440375dc1a3c3cf89a89d5de3883bf28a","codegen/dyngen.rs":"6d8bed53c6de66bc658b3186041c2b75549f49b0f0363ff18b87c8dcf2f5a05b","codegen/error.rs":"38fce9b4a06c6cd4b4b0a074417d2c9f31dac584b023b19b696cd00265a57930","codegen/helpers.rs":"0c28751565c90b4ab385ae2113cde02afa34225d85ae48fd296817aac36c5940","codegen/impl_debug.rs":"80df6136327b1ca8c7d1c2961290b5ab00b85b49b22c02f26a590bc68fb230af","codegen/impl_partialeq.rs":"db739d7ba6f5ba4033d6bf62c276f35217c20eab27230cf07dadf59e8b2f71bb","codegen/mod.rs":"61d3a0c226fba211dd3ef36bfa066f6963bff23406ef7961bfa5b79080f444d0","codegen/postprocessing/merge_extern_blocks.rs":"284457a3c75e945217bab4e5a4280fef0fcc03c31e12cc5010aab87f34c0b6c7","codegen/postprocessing/mod.rs":"160a6d6701cabf2514e23570df1bd1b648c909cc27b7c583f21d98fe0c16722e","codegen/postprocessing/sort_semantically.rs":"f465d1e8cc119082eb79c164b5cd780a370821e8bf56585b287dd3b51fc4a542","codegen/serialize.rs":"5cc71bcad2379df538cd179d1f8027c757f29e66a1cc130b222004adb698fa90","codegen/struct_layout.rs":"07007251c91e0d4eb1e46535068d8c22881d248baa2e38cab96d72691927c2e4","deps.rs":"af3dd24a7808b5abf0c4ed4b10bbceb8eef32be980ff085b8a766d8f089af1a4","diagnostics.rs":"dc40cd5e9710922422c5c9420e2351f5d976e7a1d7275e4f4ce742cad9eb53f8","extra_assertions.rs":"fb4484c0e9fcbea9ec7265f5fbd01e2b33ac022b2b17e060dce7886819d57e40","features.rs":"29f2df89716a47a7d9dbd33b1ff4da61645e729a92772530bed3a04163afc08f","ir/analysis/derive.rs":"cba290e9c4ba271e90524149ad3b874f37843bfdfab12d513cc85d2665447fd5","ir/analysis/has_destructor.rs":"e7e95c3b0989b6375cd3eabaac85a36ecc2915a1fd3700c7d26fe04e8dc83ba3","ir/analysis/has_float.rs":"a56b97bf913f132c2c63dc202b45c692c416a8c9fdc6b2baeee30362fb0d4405","ir/analysis/has_type_param_in_array.rs":"788ebb4ba2cf46a22f1e4ff3005d51f38d414b72e95355f7ff4125521e2d9525","ir/analysis/has_vtable.rs":"83efa40ae89147170eabdff1387e60aba574ca4cd4cdef22692753594f09d6c6","ir/analysis/mod.rs":"ed161d9f60306ad42af2ae70ff0eb686a36e2fb30eb94918b5e5f19af80e1db7","ir/analysis/sizedness.rs":"f0a9302f3c6ad694d76cfab11dbaf5392ecaf7f04bc7b211a5a003776b963896","ir/analysis/template_params.rs":"3ff27e2198e292a348876aa1faba39cc4b1870a24a7e173feac0b3c592001e13","ir/annotations.rs":"5ed03d025862d0d21852a76c86a993772624e123fdc3752415d588a0b4e643ab","ir/comment.rs":"4c9c20b5a3da086211e92adec0822831dbc0b7ebee98fee313edcae9ae8d55ec","ir/comp.rs":"fb32715ed8fc14bee51c344a41c1f7a8a802d4a6dceb2775034ea33a88670df7","ir/context.rs":"a1c591532b44bc532c18f8e5afa0ba4aa94934db2de23f2c71dbdfcb384fd333","ir/derive.rs":"c21e470bb0091f20bfa366110880d48984fc3cf7071fdf36eccfa64f3eca231c","ir/dot.rs":"75bdfd83d9e754ba726f6a5529ba1d9ff46f5bf49bf237452985eb008fed0854","ir/enum_ty.rs":"f4bfa6d18ba4977fb66f5d5e4a7674eded93b761404d91cdd6fdd50029db455a","ir/function.rs":"8acde871c277069d94c96cf4dea68497b2d6253e66014db9655dd825906b19cc","ir/int.rs":"601736f0ad0949e40684a9ce89bafbfefa71743df6ee6c342e44888a0f141ae0","ir/item.rs":"2d3d25c9877d3b969cba5d49696ccabdd382f38c1ab28ac32b79021008a66b19","ir/item_kind.rs":"33e21104b0bb824a696a52cd520567ae56158010a1df14777e68ac5f8ad7e8fa","ir/layout.rs":"8fbafc0eeee17abb703a18613be1066e38838d4b67f5916f714bf545e545bc1a","ir/mod.rs":"a3b98b1732111a980a795c72eaf1e09101e842ef2de76b4f2d4a7857f8d4cee4","ir/module.rs":"b2961ffa4acb0c19f084c5db084b8a17bda7158066782a73b80ee7d838789bf9","ir/objc.rs":"126c688946a7157eff8fd3a22125c6250d0a2c63ee766662b50ea241f7cd3493","ir/template.rs":"3f59efa9670ca90215d4374be869c9dbecb98a8d1041e7c6e4ab69a62bb982c2","ir/traversal.rs":"a4ec73d3533d4b93386153baf6a2ca846ee51228c76ed51105229d3ddcd74466","ir/ty.rs":"69300e7f8255627da1a3fe641ffe7215f7889d4b3c0fcbf7c366b78e3849d5cb","ir/var.rs":"40d18226706de0ee5f002d0b5617dbcba35de0605edd531c75e3a76d000f0f4f","lib.rs":"c3aff945fe2e3d498682e605a9abdd748fee71b78885d3699f4e6397b082ca87","log_stubs.rs":"9f974e041e35c8c7e29985d27ae5cd0858d68f8676d1dc005c6388d7d011707f","options/as_args.rs":"76efa4e662cc7f89ef1c1fe089d03a3c1c019ffe2aa0a30a4d49ed41e987d1c7","options/helpers.rs":"f4a7681e29b2dcc3be9249478c499d685b9e29d4f4ca4ae8bff7a91668cd8f15","options/mod.rs":"9f3e982fe8e3723bfceda5905a144d6717210bc872c4350bd9d8873496eba2a2","parse.rs":"fce3616e0464aa7414888e5d00d4df18c83bb3034a1c807d36a07a3c586e475a","regex_set.rs":"b411d64bc803947a3f69dcedcd7d03716aacbc7b1c5148b82de1cc469d9336d9","time.rs":"8efe317e7c6b5ba8e0865ce7b49ca775ee8a02590f4241ef62f647fa3c22b68e"},"package":"726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078"} \ No newline at end of file diff --git a/third_party/rust/bindgen/Cargo.toml b/third_party/rust/bindgen/Cargo.toml index 24132d62d6d0..bff6eee2d3ce 100644 --- a/third_party/rust/bindgen/Cargo.toml +++ b/third_party/rust/bindgen/Cargo.toml @@ -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 ", "Emilio Cobos Álvarez ", @@ -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" diff --git a/third_party/rust/bindgen/callbacks.rs b/third_party/rust/bindgen/callbacks.rs index c22ba975dd31..a9d315dca79e 100644 --- a/third_party/rust/bindgen/callbacks.rs +++ b/third_party/rust/bindgen/callbacks.rs @@ -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) {} diff --git a/third_party/rust/bindgen/clang.rs b/third_party/rust/bindgen/clang.rs index 3438bfa2c4af..db239ebc770e 100644 --- a/third_party/rust/bindgen/clang.rs +++ b/third_party/rust/bindgen/clang.rs @@ -1820,7 +1820,7 @@ impl TranslationUnit { let fname = CString::new(file).unwrap(); let _c_args: Vec = 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(); diff --git a/third_party/rust/bindgen/codegen/error.rs b/third_party/rust/bindgen/codegen/error.rs index 82e921d771c5..2c9bf9768047 100644 --- a/third_party/rust/bindgen/codegen/error.rs +++ b/third_party/rust/bindgen/codegen/error.rs @@ -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) - } - } + }) } } diff --git a/third_party/rust/bindgen/codegen/mod.rs b/third_party/rust/bindgen/codegen/mod.rs index 8e1360634547..bc8e3ec7113a 100644 --- a/third_party/rust/bindgen/codegen/mod.rs +++ b/third_party/rust/bindgen/codegen/mod.rs @@ -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 = diff --git a/third_party/rust/bindgen/codegen/serialize.rs b/third_party/rust/bindgen/codegen/serialize.rs index 02c46802632b..58e0882fafd7 100644 --- a/third_party/rust/bindgen/codegen/serialize.rs +++ b/third_party/rust/bindgen/codegen/serialize.rs @@ -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() { diff --git a/third_party/rust/bindgen/ir/analysis/mod.rs b/third_party/rust/bindgen/ir/analysis/mod.rs index 443384a48777..0263088a99b0 100644 --- a/third_party/rust/bindgen/ir/analysis/mod.rs +++ b/third_party/rust/bindgen/ir/analysis/mod.rs @@ -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); diff --git a/third_party/rust/bindgen/ir/item.rs b/third_party/rust/bindgen/ir/item.rs index 0556452bfae1..4abca5c49bb6 100644 --- a/third_party/rust/bindgen/ir/item.rs +++ b/third_party/rust/bindgen/ir/item.rs @@ -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 diff --git a/third_party/rust/bindgen/ir/objc.rs b/third_party/rust/bindgen/ir/objc.rs index 93d8b3bfdf44..2ebf38b8ca52 100644 --- a/third_party/rust/bindgen/ir/objc.rs +++ b/third_party/rust/bindgen/ir/objc.rs @@ -253,24 +253,11 @@ impl ObjCMethod { let split_name: Vec> = 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 diff --git a/third_party/rust/bindgen/lib.rs b/third_party/rust/bindgen/lib.rs index 54348e223259..05f95bf8f5f1 100644 --- a/third_party/rust/bindgen/lib.rs +++ b/third_party/rust/bindgen/lib.rs @@ -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); } diff --git a/third_party/rust/bindgen/options/mod.rs b/third_party/rust/bindgen/options/mod.rs index 3a82bcf397c8..558f5343a291 100644 --- a/third_party/rust/bindgen/options/mod.rs +++ b/third_party/rust/bindgen/options/mod.rs @@ -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 { diff --git a/third_party/rust/coreaudio-sys-utils/.cargo-checksum.json b/third_party/rust/coreaudio-sys-utils/.cargo-checksum.json index 114eecd0e169..978440f867be 100644 --- a/third_party/rust/coreaudio-sys-utils/.cargo-checksum.json +++ b/third_party/rust/coreaudio-sys-utils/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/coreaudio-sys-utils/Cargo.toml b/third_party/rust/coreaudio-sys-utils/Cargo.toml index 7086422a28a9..7afdb69775e5 100644 --- a/third_party/rust/coreaudio-sys-utils/Cargo.toml +++ b/third_party/rust/coreaudio-sys-utils/Cargo.toml @@ -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 diff --git a/third_party/rust/coreaudio-sys-utils/src/dispatch.rs b/third_party/rust/coreaudio-sys-utils/src/dispatch.rs index 602304bde89e..ee115f96769e 100644 --- a/third_party/rust/coreaudio-sys-utils/src/dispatch.rs +++ b/third_party/rust/coreaudio-sys-utils/src/dispatch.rs @@ -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(&self, work: F) where F: Send + FnOnce(), diff --git a/third_party/rust/coreaudio-sys/.cargo-checksum.json b/third_party/rust/coreaudio-sys/.cargo-checksum.json index 51eec39c9652..692409faaf34 100644 --- a/third_party/rust/coreaudio-sys/.cargo-checksum.json +++ b/third_party/rust/coreaudio-sys/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"21b0b00002a9b66a31357ddc5ac4c0f2a1702c85f6303cc7309e9dc7ffcaefd8","LICENSE":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"a8adeaf1947035175b890109b36604ac3676f887911b5b8debd216689c0b65bd","build.rs":"d109f0a043b4f62bee52674888a52595f9b0dc37345815905a12ad0723ab8de5","src/lib.rs":"22c9dbbb1dc38d6f77b9362e806a7ee59a8ca1aa9b2c9344d1a487a91287ed59"},"package":"f3120ebb80a9de008e638ad833d4127d50ea3d3a960ea23ea69bc66d9358a028"} \ No newline at end of file +{"files":{"Cargo.toml":"17c9796d79b692e07056a6f6b45fcb8160c98385d9dd46c3a3d67a02865b3d33","LICENSE":"7576269ea71f767b99297934c0b2367532690f8c4badc695edf8e04ab6a1e545","README.md":"a8adeaf1947035175b890109b36604ac3676f887911b5b8debd216689c0b65bd","build.rs":"e3d45b1a17b655996a09b1d8f5f4dabb8c574e5b803814a13494f56dfce32f4e","src/lib.rs":"22c9dbbb1dc38d6f77b9362e806a7ee59a8ca1aa9b2c9344d1a487a91287ed59"},"package":"d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d"} \ No newline at end of file diff --git a/third_party/rust/coreaudio-sys/Cargo.toml b/third_party/rust/coreaudio-sys/Cargo.toml index ee12ab1abbae..7b830353c193 100644 --- a/third_party/rust/coreaudio-sys/Cargo.toml +++ b/third_party/rust/coreaudio-sys/Cargo.toml @@ -11,7 +11,7 @@ [package] name = "coreaudio-sys" -version = "0.2.14" +version = "0.2.13" authors = ["Mitchell Nordine "] 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 = [] diff --git a/third_party/rust/coreaudio-sys/build.rs b/third_party/rust/coreaudio-sys/build.rs index 7083f9c318fb..81cfbcc855a2 100644 --- a/third_party/rust/coreaudio-sys/build.rs +++ b/third_party/rust/coreaudio-sys/build.rs @@ -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"); diff --git a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json index c9b2a726ca20..4c9fe0f14d66 100644 --- a/third_party/rust/cubeb-coreaudio/.cargo-checksum.json +++ b/third_party/rust/cubeb-coreaudio/.cargo-checksum.json @@ -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} \ No newline at end of file +{"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} \ No newline at end of file diff --git a/third_party/rust/cubeb-coreaudio/Cargo.toml b/third_party/rust/cubeb-coreaudio/Cargo.toml index bc4a8459f1e8..7512f8293eaa 100644 --- a/third_party/rust/cubeb-coreaudio/Cargo.toml +++ b/third_party/rust/cubeb-coreaudio/Cargo.toml @@ -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" diff --git a/third_party/rust/cubeb-coreaudio/run_device_tests.sh b/third_party/rust/cubeb-coreaudio/run_device_tests.sh index ae6df49713f4..b1a8f1e96457 100755 --- a/third_party/rust/cubeb-coreaudio/run_device_tests.sh +++ b/third_party/rust/cubeb-coreaudio/run_device_tests.sh @@ -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 diff --git a/third_party/rust/cubeb-coreaudio/run_sanitizers.sh b/third_party/rust/cubeb-coreaudio/run_sanitizers.sh index 7e24860f7deb..65956fe09754 100755 --- a/third_party/rust/cubeb-coreaudio/run_sanitizers.sh +++ b/third_party/rust/cubeb-coreaudio/run_sanitizers.sh @@ -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}" diff --git a/third_party/rust/cubeb-coreaudio/src/backend/aggregate_device.rs b/third_party/rust/cubeb-coreaudio/src/backend/aggregate_device.rs index 2738631b87af..5dc4a17fbfd4 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/aggregate_device.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/aggregate_device.rs @@ -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>, 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, Condvar)>) }; - let (lock, cvar) = &**pair; + let &(ref lock, ref cvar) = &**pair; let mut device = lock.lock().unwrap(); *device = id; cvar.notify_one(); diff --git a/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs b/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs index b9a50c6576d9..150539217003 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/device_property.rs @@ -223,49 +223,13 @@ pub fn get_ranges_of_device_sample_rate( } } -pub fn get_stream_latency(id: AudioStreamID) -> std::result::Result { - assert_ne!(id, kAudioObjectUnknown); - - let address = get_property_address( - Property::StreamLatency, - DeviceType::INPUT | DeviceType::OUTPUT, - ); - let mut size = mem::size_of::(); - 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 { - assert_ne!(id, kAudioObjectUnknown); - - let address = get_property_address( - Property::StreamTerminalType, - DeviceType::INPUT | DeviceType::OUTPUT, - ); - let mut size = mem::size_of::(); - 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 { 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::(); 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, 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 = 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 { + assert_ne!(id, kAudioObjectUnknown); + + let address = get_property_address(Property::StreamLatency, devtype); + let mut size = mem::size_of::(); + 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 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 for AudioObjectPropertySelector { Property::HardwareDevices => kAudioHardwarePropertyDevices, Property::ModelUID => kAudioDevicePropertyModelUID, Property::StreamLatency => kAudioStreamPropertyLatency, - Property::StreamTerminalType => kAudioStreamPropertyTerminalType, - Property::StreamVirtualFormat => kAudioStreamPropertyVirtualFormat, Property::TransportType => kAudioDevicePropertyTransportType, Property::ClockDomain => kAudioDevicePropertyClockDomain, } diff --git a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs index 7c896edfdfae..65e3eb97f981 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs @@ -42,7 +42,7 @@ use std::cmp; use std::ffi::{CStr, CString}; use std::fmt; use std::mem; -use std::os::raw::{c_uint, c_void}; +use std::os::raw::c_void; use std::ptr; use std::slice; use std::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; @@ -55,7 +55,6 @@ const AU_IN_BUS: AudioUnitElement = 1; const DISPATCH_QUEUE_LABEL: &str = "org.mozilla.cubeb"; const PRIVATE_AGGREGATE_DEVICE_NAME: &str = "CubebAggregateDevice"; -const VOICEPROCESSING_AGGREGATE_DEVICE_NAME: &str = "VPAUAggregateAudioDevice"; // Testing empirically, some headsets report a minimal latency that is very low, // but this does not work in practice. Lie and say the minimum is 128 frames. @@ -64,7 +63,6 @@ const SAFE_MAX_LATENCY_FRAMES: u32 = 512; bitflags! { #[allow(non_camel_case_types)] - #[derive(Clone, Debug, PartialEq, Copy)] struct device_flags: u32 { const DEV_UNKNOWN = 0b0000_0000; // Unknown const DEV_INPUT = 0b0000_0001; // Record device like mic @@ -295,7 +293,7 @@ fn minimum_resampling_input_frames( (input_rate * output_frames as f64 / output_rate).ceil() as usize } -fn audiounit_make_silent(io_data: &AudioBuffer) { +fn audiounit_make_silent(io_data: &mut AudioBuffer) { assert!(!io_data.mData.is_null()); let bytes = unsafe { let ptr = io_data.mData as *mut u8; @@ -325,7 +323,6 @@ extern "C" fn audiounit_input_callback( assert!(!user_ptr.is_null()); let stm = unsafe { &mut *(user_ptr as *mut AudioUnitStream) }; - let using_voice_processing_unit = stm.core_stream_data.using_voice_processing_unit(); if unsafe { *flags | kAudioTimeStampHostTimeValid } != 0 { let now = unsafe { mach_absolute_time() }; @@ -466,9 +463,8 @@ extern "C" fn audiounit_input_callback( }; // If the input (input-only stream) or the output is drained (duplex stream), - // cancel this callback. Note that for voice processing cases (a single unit), - // the output callback handles stopping the unit and notifying of state. - if !using_voice_processing_unit && stm.draining.load(Ordering::SeqCst) { + // cancel this callback. + if stm.draining.load(Ordering::SeqCst) { let r = stop_audiounit(stm.core_stream_data.input_unit); assert!(r.is_ok()); // Only fire state-changed callback for input-only stream. @@ -544,7 +540,7 @@ extern "C" fn audiounit_output_callback( if stm.stopped.load(Ordering::SeqCst) { cubeb_alog!("({:p}) output stopped.", stm as *const AudioUnitStream); - audiounit_make_silent(&buffers[0]); + audiounit_make_silent(&mut buffers[0]); return NO_ERR; } @@ -554,7 +550,7 @@ extern "C" fn audiounit_output_callback( let r = stop_audiounit(stm.core_stream_data.output_unit); assert!(r.is_ok()); stm.notify_state_changed(State::Drained); - audiounit_make_silent(&buffers[0]); + audiounit_make_silent(&mut buffers[0]); return NO_ERR; } @@ -685,7 +681,7 @@ extern "C" fn audiounit_output_callback( queue.run_async(move || { stm.core_stream_data.stop_audiounits(); }); - audiounit_make_silent(&buffers[0]); + audiounit_make_silent(&mut buffers[0]); return NO_ERR; } @@ -755,7 +751,7 @@ extern "C" fn audiounit_property_listener_callback( } stm.switching_device.store(true, Ordering::SeqCst); - let mut explicit_device_dead = false; + let mut input_device_dead = false; cubeb_log!( "({:p}) Handling {} device changed events for device {}", @@ -768,21 +764,16 @@ extern "C" fn audiounit_property_listener_callback( cubeb_log!("Event #{}: {}", i, p); assert_ne!(p, PropertySelector::Unknown); if p == PropertySelector::DeviceIsAlive { - explicit_device_dead = true; + input_device_dead = true; } } // Handle the events - if explicit_device_dead { - cubeb_log!("The user-selected input or output device is dead, entering error state"); + if input_device_dead { + cubeb_log!("The user-selected input device is dead, entering error state"); stm.stopped.store(true, Ordering::SeqCst); - - // Use a different thread, through the queue, to avoid deadlock when calling - // Get/SetProperties method from inside notify callback - stm.queue.clone().run_async(move || { - stm.core_stream_data.stop_audiounits(); - stm.close_on_error(); - }); + stm.core_stream_data.stop_audiounits(); + stm.close_on_error(); return NO_ERR; } { @@ -833,14 +824,14 @@ fn get_default_device_id(devtype: DeviceType) -> std::result::Result Result> { +fn audiounit_convert_channel_layout(layout: &AudioChannelLayout) -> Vec { if layout.mChannelLayoutTag != kAudioChannelLayoutTag_UseChannelDescriptions { // kAudioChannelLayoutTag_UseChannelBitmap // kAudioChannelLayoutTag_Mono // kAudioChannelLayoutTag_Stereo // .... cubeb_log!("Only handling UseChannelDescriptions for now.\n"); - return Err(Error::error()); + return Vec::new(); } let channel_descriptions = unsafe { @@ -856,10 +847,10 @@ fn audiounit_convert_channel_layout(layout: &AudioChannelLayout) -> Result Result> { +fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Vec { let mut rv = NO_ERR; let mut size: usize = 0; rv = audio_unit_get_property_info( @@ -875,7 +866,7 @@ fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Result 0); @@ -893,7 +884,7 @@ fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Result Result Result> { +fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Vec { let mut rv = NO_ERR; let mut size: usize = 0; rv = audio_unit_get_property_info( @@ -917,7 +908,8 @@ fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Result 0); @@ -935,25 +927,12 @@ fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Result Result> { - audiounit_get_current_channel_layout(output_unit) - .or_else(|_| { - // The kAudioUnitProperty_AudioChannelLayout property isn't known before - // macOS 10.12, attempt another method. - cubeb_log!( - "Cannot get current channel layout for audiounit @ {:p}. Trying preferred channel layout.", - output_unit - ); - audiounit_get_preferred_channel_layout(output_unit) - }) -} - fn start_audiounit(unit: AudioUnit) -> Result<()> { let status = audio_output_unit_start(unit); if status == NO_ERR { @@ -983,96 +962,39 @@ fn create_audiounit(device: &device_info) -> Result { .contains(device_flags::DEV_INPUT | device_flags::DEV_OUTPUT)); let unit = create_blank_audiounit()?; - let mut bus = AU_OUT_BUS; if device.flags.contains(device_flags::DEV_INPUT) { // Input only. - if let Err(e) = enable_audiounit_scope(unit, DeviceType::INPUT, true) { - cubeb_log!("Failed to enable audiounit input scope. Error: {}", e); - dispose_audio_unit(unit); - return Err(Error::error()); - } - if let Err(e) = enable_audiounit_scope(unit, DeviceType::OUTPUT, false) { - cubeb_log!("Failed to disable audiounit output scope. Error: {}", e); - dispose_audio_unit(unit); - return Err(Error::error()); - } - bus = AU_IN_BUS; + enable_audiounit_scope(unit, DeviceType::INPUT, true).map_err(|e| { + cubeb_log!("Fail to enable audiounit input scope. Error: {}", e); + Error::error() + })?; + enable_audiounit_scope(unit, DeviceType::OUTPUT, false).map_err(|e| { + cubeb_log!("Fail to disable audiounit output scope. Error: {}", e); + Error::error() + })?; } if device.flags.contains(device_flags::DEV_OUTPUT) { // Output only. - if let Err(e) = enable_audiounit_scope(unit, DeviceType::OUTPUT, true) { - cubeb_log!("Failed to enable audiounit output scope. Error: {}", e); - dispose_audio_unit(unit); - return Err(Error::error()); - } - if let Err(e) = enable_audiounit_scope(unit, DeviceType::INPUT, false) { - cubeb_log!("Failed to disable audiounit input scope. Error: {}", e); - dispose_audio_unit(unit); - return Err(Error::error()); - } - bus = AU_OUT_BUS; + enable_audiounit_scope(unit, DeviceType::OUTPUT, true).map_err(|e| { + cubeb_log!("Fail to enable audiounit output scope. Error: {}", e); + Error::error() + })?; + enable_audiounit_scope(unit, DeviceType::INPUT, false).map_err(|e| { + cubeb_log!("Fail to disable audiounit input scope. Error: {}", e); + Error::error() + })?; } - if let Err(e) = set_device_to_audiounit(unit, device.id, bus) { + set_device_to_audiounit(unit, device.id).map_err(|e| { cubeb_log!( "Failed to set device {} to the created audiounit. Error: {}", device.id, e ); - dispose_audio_unit(unit); - return Err(Error::error()); - } - - Ok(unit) -} - -fn create_voiceprocessing_audiounit( - in_device: &device_info, - out_device: &device_info, -) -> Result { - assert!(in_device.flags.contains(device_flags::DEV_INPUT)); - assert!(!in_device.flags.contains(device_flags::DEV_OUTPUT)); - assert!(!out_device.flags.contains(device_flags::DEV_INPUT)); - assert!(out_device.flags.contains(device_flags::DEV_OUTPUT)); - - let unit = create_typed_audiounit(kAudioUnitSubType_VoiceProcessingIO)?; - - if let Err(e) = set_device_to_audiounit(unit, in_device.id, AU_IN_BUS) { - cubeb_log!( - "Failed to set in device {} to the created audiounit. Error: {}", - in_device.id, - e - ); - dispose_audio_unit(unit); - return Err(Error::error()); - } - - if let Err(e) = set_device_to_audiounit(unit, out_device.id, AU_OUT_BUS) { - cubeb_log!( - "Failed to set out device {} to the created audiounit. Error: {}", - out_device.id, - e - ); - dispose_audio_unit(unit); - return Err(Error::error()); - } - - let bypass = u32::from(true); - let r = audio_unit_set_property( - unit, - kAudioUnitProperty_BypassEffect, - kAudioUnitScope_Global, - AU_IN_BUS, - &bypass, - mem::size_of::(), - ); - if r != NO_ERR { - cubeb_log!("Failed to enable bypass of voiceprocessing. Error: {}", r); - dispose_audio_unit(unit); - return Err(Error::error()); - } + Error::error() + })?; Ok(unit) } @@ -1111,7 +1033,6 @@ fn enable_audiounit_scope( fn set_device_to_audiounit( unit: AudioUnit, device_id: AudioObjectID, - bus: AudioUnitElement, ) -> std::result::Result<(), OSStatus> { assert!(!unit.is_null()); @@ -1119,7 +1040,7 @@ fn set_device_to_audiounit( unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, - bus, + 0, &device_id, mem::size_of::(), ); @@ -1130,10 +1051,13 @@ fn set_device_to_audiounit( } } -fn create_typed_audiounit(sub_type: c_uint) -> Result { +fn create_blank_audiounit() -> Result { let desc = AudioComponentDescription { componentType: kAudioUnitType_Output, - componentSubType: sub_type, + #[cfg(not(target_os = "ios"))] + componentSubType: kAudioUnitSubType_HALOutput, + #[cfg(target_os = "ios")] + componentSubType: kAudioUnitSubType_RemoteIO, componentManufacturer: kAudioUnitManufacturer_Apple, componentFlags: 0, componentFlagsMask: 0, @@ -1155,13 +1079,6 @@ fn create_typed_audiounit(sub_type: c_uint) -> Result { } } -fn create_blank_audiounit() -> Result { - #[cfg(not(target_os = "ios"))] - return create_typed_audiounit(kAudioUnitSubType_HALOutput); - #[cfg(target_os = "ios")] - return create_typed_audiounit(kAudioUnitSubType_RemoteIO); -} - fn get_buffer_size(unit: AudioUnit, devtype: DeviceType) -> std::result::Result { assert!(!unit.is_null()); let (scope, element) = match devtype { @@ -1276,7 +1193,7 @@ fn set_buffer_size_sync(unit: AudioUnit, devtype: DeviceType, frames: u32) -> Re Error::error() })?; - let (lock, cvar) = &*pair; + let &(ref lock, ref cvar) = &*pair; let changed = lock.lock().unwrap(); if !*changed { let (chg, timeout_res) = cvar.wait_timeout(changed, waiting_time).unwrap(); @@ -1322,7 +1239,7 @@ fn set_buffer_size_sync(unit: AudioUnit, devtype: DeviceType, frames: u32) -> Re assert!(in_element == AU_IN_BUS || in_element == AU_OUT_BUS); assert_eq!(in_property_id, kAudioDevicePropertyBufferFrameSize); let pair = unsafe { &mut *(in_client_data as *mut Arc<(Mutex, Condvar)>) }; - let (lock, cvar) = &**pair; + let &(ref lock, ref cvar) = &**pair; let mut changed = lock.lock().unwrap(); *changed = true; cvar.notify_one(); @@ -1364,48 +1281,10 @@ fn get_channel_count( ) -> std::result::Result { assert_ne!(devid, kAudioObjectUnknown); - let mut streams = get_device_streams(devid, devtype)?; - - if devtype == DeviceType::INPUT { - // With VPIO, output devices will/may get a Tap that appears as input channels on the - // output device id. One could check for whether the output device has a tap enabled, - // but it is impossible to distinguish an output-only device from an input+output - // device. There have also been corner cases observed, where the device does NOT have - // a Tap enabled, but it still has the extra input channels from the Tap. - // We can check the terminal type of the input stream instead -- if it is - // INPUT_UNDEFINED (reported to be the VPIO type according to Chromium) or any - // non-input-only terminal type, we ignore it when counting channels (and thereby - // determining whether we are dealing with an input device). - streams.retain(|stream| { - let terminal_type = get_stream_terminal_type(*stream); - if terminal_type.is_err() { - return true; - } - - #[allow(non_upper_case_globals)] - match terminal_type.unwrap() { - kAudioStreamTerminalTypeMicrophone - | kAudioStreamTerminalTypeHeadsetMicrophone - | kAudioStreamTerminalTypeReceiverMicrophone => true, - t if t > INPUT_UNDEFINED && t < OUTPUT_UNDEFINED => true, - t if t > BIDIRECTIONAL_UNDEFINED && t < TELEPHONY_UNDEFINED => true, - t if t > TELEPHONY_UNDEFINED && t < EXTERNAL_UNDEFINED => true, - t => { - cubeb_log!( - "Unexpected TerminalType {:06X} for input stream. Ignoring its channels.", - t - ); - false - } - } - }); - } - + let buffers = get_device_stream_configuration(devid, devtype)?; let mut count = 0; - for stream in streams { - if let Ok(format) = get_stream_virtual_format(stream) { - count += format.mChannelsPerFrame; - } + for buffer in buffers { + count += buffer.mNumberChannels; } Ok(count) } @@ -1457,7 +1336,7 @@ fn get_fixed_latency(devid: AudioObjectID, devtype: DeviceType) -> u32 { ); Ok(0) // default stream latency } else { - get_stream_latency(streams[0]) + get_stream_latency(streams[0], devtype) } }).map_err(|e| { cubeb_log!( @@ -1565,9 +1444,6 @@ fn create_cubeb_device_info( devid: AudioObjectID, devtype: DeviceType, ) -> Result { - if devtype != DeviceType::INPUT && devtype != DeviceType::OUTPUT { - return Err(Error::error()); - } let channels = get_channel_count(devid, devtype).map_err(|e| { cubeb_log!("Cannot get the channel count. Error: {}", e); Error::error() @@ -1711,6 +1587,19 @@ fn create_cubeb_device_info( Ok(dev_info) } +fn is_aggregate_device(device_info: &ffi::cubeb_device_info) -> bool { + assert!(!device_info.friendly_name.is_null()); + let private_name = + CString::new(PRIVATE_AGGREGATE_DEVICE_NAME).expect("Fail to create a private name"); + unsafe { + libc::strncmp( + device_info.friendly_name, + private_name.as_ptr(), + private_name.as_bytes().len(), + ) == 0 + } +} + fn destroy_cubeb_device_info(device: &mut ffi::cubeb_device_info) { // This should be mapped to the memory allocation in `create_cubeb_device_info`. // The `device_id`, `group_id`, `vendor_name` can be null pointer if the queries @@ -1776,7 +1665,6 @@ fn audiounit_get_devices_of_type(devtype: DeviceType) -> Vec { } else 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 { // Fail to get device uid. true @@ -2176,7 +2064,9 @@ impl ContextOps for AudioUnitContext { let devices = audiounit_get_devices_of_type(*dev_type); for device in devices { if let Ok(info) = create_cubeb_device_info(device, *dev_type) { - device_infos.push(info); + if !is_aggregate_device(&info) { + device_infos.push(info); + } } } } @@ -2218,23 +2108,9 @@ impl ContextOps for AudioUnitContext { state_callback: ffi::cubeb_state_callback, user_ptr: *mut c_void, ) -> Result { - if !input_device.is_null() && input_stream_params.is_none() { - cubeb_log!("Cannot init an input device without input stream params"); - return Err(Error::invalid_parameter()); - } - - if !output_device.is_null() && output_stream_params.is_none() { - cubeb_log!("Cannot init an output device without output stream params"); - return Err(Error::invalid_parameter()); - } - - if input_stream_params.is_none() && output_stream_params.is_none() { - cubeb_log!("Cannot init a stream without any stream params"); - return Err(Error::invalid_parameter()); - } - - if data_callback.is_none() { - cubeb_log!("Cannot init a stream without a data callback"); + if (!input_device.is_null() && input_stream_params.is_none()) + || (!output_device.is_null() && output_stream_params.is_none()) + { return Err(Error::invalid_parameter()); } @@ -2296,11 +2172,7 @@ impl ContextOps for AudioUnitContext { boxed_stream.core_stream_data = CoreStreamData::new(boxed_stream.as_ref(), in_stm_settings, out_stm_settings); - let mut result = Ok(()); - boxed_stream.queue.clone().run_sync(|| { - result = boxed_stream.core_stream_data.setup(); - }); - if let Err(r) = result { + if let Err(r) = boxed_stream.core_stream_data.setup() { cubeb_log!( "({:p}) Could not setup the audiounit stream.", boxed_stream.as_ref() @@ -2430,7 +2302,6 @@ struct CoreStreamData<'ctx> { default_output_listener: Option, input_alive_listener: Option, input_source_listener: Option, - output_alive_listener: Option, output_source_listener: Option, input_logging: Option, } @@ -2467,7 +2338,6 @@ impl<'ctx> Default for CoreStreamData<'ctx> { default_output_listener: None, input_alive_listener: None, input_source_listener: None, - output_alive_listener: None, output_source_listener: None, input_logging: None, } @@ -2511,22 +2381,12 @@ impl<'ctx> CoreStreamData<'ctx> { default_output_listener: None, input_alive_listener: None, input_source_listener: None, - output_alive_listener: None, output_source_listener: None, input_logging: None, } } - fn debug_assert_is_on_stream_queue(&self) { - if self.stm_ptr.is_null() { - return; - } - let stm = unsafe { &*self.stm_ptr }; - stm.queue.debug_assert_is_current(); - } - fn start_audiounits(&self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); // Only allowed to be called after the stream is initialized // and before the stream is destroyed. debug_assert!(!self.input_unit.is_null() || !self.output_unit.is_null()); @@ -2534,10 +2394,6 @@ impl<'ctx> CoreStreamData<'ctx> { if !self.input_unit.is_null() { start_audiounit(self.input_unit)?; } - if self.using_voice_processing_unit() { - // Handle the VoiceProcessIO case where there is a single unit. - return Ok(()); - } if !self.output_unit.is_null() { start_audiounit(self.output_unit)?; } @@ -2545,15 +2401,10 @@ impl<'ctx> CoreStreamData<'ctx> { } fn stop_audiounits(&self) { - self.debug_assert_is_on_stream_queue(); if !self.input_unit.is_null() { let r = stop_audiounit(self.input_unit); assert!(r.is_ok()); } - if self.using_voice_processing_unit() { - // Handle the VoiceProcessIO case where there is a single unit. - return; - } if !self.output_unit.is_null() { let r = stop_audiounit(self.output_unit); assert!(r.is_ok()); @@ -2568,12 +2419,45 @@ impl<'ctx> CoreStreamData<'ctx> { self.output_stream_params.rate() > 0 } - fn using_voice_processing_unit(&self) -> bool { - !self.input_unit.is_null() && self.input_unit == self.output_unit + fn should_use_aggregate_device(&self) -> bool { + // It's impossible to create an aggregate device from an aggregate device, and it's + // unnecessary to create an aggregate device when opening the same device input/output. In + // all other cases, use an aggregate device. + let mut either_already_aggregate = false; + if self.has_input() { + let input_is_aggregate = + get_device_transport_type(self.input_device.id, DeviceType::INPUT).unwrap_or(0) + == kAudioDeviceTransportTypeAggregate; + if input_is_aggregate { + either_already_aggregate = true; + } + cubeb_log!( + "Input device ID: {} (aggregate: {:?})", + self.input_device.id, + input_is_aggregate + ); + } + if self.has_output() { + let output_is_aggregate = + get_device_transport_type(self.output_device.id, DeviceType::OUTPUT).unwrap_or(0) + == kAudioDeviceTransportTypeAggregate; + if output_is_aggregate { + either_already_aggregate = true; + } + cubeb_log!( + "Output device ID: {} (aggregate: {:?})", + self.input_device.id, + output_is_aggregate + ); + } + // Only use an aggregate device when the device are different. + self.has_input() + && self.has_output() + && self.input_device.id != self.output_device.id + && !either_already_aggregate } fn same_clock_domain(&self) -> bool { - self.debug_assert_is_on_stream_queue(); // If not setting up a duplex stream, there is only one device, // no reclocking necessary. if !(self.has_input() && self.has_output()) { @@ -2597,168 +2481,24 @@ impl<'ctx> CoreStreamData<'ctx> { input_domain == output_domain } - fn create_audiounits(&mut self) -> Result<(device_info, device_info)> { - self.debug_assert_is_on_stream_queue(); - let should_use_voice_processing_unit = self.has_input() && self.has_output(); - - let should_use_aggregate_device = { - // It's impossible to create an aggregate device from an aggregate device, and it's - // unnecessary to create an aggregate device when opening the same device input/output. In - // all other cases, use an aggregate device. - let mut either_already_aggregate = false; - if self.has_input() { - let input_is_aggregate = - get_device_transport_type(self.input_device.id, DeviceType::INPUT).unwrap_or(0) - == kAudioDeviceTransportTypeAggregate; - if input_is_aggregate { - either_already_aggregate = true; - } - cubeb_log!( - "Input device ID: {} (aggregate: {:?})", - self.input_device.id, - input_is_aggregate - ); - } - if self.has_output() { - let output_is_aggregate = - get_device_transport_type(self.output_device.id, DeviceType::OUTPUT) - .unwrap_or(0) - == kAudioDeviceTransportTypeAggregate; - if output_is_aggregate { - either_already_aggregate = true; - } - cubeb_log!( - "Output device ID: {} (aggregate: {:?})", - self.input_device.id, - output_is_aggregate - ); - } - // Only use an aggregate device when the device are different. - self.has_input() - && self.has_output() - && self.input_device.id != self.output_device.id - && !either_already_aggregate - }; - - // Create an AudioUnit: - // - If we're eligible to use voice processing, try creating a VoiceProcessingIO AudioUnit. - // - If we should use an aggregate device, try creating one and input and output AudioUnits next. - // - As last resort, create regular AudioUnits. This is also the normal non-duplex path. - - if should_use_voice_processing_unit { - if let Ok(au) = - create_voiceprocessing_audiounit(&self.input_device, &self.output_device) - { - cubeb_log!("({:p}) Using VoiceProcessingIO AudioUnit", self.stm_ptr); - self.input_unit = au; - self.output_unit = au; - return Ok((self.input_device.clone(), self.output_device.clone())); - } - cubeb_log!( - "({:p}) Failed to create VoiceProcessingIO AudioUnit. Trying a regular one.", - self.stm_ptr - ); - } - - if should_use_aggregate_device { - if let Ok(device) = AggregateDevice::new(self.input_device.id, self.output_device.id) { - let in_dev_info = { - device_info { - id: device.get_device_id(), - ..self.input_device - } - }; - let out_dev_info = { - device_info { - id: device.get_device_id(), - ..self.output_device - } - }; - - match ( - create_audiounit(&in_dev_info), - create_audiounit(&out_dev_info), - ) { - (Ok(in_au), Ok(out_au)) => { - cubeb_log!( - "({:p}) Using an aggregate device {} for input and output.", - self.stm_ptr, - device.get_device_id() - ); - self.aggregate_device = Some(device); - self.input_unit = in_au; - self.output_unit = out_au; - return Ok((in_dev_info, out_dev_info)); - } - (Err(e), Ok(au)) => { - cubeb_log!( - "({:p}) Failed to create input AudioUnit for aggregate device. Error: {}.", - self.stm_ptr, - e - ); - dispose_audio_unit(au); - } - (Ok(au), Err(e)) => { - cubeb_log!( - "({:p}) Failed to create output AudioUnit for aggregate device. Error: {}.", - self.stm_ptr, - e - ); - dispose_audio_unit(au); - } - (Err(e), _) => { - cubeb_log!( - "({:p}) Failed to create AudioUnits for aggregate device. Error: {}.", - self.stm_ptr, - e - ); - } - } - } - cubeb_log!( - "({:p}) Failed to set up aggregate device. Using regular AudioUnits.", - self.stm_ptr - ); - } - - if self.has_input() { - match create_audiounit(&self.input_device) { - Ok(in_au) => self.input_unit = in_au, - Err(e) => { - cubeb_log!( - "({:p}) Failed to create regular AudioUnit for input. Error: {}", - self.stm_ptr, - e - ); - return Err(e); - } - } - } - - if self.has_output() { - match create_audiounit(&self.output_device) { - Ok(out_au) => self.output_unit = out_au, - Err(e) => { - cubeb_log!( - "({:p}) Failed to create regular AudioUnit for output. Error: {}", - self.stm_ptr, - e - ); - if !self.input_unit.is_null() { - dispose_audio_unit(self.input_unit); - self.input_unit = ptr::null_mut(); - } - return Err(e); - } - } - } - - Ok((self.input_device.clone(), self.output_device.clone())) - } - #[allow(clippy::cognitive_complexity)] // TODO: Refactoring. fn setup(&mut self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); + fn get_device_channel_count(id: AudioDeviceID, devtype: DeviceType) -> Option { + get_channel_count(id, devtype) + .or_else(|e| { + cubeb_log!("Fail to get channel count for device {}. Error: {}", id, e); + get_device_stream_format(id, devtype).map(|f| f.mChannelsPerFrame) + }) + .map_err(|e| { + cubeb_log!( + "Fail to get channel info from stream format for device {}. Error: {}", + id, + e + ); + }) + .ok() + } + if self .input_stream_params .prefs() @@ -2772,17 +2512,42 @@ impl<'ctx> CoreStreamData<'ctx> { return Err(Error::not_supported()); } + let mut in_dev_info = self.input_device.clone(); + let mut out_dev_info = self.output_device.clone(); let same_clock_domain = self.same_clock_domain(); - let (in_dev_info, out_dev_info) = self.create_audiounits()?; - let using_voice_processing_unit = self.using_voice_processing_unit(); + + if self.should_use_aggregate_device() { + match AggregateDevice::new(in_dev_info.id, out_dev_info.id) { + Ok(device) => { + in_dev_info.id = device.get_device_id(); + out_dev_info.id = device.get_device_id(); + in_dev_info.flags = device_flags::DEV_INPUT; + out_dev_info.flags = device_flags::DEV_OUTPUT; + self.aggregate_device = Some(device); + cubeb_log!( + "({:p}) Using an aggregate device {} for input and output.", + self.stm_ptr, + self.aggregate_device.as_ref().unwrap().get_device_id() + ); + } + Err(e) => { + cubeb_log!( + "({:p}) Creation of aggregate devices failed. Error: {}.\ + Using assigned devices directly instead.", + self.stm_ptr, + e + ); + } + } + } else { + cubeb_log!("Not using an aggregate device"); + } assert!(!self.stm_ptr.is_null()); let stream = unsafe { &(*self.stm_ptr) }; // Configure I/O stream if self.has_input() { - assert!(!self.input_unit.is_null()); - cubeb_log!( "({:p}) Initializing input by device info: {:?}", self.stm_ptr, @@ -2790,27 +2555,25 @@ impl<'ctx> CoreStreamData<'ctx> { ); let device_channel_count = - get_channel_count(self.input_device.id, DeviceType::INPUT).unwrap_or(0); + get_device_channel_count(self.input_device.id, DeviceType::INPUT).unwrap_or(0); if device_channel_count < self.input_stream_params.channels() { - cubeb_log!( - "({:p}) Invalid input channel count; device={}, params={}", - self.stm_ptr, - device_channel_count, - self.input_stream_params.channels() - ); return Err(Error::invalid_parameter()); } + self.input_unit = create_audiounit(&in_dev_info).map_err(|e| { + cubeb_log!("({:p}) AudioUnit creation for input failed.", self.stm_ptr); + e + })?; + cubeb_log!( - "({:p}) Opening input side: rate {}, channels {}, format {:?}, layout {:?}, prefs {:?}, latency in frames {}, voice processing {}.", + "({:p}) Opening input side: rate {}, channels {}, format {:?}, layout {:?}, prefs {:?}, latency in frames {}.", self.stm_ptr, self.input_stream_params.rate(), self.input_stream_params.channels(), self.input_stream_params.format(), self.input_stream_params.layout(), self.input_stream_params.prefs(), - stream.latency_frames, - using_voice_processing_unit + stream.latency_frames ); // Get input device hardware information. @@ -2836,9 +2599,7 @@ impl<'ctx> CoreStreamData<'ctx> { self.stm_ptr, input_hw_desc ); - // In some cases with VPIO the stream format's mChannelsPerFrame is higher than - // expected. Use get_channel_count as source of truth. - input_hw_desc.mChannelsPerFrame = device_channel_count; + assert!(input_hw_desc.mChannelsPerFrame >= device_channel_count); // Notice: when we are using aggregate device, the input_hw_desc.mChannelsPerFrame is // the total of all the input channel count of the devices added in the aggregate device. // Due to our aggregate device settings, the data captured by the output device's input @@ -2848,13 +2609,7 @@ impl<'ctx> CoreStreamData<'ctx> { // channels to the audio callback. let params = unsafe { let mut p = *self.input_stream_params.as_ptr(); - p.channels = if using_voice_processing_unit { - // With VPIO, stereo input devices configured for stereo have been observed to - // spit out only a single mono channel. - 1 - } else { - input_hw_desc.mChannelsPerFrame - }; + p.channels = input_hw_desc.mChannelsPerFrame; // Input AudioUnit must be configured with device's sample rate. // we will resample inside input callback. p.rate = input_hw_desc.mSampleRate as _; @@ -2923,9 +2678,7 @@ impl<'ctx> CoreStreamData<'ctx> { self.input_stream_params.format(), SAFE_MAX_LATENCY_FRAMES as usize, self.input_dev_desc.mChannelsPerFrame as usize, - self.input_dev_desc - .mChannelsPerFrame - .saturating_sub(device_channel_count) as usize, + (self.input_dev_desc.mChannelsPerFrame - device_channel_count) as usize, self.input_stream_params.channels() as usize, )); @@ -2960,27 +2713,26 @@ impl<'ctx> CoreStreamData<'ctx> { } if self.has_output() { - assert!(!self.output_unit.is_null()); - cubeb_log!( "({:p}) Initialize output by device info: {:?}", self.stm_ptr, out_dev_info ); - let device_channel_count = - get_channel_count(self.output_device.id, DeviceType::OUTPUT).unwrap_or(0); + self.output_unit = create_audiounit(&out_dev_info).map_err(|e| { + cubeb_log!("({:p}) AudioUnit creation for output failed.", self.stm_ptr); + e + })?; cubeb_log!( - "({:p}) Opening output side: rate {}, channels {}, format {:?}, layout {:?}, prefs {:?}, latency in frames {}, voice processing {}.", + "({:p}) Opening output side: rate {}, channels {}, format {:?}, layout {:?}, prefs {:?}, latency in frames {}.", self.stm_ptr, self.output_stream_params.rate(), self.output_stream_params.channels(), self.output_stream_params.format(), self.output_stream_params.layout(), self.output_stream_params.prefs(), - stream.latency_frames, - using_voice_processing_unit + stream.latency_frames ); // Get output device hardware information. @@ -3007,10 +2759,6 @@ impl<'ctx> CoreStreamData<'ctx> { output_hw_desc ); - // In some cases with VPIO the stream format's mChannelsPerFrame is higher than - // expected. Use get_channel_count as source of truth. - output_hw_desc.mChannelsPerFrame = device_channel_count; - // This has been observed in the wild. if output_hw_desc.mChannelsPerFrame == 0 { cubeb_log!( @@ -3027,11 +2775,6 @@ impl<'ctx> CoreStreamData<'ctx> { let params = unsafe { let mut p = *self.output_stream_params.as_ptr(); p.channels = output_hw_desc.mChannelsPerFrame; - if using_voice_processing_unit { - // VPIO will always use the sample rate of the input hw for both input and output, - // as reported to us. (We can override it but we cannot improve quality this way). - p.rate = output_hw_desc.mSampleRate as _; - } StreamParams::from(p) }; @@ -3043,22 +2786,7 @@ impl<'ctx> CoreStreamData<'ctx> { e })?; - let device_layout = self - .get_output_channel_layout() - .map_err(|e| { - cubeb_log!( - "({:p}) Could not get any channel layout. Defaulting to no channels.", - self.stm_ptr - ); - e - }) - .unwrap_or_default(); - - cubeb_log!( - "({:p} Using output device channel layout {:?}", - self.stm_ptr, - device_layout - ); + let device_layout = audiounit_get_current_channel_layout(self.output_unit); // The mixer will be set up when // 1. using aggregate device whose input device has output channels @@ -3171,19 +2899,14 @@ impl<'ctx> CoreStreamData<'ctx> { None }; let resampler_output_params = if self.has_output() { - let mut p = unsafe { *(self.output_stream_params.as_ptr()) }; - p.rate = self.output_dev_desc.mSampleRate as u32; - Some(p) + Some(unsafe { *(self.output_stream_params.as_ptr()) }) } else { None }; // Only reclock if there is an input and we couldn't use an aggregate device, and the // devices are not part of the same clock domain. - let reclock_policy = if self.aggregate_device.is_none() - && !using_voice_processing_unit - && !same_clock_domain - { + let reclock_policy = if self.aggregate_device.is_none() && !same_clock_domain { cubeb_log!( "Reclocking duplex steam using_aggregate_device={} same_clock_domain={}", self.aggregate_device.is_some(), @@ -3226,12 +2949,10 @@ impl<'ctx> CoreStreamData<'ctx> { } if !self.output_unit.is_null() { - if self.input_unit != self.output_unit { - let r = audio_unit_initialize(self.output_unit); - if r != NO_ERR { - cubeb_log!("AudioUnitInitialize/output rv={}", r); - return Err(Error::error()); - } + let r = audio_unit_initialize(self.output_unit); + if r != NO_ERR { + cubeb_log!("AudioUnitInitialize/output rv={}", r); + return Err(Error::error()); } stream.output_device_latency_frames.store( @@ -3282,30 +3003,14 @@ impl<'ctx> CoreStreamData<'ctx> { || self.input_alive_listener.is_some())) ); - // We have either default_output_listener or output_alive_listener. - // We cannot have both of them at the same time. - assert!( - !self.has_output() - || ((self.default_output_listener.is_some() - != self.output_alive_listener.is_some()) - && (self.default_output_listener.is_some() - || self.output_alive_listener.is_some())) - ); - Ok(()) } fn close(&mut self) { - self.debug_assert_is_on_stream_queue(); if !self.input_unit.is_null() { audio_unit_uninitialize(self.input_unit); - if self.using_voice_processing_unit() { - // Handle the VoiceProcessIO case where there is a single unit. - self.output_unit = ptr::null_mut(); - } - - // Cannot unset self.input_unit yet, since the output callback might be live - // and reading it. + dispose_audio_unit(self.input_unit); + self.input_unit = ptr::null_mut(); } if !self.output_unit.is_null() { @@ -3314,11 +3019,6 @@ impl<'ctx> CoreStreamData<'ctx> { self.output_unit = ptr::null_mut(); } - if !self.input_unit.is_null() { - dispose_audio_unit(self.input_unit); - self.input_unit = ptr::null_mut(); - } - self.resampler.destroy(); self.mixer = None; self.aggregate_device = None; @@ -3339,7 +3039,6 @@ impl<'ctx> CoreStreamData<'ctx> { } fn install_device_changed_callback(&mut self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); assert!(!self.stm_ptr.is_null()); let stm = unsafe { &(*self.stm_ptr) }; @@ -3350,10 +3049,6 @@ impl<'ctx> CoreStreamData<'ctx> { self.output_source_listener.is_none(), "register output_source_listener without unregistering the one in use" ); - assert!( - self.output_alive_listener.is_none(), - "register output_alive_listener without unregistering the one in use" - ); // Get the notification when the data source on the same device changes, // e.g., when the user plugs in a TRRS headset into the headphone jack. @@ -3368,29 +3063,6 @@ impl<'ctx> CoreStreamData<'ctx> { cubeb_log!("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDataSource rv={}, device id={}", rv, self.output_device.id); return Err(Error::error()); } - - // Get the notification when the output device is going away - // if the output doesn't follow the system default. - if !self - .output_device - .flags - .contains(device_flags::DEV_SELECTED_DEFAULT) - { - self.output_alive_listener = Some(device_property_listener::new( - self.output_device.id, - get_property_address( - Property::DeviceIsAlive, - DeviceType::INPUT | DeviceType::OUTPUT, - ), - audiounit_property_listener_callback, - )); - let rv = stm.add_device_listener(self.output_alive_listener.as_ref().unwrap()); - if rv != NO_ERR { - self.output_alive_listener = None; - cubeb_log!("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDeviceIsAlive rv={}, device id ={}", rv, self.output_device.id); - return Err(Error::error()); - } - } } if !self.input_unit.is_null() { @@ -3447,16 +3119,10 @@ impl<'ctx> CoreStreamData<'ctx> { } fn install_system_changed_callback(&mut self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); assert!(!self.stm_ptr.is_null()); let stm = unsafe { &(*self.stm_ptr) }; - if !self.output_unit.is_null() - && self - .output_device - .flags - .contains(device_flags::DEV_SELECTED_DEFAULT) - { + if !self.output_unit.is_null() { assert!( self.default_output_listener.is_none(), "register default_output_listener without unregistering the one in use" @@ -3515,11 +3181,9 @@ impl<'ctx> CoreStreamData<'ctx> { } fn uninstall_device_changed_callback(&mut self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); if self.stm_ptr.is_null() { assert!( self.output_source_listener.is_none() - && self.output_alive_listener.is_none() && self.input_source_listener.is_none() && self.input_alive_listener.is_none() ); @@ -3540,15 +3204,6 @@ impl<'ctx> CoreStreamData<'ctx> { self.output_source_listener = None; } - if self.output_alive_listener.is_some() { - let rv = stm.remove_device_listener(self.output_alive_listener.as_ref().unwrap()); - if rv != NO_ERR { - cubeb_log!("AudioObjectRemovePropertyListener/output/kAudioDevicePropertyDeviceIsAlive rv={}, device id={}", rv, self.output_device.id); - r = Err(Error::error()); - } - self.output_alive_listener = None; - } - if self.input_source_listener.is_some() { let rv = stm.remove_device_listener(self.input_source_listener.as_ref().unwrap()); if rv != NO_ERR { @@ -3571,7 +3226,6 @@ impl<'ctx> CoreStreamData<'ctx> { } fn uninstall_system_changed_callback(&mut self) -> Result<()> { - self.debug_assert_is_on_stream_queue(); if self.stm_ptr.is_null() { assert!( self.default_output_listener.is_none() && self.default_input_listener.is_none() @@ -3599,33 +3253,10 @@ impl<'ctx> CoreStreamData<'ctx> { Ok(()) } - - fn get_output_channel_layout(&self) -> Result> { - self.debug_assert_is_on_stream_queue(); - assert!(!self.output_unit.is_null()); - if !self.using_voice_processing_unit() { - return get_channel_layout(self.output_unit); - } - - // The VoiceProcessingIO unit (as tried on MacOS 14) is known to not support - // kAudioUnitProperty_AudioChannelLayout queries, and to lie about - // kAudioDevicePropertyPreferredChannelLayout. If we're using - // VoiceProcessingIO, try standing up a regular AudioUnit and query that. - cubeb_log!( - "({:p}) get_output_channel_layout with a VoiceProcessingIO output unit. Trying a dedicated unit.", - self.stm_ptr - ); - let mut dedicated_unit = create_audiounit(&self.output_device)?; - let res = get_channel_layout(dedicated_unit); - dispose_audio_unit(dedicated_unit); - dedicated_unit = ptr::null_mut(); - res - } } impl<'ctx> Drop for CoreStreamData<'ctx> { fn drop(&mut self) { - self.debug_assert_is_on_stream_queue(); self.stop_audiounits(); self.close(); } @@ -3725,7 +3356,6 @@ impl<'ctx> AudioUnitStream<'ctx> { } fn add_device_listener(&self, listener: &device_property_listener) -> OSStatus { - self.queue.debug_assert_is_current(); audio_object_add_property_listener( listener.device, &listener.property, @@ -3735,7 +3365,6 @@ impl<'ctx> AudioUnitStream<'ctx> { } fn remove_device_listener(&self, listener: &device_property_listener) -> OSStatus { - self.queue.debug_assert_is_current(); audio_object_remove_property_listener( listener.device, &listener.property, @@ -3759,7 +3388,6 @@ impl<'ctx> AudioUnitStream<'ctx> { } fn reinit(&mut self) -> Result<()> { - self.queue.debug_assert_is_current(); // Call stop_audiounits to avoid potential data race. If there is a running data callback, // which locks a mutex inside CoreAudio framework, then this call will block the current // thread until the callback is finished since this call asks to lock a mutex inside @@ -3876,25 +3504,28 @@ impl<'ctx> AudioUnitStream<'ctx> { } fn close_on_error(&mut self) { - self.queue.debug_assert_is_current(); - let stm_ptr = self as *const AudioUnitStream; + let queue = self.queue.clone(); - self.core_stream_data.close(); - self.notify_state_changed(State::Error); - cubeb_log!("({:p}) Close the stream due to an error.", stm_ptr); + // Use a different thread, through the queue, to avoid deadlock when calling + // Get/SetProperties method from inside notify callback + queue.run_async(move || { + let stm_ptr = self as *const AudioUnitStream; - self.switching_device.store(false, Ordering::SeqCst); + self.core_stream_data.close(); + self.notify_state_changed(State::Error); + cubeb_log!("({:p}) Close the stream due to an error.", stm_ptr); + + self.switching_device.store(false, Ordering::SeqCst); + }); } fn destroy_internal(&mut self) { - self.queue.debug_assert_is_current(); self.core_stream_data.close(); assert!(self.context.active_streams() >= 1); self.context.update_latency_by_removing_stream(); } fn destroy(&mut self) { - self.queue.debug_assert_is_current(); if self .core_stream_data .uninstall_system_changed_callback() @@ -3920,31 +3551,31 @@ impl<'ctx> AudioUnitStream<'ctx> { // Execute the stream destroy work. self.destroy_pending.store(true, Ordering::SeqCst); - // Call stop_audiounits to avoid potential data race. If there is a running data callback, - // which locks a mutex inside CoreAudio framework, then this call will block the current - // thread until the callback is finished since this call asks to lock a mutex inside - // CoreAudio framework that is used by the data callback. - if !self.stopped.load(Ordering::SeqCst) { - self.core_stream_data.stop_audiounits(); - self.stopped.store(true, Ordering::SeqCst); - } + let queue = self.queue.clone(); - self.destroy_internal(); + let stream_ptr = self as *const AudioUnitStream; + // Execute close in serial queue to avoid collision + // with reinit when un/plug devices + queue.run_final(move || { + // Call stop_audiounits to avoid potential data race. If there is a running data callback, + // which locks a mutex inside CoreAudio framework, then this call will block the current + // thread until the callback is finished since this call asks to lock a mutex inside + // CoreAudio framework that is used by the data callback. + if !self.stopped.load(Ordering::SeqCst) { + self.core_stream_data.stop_audiounits(); + self.stopped.store(true, Ordering::SeqCst); + } - cubeb_log!( - "Cubeb stream ({:p}) destroyed successful.", - self as *const AudioUnitStream - ); + self.destroy_internal(); + }); + + cubeb_log!("Cubeb stream ({:p}) destroyed successful.", stream_ptr); } } impl<'ctx> Drop for AudioUnitStream<'ctx> { fn drop(&mut self) { - // Execute destroy in serial queue to avoid collision with reinit when un/plug devices - self.queue.clone().run_final(move || { - self.destroy(); - self.core_stream_data = CoreStreamData::default(); - }); + self.destroy(); } } diff --git a/third_party/rust/cubeb-coreaudio/src/backend/resampler.rs b/third_party/rust/cubeb-coreaudio/src/backend/resampler.rs index b72fc6310b25..fb5b0e9e1e48 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/resampler.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/resampler.rs @@ -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, diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/aggregate_device.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/aggregate_device.rs index 1d3c341ae8f4..49726f2613da 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/aggregate_device.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/aggregate_device.rs @@ -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)); diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs index 35e4985d0733..5c507bf6f3e0 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/api.rs @@ -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() { diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/device_change.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/device_change.rs index ec353a692203..a0897a81e847 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/device_change.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/device_change.rs @@ -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; + 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; 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; + 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) }; + let count = unsafe { &*(data as *const Mutex) }; { - 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) }; + let count = unsafe { &*(data as *const Mutex) }; { - let mut counts = notifier.lock().unwrap(); - counts.output += 1; - notifier.notify(counts); + let mut guard = count.lock().unwrap(); + *guard += 1; } } + + fn check_result( + in_scope: bool, + expected: (T, T), + watcher: &Watcher, + ) { + 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; + 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; 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) }; - let mut count_guard = notifier.lock().unwrap(); - *count_guard += 1; - notifier.notify(count_guard); + let count = unsafe { &*(data as *const Mutex) }; + { + 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, + struct SharedData { + changed_count: Arc>, + states: Arc>>, } - 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; + 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(¬ifier); - 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) }; - 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) }; - let mut data_guard = notifier.lock().unwrap(); - data_guard.changed_count += 1; - notifier.notify(data_guard); - } -} - -struct Notifier { - value: Mutex, - cvar: Condvar, -} - -impl Notifier { - 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> { - 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 { - notifier: Arc>, + watching: Arc>, + current: Option, } impl Watcher { - fn new(value: &Arc>) -> Self { + fn new(value: &Arc>) -> Self { Self { - notifier: Arc::clone(value), + watching: Arc::clone(value), + current: None, } } - fn lock(&self) -> LockResult> { - 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> - 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() } } diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/device_property.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/device_property.rs index 8277a7642d5f..d8d3ef0c9aee 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/device_property.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/device_property.rs @@ -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::>>(); - 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::>>(); - 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 { - #[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()); } diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/interfaces.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/interfaces.rs index d92f322ba2c7..1b7c2cf3854e 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/interfaces.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/interfaces.rs @@ -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 = vec![1, 2, 3, 4, 6]; - let freq_values: Vec = vec![16000, 24000, 44100, 48000]; - let is_float_values: Vec = 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(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, diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/parallel.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/parallel.rs index aa34276eda50..e971737cca84 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/parallel.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/parallel.rs @@ -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( 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( None }, latency_frames, - Some(noop_data_callback), + None, // No data callback. None, // No state callback. ptr::null_mut(), // No user data pointer. ) diff --git a/third_party/rust/cubeb-coreaudio/src/backend/tests/utils.rs b/third_party/rust/cubeb-coreaudio/src/backend/tests/utils.rs index 6ea1ebff9372..1c2c0683afb5 100644 --- a/third_party/rust/cubeb-coreaudio/src/backend/tests/utils.rs +++ b/third_party/rust/cubeb-coreaudio/src/backend/tests/utils.rs @@ -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 { - 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 { @@ -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 { let mut devices = Vec::new(); @@ -303,12 +284,11 @@ pub fn test_get_all_devices(filter: DeviceFilter) -> Vec { } 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 { } pub fn test_get_devices_in_scope(scope: Scope) -> Vec { - 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 { 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 { @@ -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 { 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( 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( 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 + } } diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index 0c2780783e5c..078a2712b1ab 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -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 } diff --git a/tools/profiler/rust-api/Cargo.toml b/tools/profiler/rust-api/Cargo.toml index 7efc739c7814..7931b6eef5a6 100644 --- a/tools/profiler/rust-api/Cargo.toml +++ b/tools/profiler/rust-api/Cargo.toml @@ -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]