forked from mirrors/gecko-dev
Bug 1895787 - Update cubeb rust repos to support audio dumping and more. r=cubeb-reviewers,supply-chain-reviewers,padenot
The "more" is mainly some fixes in the coreaudio backend, including: - serializing more audio operations onto the serial queue - using the correct audio unit scope when querying for its stream format - tightening up some potential races around reinit on certain errors Differential Revision: https://phabricator.services.mozilla.com/D211042
This commit is contained in:
parent
5fdd6bd754
commit
e71ae3a83f
51 changed files with 1030 additions and 281 deletions
|
|
@ -65,19 +65,19 @@ git = "https://github.com/mozilla/application-services"
|
||||||
rev = "e0563d725f852f617878ecc13a03cdf50c85cd5a"
|
rev = "e0563d725f852f617878ecc13a03cdf50c85cd5a"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/mozilla/audioipc?rev=409e11f8de6288e9ddfe269654523735302e59e6"]
|
[source."git+https://github.com/mozilla/audioipc?rev=3495905752a4263827f5d43737f9ca3ed0243ce0"]
|
||||||
git = "https://github.com/mozilla/audioipc"
|
git = "https://github.com/mozilla/audioipc"
|
||||||
rev = "409e11f8de6288e9ddfe269654523735302e59e6"
|
rev = "3495905752a4263827f5d43737f9ca3ed0243ce0"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ca174cf83ebe32b3198478c2211d69678845bc7"]
|
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=0989726a1b9b640a30dfdf3ea005a12c73ab8155"]
|
||||||
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
||||||
rev = "4ca174cf83ebe32b3198478c2211d69678845bc7"
|
rev = "0989726a1b9b640a30dfdf3ea005a12c73ab8155"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8ff972c8e2ec1782ff262ac4071c0415e69b1367"]
|
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2"]
|
||||||
git = "https://github.com/mozilla/cubeb-pulse-rs"
|
git = "https://github.com/mozilla/cubeb-pulse-rs"
|
||||||
rev = "8ff972c8e2ec1782ff262ac4071c0415e69b1367"
|
rev = "8678dcab1c287de79c4c184ccc2e065bc62b70e2"
|
||||||
replace-with = "vendored-sources"
|
replace-with = "vendored-sources"
|
||||||
|
|
||||||
[source."git+https://github.com/mozilla/midir.git?rev=85156e360a37d851734118104619f86bd18e94c6"]
|
[source."git+https://github.com/mozilla/midir.git?rev=85156e360a37d851734118104619f86bd18e94c6"]
|
||||||
|
|
|
||||||
32
Cargo.lock
generated
32
Cargo.lock
generated
|
|
@ -260,7 +260,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "audioipc2"
|
name = "audioipc2"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/mozilla/audioipc?rev=409e11f8de6288e9ddfe269654523735302e59e6#409e11f8de6288e9ddfe269654523735302e59e6"
|
source = "git+https://github.com/mozilla/audioipc?rev=3495905752a4263827f5d43737f9ca3ed0243ce0#3495905752a4263827f5d43737f9ca3ed0243ce0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"ashmem",
|
"ashmem",
|
||||||
|
|
@ -288,7 +288,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "audioipc2-client"
|
name = "audioipc2-client"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/mozilla/audioipc?rev=409e11f8de6288e9ddfe269654523735302e59e6#409e11f8de6288e9ddfe269654523735302e59e6"
|
source = "git+https://github.com/mozilla/audioipc?rev=3495905752a4263827f5d43737f9ca3ed0243ce0#3495905752a4263827f5d43737f9ca3ed0243ce0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"audio_thread_priority",
|
"audio_thread_priority",
|
||||||
"audioipc2",
|
"audioipc2",
|
||||||
|
|
@ -299,7 +299,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "audioipc2-server"
|
name = "audioipc2-server"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/mozilla/audioipc?rev=409e11f8de6288e9ddfe269654523735302e59e6#409e11f8de6288e9ddfe269654523735302e59e6"
|
source = "git+https://github.com/mozilla/audioipc?rev=3495905752a4263827f5d43737f9ca3ed0243ce0#3495905752a4263827f5d43737f9ca3ed0243ce0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"audio_thread_priority",
|
"audio_thread_priority",
|
||||||
"audioipc2",
|
"audioipc2",
|
||||||
|
|
@ -941,7 +941,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "coreaudio-sys-utils"
|
name = "coreaudio-sys-utils"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ca174cf83ebe32b3198478c2211d69678845bc7#4ca174cf83ebe32b3198478c2211d69678845bc7"
|
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=0989726a1b9b640a30dfdf3ea005a12c73ab8155#0989726a1b9b640a30dfdf3ea005a12c73ab8155"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"coreaudio-sys",
|
"coreaudio-sys",
|
||||||
|
|
@ -1160,27 +1160,27 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb"
|
name = "cubeb"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6db57570f2617f0214c11721e8d2325816d9dc936c2c472661ac5d90a30fba98"
|
checksum = "3d105547cf8036cdb30e796ce0d06832af4766106a44574402fa2fd3c861a042"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cubeb-core",
|
"cubeb-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-backend"
|
name = "cubeb-backend"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b00b0f3b84e315571bd8c4e18794180633066267a413f2f05bca65001adc8410"
|
checksum = "67361fe9b49b4599e2a230ce322529b6ddd91df14897c872dcede716f8fbca81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cubeb-core",
|
"cubeb-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-core"
|
name = "cubeb-core"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2380c03a7df0ea3744f6a210d6340f423935e53cbf2fd68ada84b5e808e46ac7"
|
checksum = "ac08d314dd1ec6d41d9ccdeec70899c98ed3b89845367000dd6096099481bc73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.999.999",
|
"bitflags 1.999.999",
|
||||||
"cubeb-sys",
|
"cubeb-sys",
|
||||||
|
|
@ -1189,7 +1189,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-coreaudio"
|
name = "cubeb-coreaudio"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=4ca174cf83ebe32b3198478c2211d69678845bc7#4ca174cf83ebe32b3198478c2211d69678845bc7"
|
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=0989726a1b9b640a30dfdf3ea005a12c73ab8155#0989726a1b9b640a30dfdf3ea005a12c73ab8155"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic",
|
"atomic",
|
||||||
"audio-mixer",
|
"audio-mixer",
|
||||||
|
|
@ -1208,7 +1208,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-pulse"
|
name = "cubeb-pulse"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8ff972c8e2ec1782ff262ac4071c0415e69b1367#8ff972c8e2ec1782ff262ac4071c0415e69b1367"
|
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2#8678dcab1c287de79c4c184ccc2e065bc62b70e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cubeb-backend",
|
"cubeb-backend",
|
||||||
"pulse",
|
"pulse",
|
||||||
|
|
@ -1219,9 +1219,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-sys"
|
name = "cubeb-sys"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c20c457d7b34dad6e0c1a9c759c96b4420b9e9917a572998b81835799a07e1d"
|
checksum = "26073cd50c7b6ba4272204839f56921557609a0d67e092882cbb903df94cab39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cmake",
|
"cmake",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
|
@ -4649,7 +4649,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulse"
|
name = "pulse"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8ff972c8e2ec1782ff262ac4071c0415e69b1367#8ff972c8e2ec1782ff262ac4071c0415e69b1367"
|
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2#8678dcab1c287de79c4c184ccc2e065bc62b70e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"pulse-ffi",
|
"pulse-ffi",
|
||||||
|
|
@ -4658,7 +4658,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulse-ffi"
|
name = "pulse-ffi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8ff972c8e2ec1782ff262ac4071c0415e69b1367#8ff972c8e2ec1782ff262ac4071c0415e69b1367"
|
source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2#8678dcab1c287de79c4c184ccc2e065bc62b70e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1288,6 +1288,11 @@ who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.10.3 -> 0.12.0"
|
delta = "0.10.3 -> 0.12.0"
|
||||||
|
|
||||||
|
[[audits.cubeb]]
|
||||||
|
who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.12.0 -> 0.13.0"
|
||||||
|
|
||||||
[[audits.cubeb-backend]]
|
[[audits.cubeb-backend]]
|
||||||
who = "Matthew Gregan <kinetik@flim.org>"
|
who = "Matthew Gregan <kinetik@flim.org>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -1319,6 +1324,11 @@ who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.10.7 -> 0.12.0"
|
delta = "0.10.7 -> 0.12.0"
|
||||||
|
|
||||||
|
[[audits.cubeb-backend]]
|
||||||
|
who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.12.0 -> 0.13.0"
|
||||||
|
|
||||||
[[audits.cubeb-core]]
|
[[audits.cubeb-core]]
|
||||||
who = "Matthew Gregan <kinetik@flim.org>"
|
who = "Matthew Gregan <kinetik@flim.org>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -1355,6 +1365,11 @@ who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.10.7 -> 0.12.0"
|
delta = "0.10.7 -> 0.12.0"
|
||||||
|
|
||||||
|
[[audits.cubeb-core]]
|
||||||
|
who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.12.0 -> 0.13.0"
|
||||||
|
|
||||||
[[audits.cubeb-sys]]
|
[[audits.cubeb-sys]]
|
||||||
who = "Matthew Gregan <kinetik@flim.org>"
|
who = "Matthew Gregan <kinetik@flim.org>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
@ -1386,6 +1401,11 @@ who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
delta = "0.10.7 -> 0.12.0"
|
delta = "0.10.7 -> 0.12.0"
|
||||||
|
|
||||||
|
[[audits.cubeb-sys]]
|
||||||
|
who = "Andreas Pehrson <apehrson@mozilla.com>"
|
||||||
|
criteria = "safe-to-deploy"
|
||||||
|
delta = "0.12.0 -> 0.13.0"
|
||||||
|
|
||||||
[[audits.d3d12]]
|
[[audits.d3d12]]
|
||||||
who = "Jim Blandy <jimb@red-bean.com>"
|
who = "Jim Blandy <jimb@red-bean.com>"
|
||||||
criteria = "safe-to-deploy"
|
criteria = "safe-to-deploy"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"e94c46bbd290f02adccc7ae932285416d7e021bfde80abb2fb31a2c05426e732","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/context.rs":"a0559e92b554ef3156ab2bf2f1424555c8ef4a7977b9f43ac8500a9f399f8d99","src/lib.rs":"c87d9d57a16a9286cde730978db692df0fbc70cc69dd4f4677198d6843031fd8","src/send_recv.rs":"859abe75b521eb4297c84b30423814b5b87f3c7741ad16fe72189212e123e1ac","src/stream.rs":"90dc6a85552f3569ab1847de4247a46bcff2f5aef0c4d43fa2376589df015b25"},"package":null}
|
{"files":{"Cargo.toml":"b4fad65749eb0988ce4e6b6a2aae51e58ae22eca97cf61dfb011e951a0909f0e","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/context.rs":"a0559e92b554ef3156ab2bf2f1424555c8ef4a7977b9f43ac8500a9f399f8d99","src/lib.rs":"c87d9d57a16a9286cde730978db692df0fbc70cc69dd4f4677198d6843031fd8","src/send_recv.rs":"859abe75b521eb4297c84b30423814b5b87f3c7741ad16fe72189212e123e1ac","src/stream.rs":"90dc6a85552f3569ab1847de4247a46bcff2f5aef0c4d43fa2376589df015b25"},"package":null}
|
||||||
2
third_party/rust/audioipc2-client/Cargo.toml
vendored
2
third_party/rust/audioipc2-client/Cargo.toml
vendored
|
|
@ -21,7 +21,7 @@ description = "Cubeb Backend for talking to remote cubeb server."
|
||||||
license = "ISC"
|
license = "ISC"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cubeb-backend = "0.12"
|
cubeb-backend = "0.13"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
[dependencies.audio_thread_priority]
|
[dependencies.audio_thread_priority]
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"77997660e305851d9c0e656aac7159b999452a36f3436d8b2f402edd36fef853","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/lib.rs":"d70079c66de72c3469504f1f0c9cf5e510644cac17f2d8300b8d12218740e07b","src/server.rs":"187e2236aa9f2fb6cc4a533d40714a71504afa5ef9d849ac28b7f26032859c29"},"package":null}
|
{"files":{"Cargo.toml":"62eab883f31c0c088ff865fe2e4305d987b7b534f6cdfe1e5812072a2ec13f8b","cbindgen.toml":"fb6abe1671497f432a06e40b1db7ed7cd2cceecbd9a2382193ad7534e8855e34","src/lib.rs":"d70079c66de72c3469504f1f0c9cf5e510644cac17f2d8300b8d12218740e07b","src/server.rs":"187e2236aa9f2fb6cc4a533d40714a71504afa5ef9d849ac28b7f26032859c29"},"package":null}
|
||||||
2
third_party/rust/audioipc2-server/Cargo.toml
vendored
2
third_party/rust/audioipc2-server/Cargo.toml
vendored
|
|
@ -21,7 +21,7 @@ description = "Remote cubeb server"
|
||||||
license = "ISC"
|
license = "ISC"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cubeb-core = "0.12.0"
|
cubeb-core = "0.13"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
once_cell = "1.2.0"
|
once_cell = "1.2.0"
|
||||||
slab = "0.4"
|
slab = "0.4"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"dff67ba050be15275d357b7f001df6caa6ae1f93b2acd61ac7d6ee269a1f5960","benches/serialization.rs":"d56855d868dab6aa22c8b03a61084535351b76c94b68d8b1d20764e352fe473f","build.rs":"65df9a97c6cdaa3faf72581f04ac289197b0b1797d69d22c1796e957ff1089e2","src/codec.rs":"86068272e220696d8d7e369072326349e7598e5a24223d98179c3251bb7b3ff1","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/ipccore.rs":"db73e916468c54d3497d75ffcab3bf23067771ed7b2e1a23c714429f56f59ec3","src/lib.rs":"a6fcac8b44318435db60313d3ef32ff3fada390bea8978c8414c40744998b98b","src/messages.rs":"d4f6d4f41b7fd3cc7deae726657e1100f315f4cd10c5fe6ce8a57c03c8e26ca9","src/rpccore.rs":"025b6614f1c42b96b0a8e74fd7881032d338c66e0d67ec0af70f910a9e30ebe1","src/shm.rs":"c00d16f4af510d12e704ae865f7348ad64ddef180e42b18e7dd95c4be35a9c80","src/sys/mod.rs":"e6fa1d260abf093e1f7b50185195e2d3aee0eb8c9774c6f253953b5896d838f3","src/sys/unix/cmsg.rs":"9529e8f8429db86f7c5df132953d3054e603852270f3c6938cdb5f630b2711f1","src/sys/unix/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/sys/unix/mod.rs":"59835f0d5509940078b1820a54f49fc5514adeb3e45e7d21e3ab917431da2e74","src/sys/unix/msg.rs":"0e297d73bae9414184f85c2209cca0a3fde6d999a3f1d3f42faa3f56b6d57233","src/sys/windows/mod.rs":"7eaabb76e62c6962b636320e2bbf79a78fce61659c799a798f7dd6d56b0be8a1"},"package":null}
|
{"files":{"Cargo.toml":"5dc7153bf7291eea52bdc5561440c1c646272f8c913e8782bc2c84b7ed2f8b76","benches/serialization.rs":"d56855d868dab6aa22c8b03a61084535351b76c94b68d8b1d20764e352fe473f","build.rs":"65df9a97c6cdaa3faf72581f04ac289197b0b1797d69d22c1796e957ff1089e2","src/codec.rs":"86068272e220696d8d7e369072326349e7598e5a24223d98179c3251bb7b3ff1","src/errors.rs":"67a4a994d0724397657581cde153bdfc05ce86e7efc467f23fafc8f64df80fa4","src/ipccore.rs":"db73e916468c54d3497d75ffcab3bf23067771ed7b2e1a23c714429f56f59ec3","src/lib.rs":"a6fcac8b44318435db60313d3ef32ff3fada390bea8978c8414c40744998b98b","src/messages.rs":"d4f6d4f41b7fd3cc7deae726657e1100f315f4cd10c5fe6ce8a57c03c8e26ca9","src/rpccore.rs":"025b6614f1c42b96b0a8e74fd7881032d338c66e0d67ec0af70f910a9e30ebe1","src/shm.rs":"c00d16f4af510d12e704ae865f7348ad64ddef180e42b18e7dd95c4be35a9c80","src/sys/mod.rs":"e6fa1d260abf093e1f7b50185195e2d3aee0eb8c9774c6f253953b5896d838f3","src/sys/unix/cmsg.rs":"9529e8f8429db86f7c5df132953d3054e603852270f3c6938cdb5f630b2711f1","src/sys/unix/cmsghdr.c":"d7344b3dc15cdce410c68669b848bb81f7fe36362cd3699668cb613fa05180f8","src/sys/unix/mod.rs":"59835f0d5509940078b1820a54f49fc5514adeb3e45e7d21e3ab917431da2e74","src/sys/unix/msg.rs":"25244de3eba920fa42e032f8fa4ea4913a9fdeb5124ade61e707f6cc6dd946b0","src/sys/windows/mod.rs":"7eaabb76e62c6962b636320e2bbf79a78fce61659c799a798f7dd6d56b0be8a1"},"package":null}
|
||||||
2
third_party/rust/audioipc2/Cargo.toml
vendored
2
third_party/rust/audioipc2/Cargo.toml
vendored
|
|
@ -29,7 +29,7 @@ bincode = "1.3"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
crossbeam-queue = "0.3"
|
crossbeam-queue = "0.3"
|
||||||
cubeb = "0.12"
|
cubeb = "0.13"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
scopeguard = "1.1.0"
|
scopeguard = "1.1.0"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ pub(crate) fn recv_msg_with_flags(
|
||||||
flags: libc::c_int,
|
flags: libc::c_int,
|
||||||
) -> io::Result<(usize, usize, libc::c_int)> {
|
) -> io::Result<(usize, usize, libc::c_int)> {
|
||||||
let slice = unix::as_os_slice_mut(bufs);
|
let slice = unix::as_os_slice_mut(bufs);
|
||||||
let len = cmp::min(<libc::c_int>::max_value() as usize, slice.len());
|
let len = cmp::min(<libc::c_int>::MAX as usize, slice.len());
|
||||||
let (control, controllen) = if cmsg.len() == 0 {
|
let (control, controllen) = if cmsg.len() == 0 {
|
||||||
(ptr::null_mut(), 0)
|
(ptr::null_mut(), 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -63,7 +63,7 @@ pub(crate) fn send_msg_with_flags(
|
||||||
flags: libc::c_int,
|
flags: libc::c_int,
|
||||||
) -> io::Result<usize> {
|
) -> io::Result<usize> {
|
||||||
let slice = unix::as_os_slice(bufs);
|
let slice = unix::as_os_slice(bufs);
|
||||||
let len = cmp::min(<libc::c_int>::max_value() as usize, slice.len());
|
let len = cmp::min(<libc::c_int>::MAX as usize, slice.len());
|
||||||
let (control, controllen) = if cmsg.is_empty() {
|
let (control, controllen) = if cmsg.is_empty() {
|
||||||
(ptr::null_mut(), 0)
|
(ptr::null_mut(), 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"b3a6e03dbc48515bbca791eba64096ab43dddafa6c60eec2b824369e2afb31b8","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"d9bc993ea8bb51220c5cdc54488bc795f74411fe688332bd80dbb062c41342bb","src/lib.rs":"4ce6db20f88487e99057ebeae0615fa1c99e82cfee0ab0825936da2e108fc73e","src/log.rs":"968b839a8a5a56fe42e372678fdd580e2777e1dba8c4f0bee6fbfe5e3f03b860","src/ops.rs":"e631eba0d1ef8c13287361be32c0806d7869f598f58266bab0a45642521fa07e","src/traits.rs":"45e3e58772dd0ff40bf36d56dd9f1fc682cc08cea570022fa50eae1c34d43a3a","tests/test_capi.rs":"783c8321dceb33a414168ae64e162f934015144f49118d868557009819a20e06"},"package":"b00b0f3b84e315571bd8c4e18794180633066267a413f2f05bca65001adc8410"}
|
{"files":{"Cargo.toml":"ea3e08eb6e9fd52717bf756cf2a7063afeb3af617df0dee2f14591f45b9e6f62","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/capi.rs":"d9bc993ea8bb51220c5cdc54488bc795f74411fe688332bd80dbb062c41342bb","src/lib.rs":"4ce6db20f88487e99057ebeae0615fa1c99e82cfee0ab0825936da2e108fc73e","src/log.rs":"968b839a8a5a56fe42e372678fdd580e2777e1dba8c4f0bee6fbfe5e3f03b860","src/ops.rs":"e631eba0d1ef8c13287361be32c0806d7869f598f58266bab0a45642521fa07e","src/traits.rs":"876ea164c03d198c92a61d9b11d2839c3a257ae48042b9cd2d9ececcf00d373a","tests/test_capi.rs":"783c8321dceb33a414168ae64e162f934015144f49118d868557009819a20e06"},"package":"67361fe9b49b4599e2a230ce322529b6ddd91df14897c872dcede716f8fbca81"}
|
||||||
4
third_party/rust/cubeb-backend/Cargo.toml
vendored
4
third_party/rust/cubeb-backend/Cargo.toml
vendored
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cubeb-backend"
|
name = "cubeb-backend"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
||||||
description = """
|
description = """
|
||||||
Bindings to libcubeb internals to facilitate implementing cubeb backends in rust.
|
Bindings to libcubeb internals to facilitate implementing cubeb backends in rust.
|
||||||
|
|
@ -23,7 +23,7 @@ license = "ISC"
|
||||||
repository = "https://github.com/mozilla/cubeb-rs"
|
repository = "https://github.com/mozilla/cubeb-rs"
|
||||||
|
|
||||||
[dependencies.cubeb-core]
|
[dependencies.cubeb-core]
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
gecko-in-tree = ["cubeb-core/gecko-in-tree"]
|
gecko-in-tree = ["cubeb-core/gecko-in-tree"]
|
||||||
|
|
|
||||||
2
third_party/rust/cubeb-backend/src/traits.rs
vendored
2
third_party/rust/cubeb-backend/src/traits.rs
vendored
|
|
@ -24,7 +24,7 @@ pub trait ContextOps {
|
||||||
collection: &DeviceCollectionRef,
|
collection: &DeviceCollectionRef,
|
||||||
) -> Result<()>;
|
) -> Result<()>;
|
||||||
fn device_collection_destroy(&mut self, collection: &mut DeviceCollectionRef) -> Result<()>;
|
fn device_collection_destroy(&mut self, collection: &mut DeviceCollectionRef) -> Result<()>;
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn stream_init(
|
fn stream_init(
|
||||||
&mut self,
|
&mut self,
|
||||||
stream_name: Option<&CStr>,
|
stream_name: Option<&CStr>,
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.toml":"9f1c5d546cc66c991eafd6369bb8799f6021e677217b86f092d08c6a1e6fee6a","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"87adbbdd63fde848eeaae4a79a04859ed02ca982fb644f6b8b5fe7c158a8944c","src/call.rs":"cf8949c2cf53f5418d8e5222f570b9301a98a476a18c734fc2ebbc8b53ac0165","src/channel.rs":"c88b8846e53bbec6b125a4fa6a3787c48312be958bd08cc5ee773b218d93d683","src/context.rs":"ac5937037e69f32bb3ef5985d1921f53a2651d0068c12f90762eb0e18489e93e","src/device.rs":"86fd507bf1cd97b13b8cf3e92519b3be11904be68d4997658b276d5054162cd7","src/device_collection.rs":"f86535ffeee73b889bdbac1c5a3432b01cca86df819a7cc26eaa0c983d30cbbe","src/error.rs":"3693bf575e9504b9b1ab114de3e2ce7132039acf27ec68967dae66c2ce1581aa","src/ffi_types.rs":"71948d0949675df876e18c4340f4e693fc6a14c4de9d63a3885450c95577596b","src/format.rs":"7162c1550be53f5fe94b0bba4c71fea2f0304462108657c62a20ea47207ca413","src/lib.rs":"57ecf793ab1cc052c021ccbf9ad011ea52d1303e2dbc54adea90a95b5d7a36cf","src/log.rs":"4bef74d7a7fd9ffdf249be5ef95781969f00a7ecff2d3a190d5b1536d1635a73","src/stream.rs":"9fbfc65f77fb1009f8578c530744276828a6d6778f53b96decb698d937c2b098","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"2380c03a7df0ea3744f6a210d6340f423935e53cbf2fd68ada84b5e808e46ac7"}
|
{"files":{"Cargo.toml":"23878f9ab656986033932729656b52e131f3fc186be68fa7bbef288d6d7590d8","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","src/builders.rs":"584d3e911d55746ab6ff9aed4c5901a73a9518ac14fa2e589fe169541ec78e33","src/call.rs":"cf8949c2cf53f5418d8e5222f570b9301a98a476a18c734fc2ebbc8b53ac0165","src/channel.rs":"c88b8846e53bbec6b125a4fa6a3787c48312be958bd08cc5ee773b218d93d683","src/context.rs":"f58f8562599d27ab4a9bf76d429a5b7dc971449c20245803fc857ddb6e3090cc","src/device.rs":"86fd507bf1cd97b13b8cf3e92519b3be11904be68d4997658b276d5054162cd7","src/device_collection.rs":"f86535ffeee73b889bdbac1c5a3432b01cca86df819a7cc26eaa0c983d30cbbe","src/error.rs":"3693bf575e9504b9b1ab114de3e2ce7132039acf27ec68967dae66c2ce1581aa","src/ffi_types.rs":"71948d0949675df876e18c4340f4e693fc6a14c4de9d63a3885450c95577596b","src/format.rs":"7162c1550be53f5fe94b0bba4c71fea2f0304462108657c62a20ea47207ca413","src/lib.rs":"57ecf793ab1cc052c021ccbf9ad011ea52d1303e2dbc54adea90a95b5d7a36cf","src/log.rs":"4bef74d7a7fd9ffdf249be5ef95781969f00a7ecff2d3a190d5b1536d1635a73","src/stream.rs":"9fbfc65f77fb1009f8578c530744276828a6d6778f53b96decb698d937c2b098","src/util.rs":"308cfbaacd615ff600e74415c52daeef007fff34a4a0648a73c0042f6067f84f"},"package":"ac08d314dd1ec6d41d9ccdeec70899c98ed3b89845367000dd6096099481bc73"}
|
||||||
4
third_party/rust/cubeb-core/Cargo.toml
vendored
4
third_party/rust/cubeb-core/Cargo.toml
vendored
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cubeb-core"
|
name = "cubeb-core"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
||||||
description = """
|
description = """
|
||||||
Common types and definitions for cubeb rust and C bindings. Not intended for direct use.
|
Common types and definitions for cubeb rust and C bindings. Not intended for direct use.
|
||||||
|
|
@ -26,7 +26,7 @@ repository = "https://github.com/mozilla/cubeb-rs"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
|
||||||
[dependencies.cubeb-sys]
|
[dependencies.cubeb-sys]
|
||||||
version = "0.12.0"
|
version = "0.13"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
gecko-in-tree = ["cubeb-sys/gecko-in-tree"]
|
gecko-in-tree = ["cubeb-sys/gecko-in-tree"]
|
||||||
|
|
|
||||||
1
third_party/rust/cubeb-core/src/builders.rs
vendored
1
third_party/rust/cubeb-core/src/builders.rs
vendored
|
|
@ -6,7 +6,6 @@
|
||||||
use ffi;
|
use ffi;
|
||||||
use {ChannelLayout, SampleFormat, StreamParams, StreamPrefs};
|
use {ChannelLayout, SampleFormat, StreamParams, StreamPrefs};
|
||||||
|
|
||||||
///
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StreamParamsBuilder(ffi::cubeb_stream_params);
|
pub struct StreamParamsBuilder(ffi::cubeb_stream_params);
|
||||||
|
|
||||||
|
|
|
||||||
2
third_party/rust/cubeb-core/src/context.rs
vendored
2
third_party/rust/cubeb-core/src/context.rs
vendored
|
|
@ -95,7 +95,7 @@ impl ContextRef {
|
||||||
///
|
///
|
||||||
/// This function is unsafe because it dereferences the given `data_callback`, `state_callback`, and `user_ptr` pointers.
|
/// This function is unsafe because it dereferences the given `data_callback`, `state_callback`, and `user_ptr` pointers.
|
||||||
/// The caller should ensure those pointers are valid.
|
/// The caller should ensure those pointers are valid.
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub unsafe fn stream_init(
|
pub unsafe fn stream_init(
|
||||||
&self,
|
&self,
|
||||||
stream_name: Option<&CStr>,
|
stream_name: Option<&CStr>,
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"ac8f4cf5b7631b5c738d50c0cf78113bd395940b9e76593904bbaf2d02d16a70",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"a16b883e4fb41bdbbe5f68158040f181aeeffb4573ab0d493e9452f7c6f00541","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":"90c2542fa3ff8a35fed894fae3a1aa0157117b7f0e28df14b8e6f7b1f1f43797","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"db7d644358090b1d65ff2d53ad854369790ae4ad7dfa12b79888c0002c1b4950","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"a7622feaa41db1cd76fd35a85a022e44f4894e396a104a59008d5b8757d2ab4e","src/backend/mixer.rs":"c4d09291598cbffb2217b551770ec590f34b6dd6b461dd99b019d5bb70f0eef3","src/backend/mod.rs":"d75e116a58d63c6a7cb281d160066f48c8c449702dad58c762ad50d9512d7bd3","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"770cf90f32b5ab2203476031c1fbc8379b713baa97bec36f7fd0d77fef1efd60","src/backend/tests/api.rs":"773e88b506efccf0eacbf408d34dea1fb2c5a8500e7fe8a494a97f15f1ea41fc","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"babf50326fb38db24fe80f24f546e1b6ad04319ae8835bb372d893fc9b3038a2","src/backend/tests/device_property.rs":"73c25f579a995e8a59c9b7d391813afb75f739b5e2f825480cba04499a1d46e8","src/backend/tests/interfaces.rs":"654333cd6d6023e72ba392d98872d33bc55f8f052205a9f701aec72069449e24","src/backend/tests/manual.rs":"e550cc8bb7619bb80b68e49bf7f475c029e0f1b34323d1d30edcbe322cf4efc7","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"80d7e4ebc06b23c63a4d2867e0c80e0bfe05449fa55edd21e785ed2c089bf7d5","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
|
{"files":{".circleci/config.yml":"7f3dc865105ca8f33965a7958b1fe2e627ae2d5a703f3b2a4ab6e2e796018597",".editorconfig":"4e53b182bcc78b83d7e1b5c03efa14d22d4955c4ed2514d1ba4e99c1eb1a50ba",".githooks/pre-push":"8b8b26544cd56f54c0c33812551f786bb25cb08c86dbfeb6bf3daad881c826a1",".github/workflows/test.yml":"cf6ebe6d41b022897360866b526d19ba8843aa82ae99a1d28393985576b6a782",".travis.yml":"dc07bac53f70f16c9bdf52264bdc58500ae6018c1b4c567bc7642f6b4ca3cc35","Cargo.toml":"2698cf87581d8d551ed3ac5875564720ed23d7b788e8d145d4281c8026203cd2","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":"90c2542fa3ff8a35fed894fae3a1aa0157117b7f0e28df14b8e6f7b1f1f43797","run_sanitizers.sh":"84e93a0da137803018f37403511e8c92760be730426bf6cea34419d93d1a7ff8","run_tests.sh":"bae82f66dd47a060b6fdcc238520084aec1079d5b1b1d66d103baa1ffaa8773d","src/backend/aggregate_device.rs":"6e94c36c09081a728b1ab748b460fe8f538cf5f50bc62fd47171a393fe2d609a","src/backend/auto_release.rs":"050fdcee74cf46b9a8a85a877e166d72a853d33220f59cf734cbb6ea09daa441","src/backend/buffer_manager.rs":"e9bcf964347daa8952f98caa2746e34a31ea8908375204896593f56e4b6147ca","src/backend/device_property.rs":"0714b90c3187b0b1709f5e4b7757e1b434659276e00db48a3f3270fbfd429640","src/backend/mixer.rs":"c4d09291598cbffb2217b551770ec590f34b6dd6b461dd99b019d5bb70f0eef3","src/backend/mod.rs":"cfda5e4d5f7d3f6fda65fbcbf19bb114cdd2d9b6750c03967a4432bd1bfb788e","src/backend/resampler.rs":"48bf8f56ae8d60dbabca6417b768000619abee8731ac3902164b45651ac08a4d","src/backend/tests/aggregate_device.rs":"48e291b355a7c0c643fc58e9d238ed00234b4f1ac0f4c26737cc74862d4f2ac8","src/backend/tests/api.rs":"ef3babcd3410394b8d5bcdaf0ea526486b14d8e42f33211997aafe179430bf4a","src/backend/tests/backlog.rs":"3b189a7e036543c467cc242af0ed3332721179ee2b1c8847a6db563546f1ac52","src/backend/tests/device_change.rs":"babf50326fb38db24fe80f24f546e1b6ad04319ae8835bb372d893fc9b3038a2","src/backend/tests/device_property.rs":"73c25f579a995e8a59c9b7d391813afb75f739b5e2f825480cba04499a1d46e8","src/backend/tests/interfaces.rs":"cd58614435574444d8a1f039dc201cf371cccacd58efbae8ed8fbff919550d0a","src/backend/tests/manual.rs":"16dca201d7a7c6d37186aafdee277d437fc2ce5bbd215f33e660c6cb971395de","src/backend/tests/mod.rs":"8dba770023d7f9c4228f0e11915347f0e07da5fd818e3ee4478c4b197af9aa2a","src/backend/tests/parallel.rs":"a7ebd579339c40ca64c0757cc9da6baec641e670f226e1b2ec5049894700bd7a","src/backend/tests/tone.rs":"b028c67777b6453a26190b6a49785dfe28556adcbe179cb10862ce0d47ee8509","src/backend/tests/utils.rs":"21c8e7f6f18da0f8d33733ad0fc981041b43586db6a637c3f7aec7e7b3936aed","src/backend/utils.rs":"6c3ffbcd602e6cc9f56deb9ecb07b2eef2e6f074ef924178e466f380aae5c595","src/capi.rs":"21b66b70545bf04ec719928004d1d9adb45b24ced51288f5b2993d79aaf78f5f","src/lib.rs":"5e586d45cd6b3722f0a6736d9252593299269817a153eef1930a5fb9bfbb56f5","todo.md":"efc1f012eb9a331a040cad4ac03aa79307f25885f71b6fb38f3ad7af8d7d515c"},"package":null}
|
||||||
|
|
@ -33,10 +33,13 @@ jobs:
|
||||||
rustc --version
|
rustc --version
|
||||||
cargo --version
|
cargo --version
|
||||||
|
|
||||||
- name: Setup Audio
|
- name: Setup switchaudio
|
||||||
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }}
|
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-14' }}
|
||||||
run: |
|
run: |
|
||||||
brew install switchaudio-osx
|
brew install switchaudio-osx
|
||||||
|
|
||||||
|
- name: Setup blackhole-2ch
|
||||||
|
run: |
|
||||||
brew install blackhole-2ch
|
brew install blackhole-2ch
|
||||||
SwitchAudioSource -s "BlackHole 2ch" -t input
|
SwitchAudioSource -s "BlackHole 2ch" -t input
|
||||||
SwitchAudioSource -s "BlackHole 2ch" -t output
|
SwitchAudioSource -s "BlackHole 2ch" -t output
|
||||||
|
|
|
||||||
2
third_party/rust/cubeb-coreaudio/Cargo.toml
vendored
2
third_party/rust/cubeb-coreaudio/Cargo.toml
vendored
|
|
@ -29,7 +29,7 @@ crate-type = [
|
||||||
atomic = "0.4"
|
atomic = "0.4"
|
||||||
audio-mixer = "0.2"
|
audio-mixer = "0.2"
|
||||||
bitflags = "2"
|
bitflags = "2"
|
||||||
cubeb-backend = "0.12.0"
|
cubeb-backend = "0.13"
|
||||||
float-cmp = "0.6"
|
float-cmp = "0.6"
|
||||||
lazy_static = "1.2"
|
lazy_static = "1.2"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
|
||||||
|
|
@ -149,11 +149,12 @@ impl AggregateDevice {
|
||||||
pub fn create_blank_device_sync(
|
pub fn create_blank_device_sync(
|
||||||
plugin_id: AudioObjectID,
|
plugin_id: AudioObjectID,
|
||||||
) -> std::result::Result<AudioObjectID, Error> {
|
) -> std::result::Result<AudioObjectID, Error> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let waiting_time = Duration::new(5, 0);
|
let waiting_time = Duration::new(5, 0);
|
||||||
|
|
||||||
let condvar_pair = Arc::new((Mutex::new(Vec::<AudioObjectID>::new()), Condvar::new()));
|
let condvar_pair = Arc::new((Mutex::new(()), Condvar::new()));
|
||||||
let mut cloned_condvar_pair = condvar_pair.clone();
|
let mut cloned_condvar_pair = condvar_pair.clone();
|
||||||
let data_ptr = &mut cloned_condvar_pair as *mut Arc<(Mutex<Vec<AudioObjectID>>, Condvar)>;
|
let data_ptr = &mut cloned_condvar_pair as *mut Arc<(Mutex<()>, Condvar)>;
|
||||||
|
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
Property::HardwareDevices,
|
Property::HardwareDevices,
|
||||||
|
|
@ -182,18 +183,18 @@ impl AggregateDevice {
|
||||||
|
|
||||||
// Wait until the aggregate is created.
|
// Wait until the aggregate is created.
|
||||||
let (lock, cvar) = &*condvar_pair;
|
let (lock, cvar) = &*condvar_pair;
|
||||||
let devices = lock.lock().unwrap();
|
let guard = lock.lock().unwrap();
|
||||||
if !devices.contains(&device) {
|
let (_guard, timeout_res) = cvar
|
||||||
let (devs, timeout_res) = cvar.wait_timeout(devices, waiting_time).unwrap();
|
.wait_timeout_while(guard, waiting_time, |()| {
|
||||||
if timeout_res.timed_out() {
|
!audiounit_get_devices().contains(&device)
|
||||||
cubeb_log!(
|
})
|
||||||
"Time out for waiting the creation of aggregate device {}!",
|
.unwrap();
|
||||||
device
|
if timeout_res.timed_out() {
|
||||||
);
|
cubeb_log!(
|
||||||
}
|
"Time out for waiting the creation of aggregate device {}!",
|
||||||
if !devs.contains(&device) {
|
device
|
||||||
return Err(Error::from(waiting_time));
|
);
|
||||||
}
|
return Err(Error::from(waiting_time));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn devices_changed_callback(
|
extern "C" fn devices_changed_callback(
|
||||||
|
|
@ -203,10 +204,9 @@ impl AggregateDevice {
|
||||||
data: *mut c_void,
|
data: *mut c_void,
|
||||||
) -> OSStatus {
|
) -> OSStatus {
|
||||||
assert_eq!(id, kAudioObjectSystemObject);
|
assert_eq!(id, kAudioObjectSystemObject);
|
||||||
let pair = unsafe { &mut *(data as *mut Arc<(Mutex<Vec<AudioObjectID>>, Condvar)>) };
|
let pair = unsafe { &mut *(data as *mut Arc<(Mutex<()>, Condvar)>) };
|
||||||
let (lock, cvar) = &**pair;
|
let (lock, cvar) = &**pair;
|
||||||
let mut devices = lock.lock().unwrap();
|
let _guard = lock.lock().unwrap();
|
||||||
*devices = audiounit_get_devices();
|
|
||||||
cvar.notify_one();
|
cvar.notify_one();
|
||||||
NO_ERR
|
NO_ERR
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +218,7 @@ impl AggregateDevice {
|
||||||
plugin_id: AudioObjectID,
|
plugin_id: AudioObjectID,
|
||||||
) -> std::result::Result<AudioObjectID, Error> {
|
) -> std::result::Result<AudioObjectID, Error> {
|
||||||
assert_ne!(plugin_id, kAudioObjectUnknown);
|
assert_ne!(plugin_id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
mSelector: kAudioPlugInCreateAggregateDevice,
|
mSelector: kAudioPlugInCreateAggregateDevice,
|
||||||
|
|
@ -306,6 +307,7 @@ impl AggregateDevice {
|
||||||
input_id: AudioDeviceID,
|
input_id: AudioDeviceID,
|
||||||
output_id: AudioDeviceID,
|
output_id: AudioDeviceID,
|
||||||
) -> std::result::Result<(), Error> {
|
) -> std::result::Result<(), Error> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
mSelector: kAudioAggregateDevicePropertyFullSubDeviceList,
|
mSelector: kAudioAggregateDevicePropertyFullSubDeviceList,
|
||||||
mScope: kAudioObjectPropertyScopeGlobal,
|
mScope: kAudioObjectPropertyScopeGlobal,
|
||||||
|
|
@ -392,6 +394,7 @@ impl AggregateDevice {
|
||||||
assert_ne!(input_id, kAudioObjectUnknown);
|
assert_ne!(input_id, kAudioObjectUnknown);
|
||||||
assert_ne!(output_id, kAudioObjectUnknown);
|
assert_ne!(output_id, kAudioObjectUnknown);
|
||||||
assert_ne!(input_id, output_id);
|
assert_ne!(input_id, output_id);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let output_sub_devices = Self::get_sub_devices(output_id)?;
|
let output_sub_devices = Self::get_sub_devices(output_id)?;
|
||||||
let input_sub_devices = Self::get_sub_devices(input_id)?;
|
let input_sub_devices = Self::get_sub_devices(input_id)?;
|
||||||
|
|
@ -431,6 +434,7 @@ impl AggregateDevice {
|
||||||
device_id: AudioDeviceID,
|
device_id: AudioDeviceID,
|
||||||
) -> std::result::Result<Vec<AudioObjectID>, Error> {
|
) -> std::result::Result<Vec<AudioObjectID>, Error> {
|
||||||
assert_ne!(device_id, kAudioObjectUnknown);
|
assert_ne!(device_id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let mut sub_devices = Vec::new();
|
let mut sub_devices = Vec::new();
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
|
|
@ -468,6 +472,7 @@ impl AggregateDevice {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_master_device_uid(device_id: AudioDeviceID) -> std::result::Result<String, Error> {
|
pub fn get_master_device_uid(device_id: AudioDeviceID) -> std::result::Result<String, Error> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
mSelector: kAudioAggregateDevicePropertyMainSubDevice,
|
mSelector: kAudioAggregateDevicePropertyMainSubDevice,
|
||||||
mScope: kAudioObjectPropertyScopeGlobal,
|
mScope: kAudioObjectPropertyScopeGlobal,
|
||||||
|
|
@ -495,6 +500,7 @@ impl AggregateDevice {
|
||||||
) -> std::result::Result<(), Error> {
|
) -> std::result::Result<(), Error> {
|
||||||
assert_ne!(device_id, kAudioObjectUnknown);
|
assert_ne!(device_id, kAudioObjectUnknown);
|
||||||
assert_ne!(primary_id, kAudioObjectUnknown);
|
assert_ne!(primary_id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
cubeb_log!(
|
cubeb_log!(
|
||||||
"Set master device of the aggregate device {} to device {}",
|
"Set master device of the aggregate device {} to device {}",
|
||||||
|
|
@ -526,6 +532,7 @@ impl AggregateDevice {
|
||||||
device_id: AudioObjectID,
|
device_id: AudioObjectID,
|
||||||
) -> std::result::Result<(), Error> {
|
) -> std::result::Result<(), Error> {
|
||||||
assert_ne!(device_id, kAudioObjectUnknown);
|
assert_ne!(device_id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
mSelector: kAudioObjectPropertyOwnedObjects,
|
mSelector: kAudioObjectPropertyOwnedObjects,
|
||||||
mScope: kAudioObjectPropertyScopeGlobal,
|
mScope: kAudioObjectPropertyScopeGlobal,
|
||||||
|
|
@ -609,6 +616,7 @@ impl AggregateDevice {
|
||||||
) -> std::result::Result<(), Error> {
|
) -> std::result::Result<(), Error> {
|
||||||
assert_ne!(plugin_id, kAudioObjectUnknown);
|
assert_ne!(plugin_id, kAudioObjectUnknown);
|
||||||
assert_ne!(device_id, kAudioObjectUnknown);
|
assert_ne!(device_id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = AudioObjectPropertyAddress {
|
let address = AudioObjectPropertyAddress {
|
||||||
mSelector: kAudioPlugInDestroyAggregateDevice,
|
mSelector: kAudioPlugInDestroyAggregateDevice,
|
||||||
|
|
@ -640,6 +648,7 @@ impl AggregateDevice {
|
||||||
assert_ne!(input_id, kAudioObjectUnknown);
|
assert_ne!(input_id, kAudioObjectUnknown);
|
||||||
assert_ne!(output_id, kAudioObjectUnknown);
|
assert_ne!(output_id, kAudioObjectUnknown);
|
||||||
assert_ne!(input_id, output_id);
|
assert_ne!(input_id, output_id);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let label = get_device_label(input_id, DeviceType::INPUT)?;
|
let label = get_device_label(input_id, DeviceType::INPUT)?;
|
||||||
let input_label = label.into_string();
|
let input_label = label.into_string();
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ pub fn get_device_uid(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceUID, devtype);
|
let address = get_property_address(Property::DeviceUID, devtype);
|
||||||
let mut size = mem::size_of::<CFStringRef>();
|
let mut size = mem::size_of::<CFStringRef>();
|
||||||
|
|
@ -22,6 +23,7 @@ pub fn get_device_model_uid(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::ModelUID, devtype);
|
let address = get_property_address(Property::ModelUID, devtype);
|
||||||
let mut size = mem::size_of::<CFStringRef>();
|
let mut size = mem::size_of::<CFStringRef>();
|
||||||
|
|
@ -39,6 +41,7 @@ pub fn get_device_transport_type(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<u32, OSStatus> {
|
) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::TransportType, devtype);
|
let address = get_property_address(Property::TransportType, devtype);
|
||||||
let mut size = mem::size_of::<u32>();
|
let mut size = mem::size_of::<u32>();
|
||||||
|
|
@ -56,6 +59,7 @@ pub fn get_device_source(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<u32, OSStatus> {
|
) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceSource, devtype);
|
let address = get_property_address(Property::DeviceSource, devtype);
|
||||||
let mut size = mem::size_of::<u32>();
|
let mut size = mem::size_of::<u32>();
|
||||||
|
|
@ -73,6 +77,7 @@ pub fn get_device_source_name(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let mut source: u32 = get_device_source(id, devtype)?;
|
let mut source: u32 = get_device_source(id, devtype)?;
|
||||||
let address = get_property_address(Property::DeviceSourceName, devtype);
|
let address = get_property_address(Property::DeviceSourceName, devtype);
|
||||||
|
|
@ -97,6 +102,7 @@ pub fn get_device_name(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceName, devtype);
|
let address = get_property_address(Property::DeviceName, devtype);
|
||||||
let mut size = mem::size_of::<CFStringRef>();
|
let mut size = mem::size_of::<CFStringRef>();
|
||||||
|
|
@ -114,6 +120,7 @@ pub fn get_device_manufacturer(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceManufacturer, devtype);
|
let address = get_property_address(Property::DeviceManufacturer, devtype);
|
||||||
let mut size = mem::size_of::<CFStringRef>();
|
let mut size = mem::size_of::<CFStringRef>();
|
||||||
|
|
@ -131,6 +138,7 @@ pub fn get_device_buffer_frame_size_range(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<AudioValueRange, OSStatus> {
|
) -> std::result::Result<AudioValueRange, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceBufferFrameSizeRange, devtype);
|
let address = get_property_address(Property::DeviceBufferFrameSizeRange, devtype);
|
||||||
let mut size = mem::size_of::<AudioValueRange>();
|
let mut size = mem::size_of::<AudioValueRange>();
|
||||||
|
|
@ -148,6 +156,7 @@ pub fn get_device_latency(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<u32, OSStatus> {
|
) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceLatency, devtype);
|
let address = get_property_address(Property::DeviceLatency, devtype);
|
||||||
let mut size = mem::size_of::<u32>();
|
let mut size = mem::size_of::<u32>();
|
||||||
|
|
@ -165,6 +174,7 @@ pub fn get_device_streams(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<Vec<AudioStreamID>, OSStatus> {
|
) -> std::result::Result<Vec<AudioStreamID>, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceStreams, devtype);
|
let address = get_property_address(Property::DeviceStreams, devtype);
|
||||||
|
|
||||||
|
|
@ -188,6 +198,7 @@ pub fn get_device_sample_rate(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<f64, OSStatus> {
|
) -> std::result::Result<f64, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceSampleRate, devtype);
|
let address = get_property_address(Property::DeviceSampleRate, devtype);
|
||||||
let mut size = mem::size_of::<f64>();
|
let mut size = mem::size_of::<f64>();
|
||||||
|
|
@ -205,6 +216,7 @@ pub fn get_ranges_of_device_sample_rate(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<Vec<AudioValueRange>, OSStatus> {
|
) -> std::result::Result<Vec<AudioValueRange>, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::DeviceSampleRates, devtype);
|
let address = get_property_address(Property::DeviceSampleRates, devtype);
|
||||||
|
|
||||||
|
|
@ -225,6 +237,7 @@ pub fn get_ranges_of_device_sample_rate(
|
||||||
|
|
||||||
pub fn get_stream_latency(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
|
pub fn get_stream_latency(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
Property::StreamLatency,
|
Property::StreamLatency,
|
||||||
|
|
@ -242,6 +255,7 @@ pub fn get_stream_latency(id: AudioStreamID) -> std::result::Result<u32, OSStatu
|
||||||
|
|
||||||
pub fn get_stream_terminal_type(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
|
pub fn get_stream_terminal_type(id: AudioStreamID) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
Property::StreamTerminalType,
|
Property::StreamTerminalType,
|
||||||
|
|
@ -261,6 +275,7 @@ pub fn get_stream_virtual_format(
|
||||||
id: AudioStreamID,
|
id: AudioStreamID,
|
||||||
) -> std::result::Result<AudioStreamBasicDescription, OSStatus> {
|
) -> std::result::Result<AudioStreamBasicDescription, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
Property::StreamVirtualFormat,
|
Property::StreamVirtualFormat,
|
||||||
|
|
@ -281,6 +296,7 @@ pub fn get_clock_domain(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<u32, OSStatus> {
|
) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(id, kAudioObjectUnknown);
|
assert_ne!(id, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let address = get_property_address(Property::ClockDomain, devtype);
|
let address = get_property_address(Property::ClockDomain, devtype);
|
||||||
let mut size = mem::size_of::<u32>();
|
let mut size = mem::size_of::<u32>();
|
||||||
|
|
|
||||||
318
third_party/rust/cubeb-coreaudio/src/backend/mod.rs
vendored
318
third_party/rust/cubeb-coreaudio/src/backend/mod.rs
vendored
|
|
@ -33,7 +33,7 @@ use self::mixer::*;
|
||||||
use self::resampler::*;
|
use self::resampler::*;
|
||||||
use self::utils::*;
|
use self::utils::*;
|
||||||
use backend::ringbuf::RingBuffer;
|
use backend::ringbuf::RingBuffer;
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
use cubeb_backend::ffi::cubeb_audio_dump_stream_t;
|
use cubeb_backend::ffi::cubeb_audio_dump_stream_t;
|
||||||
use cubeb_backend::{
|
use cubeb_backend::{
|
||||||
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
|
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
|
||||||
|
|
@ -116,7 +116,7 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
fn dump_audio(stream: cubeb_audio_dump_stream_t, audio_samples: *mut c_void, count: u32) {
|
fn dump_audio(stream: cubeb_audio_dump_stream_t, audio_samples: *mut c_void, count: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let rv = ffi::cubeb_audio_dump_write(stream, audio_samples, count);
|
let rv = ffi::cubeb_audio_dump_write(stream, audio_samples, count);
|
||||||
|
|
@ -569,7 +569,7 @@ extern "C" fn audiounit_input_callback(
|
||||||
} else {
|
} else {
|
||||||
assert_eq!(status, NO_ERR);
|
assert_eq!(status, NO_ERR);
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
dump_audio(
|
dump_audio(
|
||||||
stm.core_stream_data.audio_dump_input,
|
stm.core_stream_data.audio_dump_input,
|
||||||
|
|
@ -628,15 +628,15 @@ extern "C" fn audiounit_input_callback(
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
if outframes < 0 {
|
if outframes < 0 {
|
||||||
stm.stopped.store(true, Ordering::SeqCst);
|
if !stm.stopped.swap(true, Ordering::SeqCst) {
|
||||||
stm.notify_state_changed(State::Error);
|
stm.notify_state_changed(State::Error);
|
||||||
let queue = stm.queue.clone();
|
// Use a new thread, through the queue, to avoid deadlock when calling
|
||||||
// Use a new thread, through the queue, to avoid deadlock when calling
|
// AudioOutputUnitStop method from inside render callback
|
||||||
// AudioOutputUnitStop method from inside render callback
|
stm.queue.clone().run_async(move || {
|
||||||
queue.run_async(move || {
|
stm.core_stream_data.stop_audiounits();
|
||||||
stm.core_stream_data.stop_audiounits();
|
});
|
||||||
});
|
}
|
||||||
return handle;
|
return ErrorHandle::Return(status);
|
||||||
}
|
}
|
||||||
if outframes < total_input_frames {
|
if outframes < total_input_frames {
|
||||||
stm.draining.store(true, Ordering::SeqCst);
|
stm.draining.store(true, Ordering::SeqCst);
|
||||||
|
|
@ -654,15 +654,16 @@ extern "C" fn audiounit_input_callback(
|
||||||
|
|
||||||
// If the input (input-only stream) is drained, cancel this callback. Whenever an output
|
// If the input (input-only stream) is drained, cancel this callback. Whenever an output
|
||||||
// is involved, the output callback handles stopping all units and notifying of state.
|
// is involved, the output callback handles stopping all units and notifying of state.
|
||||||
if stm.core_stream_data.output_unit.is_null() && stm.draining.load(Ordering::SeqCst) {
|
if stm.core_stream_data.output_unit.is_null()
|
||||||
stm.stopped.store(true, Ordering::SeqCst);
|
&& stm.draining.load(Ordering::SeqCst)
|
||||||
|
&& !stm.stopped.swap(true, Ordering::SeqCst)
|
||||||
|
{
|
||||||
cubeb_alog!("({:p}) Input-only drained.", stm as *const AudioUnitStream);
|
cubeb_alog!("({:p}) Input-only drained.", stm as *const AudioUnitStream);
|
||||||
stm.notify_state_changed(State::Drained);
|
stm.notify_state_changed(State::Drained);
|
||||||
let queue = stm.queue.clone();
|
|
||||||
// Use a new thread, through the queue, to avoid deadlock when calling
|
// Use a new thread, through the queue, to avoid deadlock when calling
|
||||||
// AudioOutputUnitStop method from inside render callback
|
// AudioOutputUnitStop method from inside render callback
|
||||||
let stm_ptr = user_ptr as usize;
|
let stm_ptr = user_ptr as usize;
|
||||||
queue.run_async(move || {
|
stm.queue.clone().run_async(move || {
|
||||||
let stm = unsafe { &mut *(stm_ptr as *mut AudioUnitStream) };
|
let stm = unsafe { &mut *(stm_ptr as *mut AudioUnitStream) };
|
||||||
stm.core_stream_data.stop_audiounits();
|
stm.core_stream_data.stop_audiounits();
|
||||||
});
|
});
|
||||||
|
|
@ -735,7 +736,7 @@ extern "C" fn audiounit_output_callback(
|
||||||
if stm.stopped.load(Ordering::SeqCst) {
|
if stm.stopped.load(Ordering::SeqCst) {
|
||||||
cubeb_alog!("({:p}) output stopped.", stm as *const AudioUnitStream);
|
cubeb_alog!("({:p}) output stopped.", stm as *const AudioUnitStream);
|
||||||
audiounit_make_silent(&buffers[0]);
|
audiounit_make_silent(&buffers[0]);
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
dump_audio(
|
dump_audio(
|
||||||
stm.core_stream_data.audio_dump_output,
|
stm.core_stream_data.audio_dump_output,
|
||||||
|
|
@ -749,12 +750,8 @@ extern "C" fn audiounit_output_callback(
|
||||||
if stm.draining.load(Ordering::SeqCst) {
|
if stm.draining.load(Ordering::SeqCst) {
|
||||||
// Cancel all callbacks. For input-only streams, the input callback handles
|
// Cancel all callbacks. For input-only streams, the input callback handles
|
||||||
// cancelling itself.
|
// cancelling itself.
|
||||||
stm.stopped.store(true, Ordering::SeqCst);
|
|
||||||
cubeb_alog!("({:p}) output drained.", stm as *const AudioUnitStream);
|
|
||||||
stm.notify_state_changed(State::Drained);
|
|
||||||
let queue = stm.queue.clone();
|
|
||||||
audiounit_make_silent(&buffers[0]);
|
audiounit_make_silent(&buffers[0]);
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
dump_audio(
|
dump_audio(
|
||||||
stm.core_stream_data.audio_dump_output,
|
stm.core_stream_data.audio_dump_output,
|
||||||
|
|
@ -762,11 +759,15 @@ extern "C" fn audiounit_output_callback(
|
||||||
output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
|
output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Use a new thread, through the queue, to avoid deadlock when calling
|
if !stm.stopped.swap(true, Ordering::SeqCst) {
|
||||||
// AudioOutputUnitStop method from inside render callback
|
cubeb_alog!("({:p}) output drained.", stm as *const AudioUnitStream);
|
||||||
queue.run_async(move || {
|
stm.notify_state_changed(State::Drained);
|
||||||
stm.core_stream_data.stop_audiounits();
|
// Use a new thread, through the queue, to avoid deadlock when calling
|
||||||
});
|
// AudioOutputUnitStop method from inside render callback
|
||||||
|
stm.queue.clone().run_async(move || {
|
||||||
|
stm.core_stream_data.stop_audiounits();
|
||||||
|
});
|
||||||
|
}
|
||||||
return NO_ERR;
|
return NO_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -886,12 +887,9 @@ extern "C" fn audiounit_output_callback(
|
||||||
);
|
);
|
||||||
|
|
||||||
if outframes < 0 || outframes > i64::from(output_frames) {
|
if outframes < 0 || outframes > i64::from(output_frames) {
|
||||||
stm.stopped.store(true, Ordering::SeqCst);
|
|
||||||
stm.notify_state_changed(State::Error);
|
|
||||||
let queue = stm.queue.clone();
|
|
||||||
audiounit_make_silent(&buffers[0]);
|
audiounit_make_silent(&buffers[0]);
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
dump_audio(
|
dump_audio(
|
||||||
stm.core_stream_data.audio_dump_output,
|
stm.core_stream_data.audio_dump_output,
|
||||||
|
|
@ -899,11 +897,14 @@ extern "C" fn audiounit_output_callback(
|
||||||
output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
|
output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Use a new thread, through the queue, to avoid deadlock when calling
|
if !stm.stopped.swap(true, Ordering::SeqCst) {
|
||||||
// AudioOutputUnitStop method from inside render callback
|
stm.notify_state_changed(State::Error);
|
||||||
queue.run_async(move || {
|
// Use a new thread, through the queue, to avoid deadlock when calling
|
||||||
stm.core_stream_data.stop_audiounits();
|
// AudioOutputUnitStop method from inside render callback
|
||||||
});
|
stm.queue.clone().run_async(move || {
|
||||||
|
stm.core_stream_data.stop_audiounits();
|
||||||
|
});
|
||||||
|
}
|
||||||
return NO_ERR;
|
return NO_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -951,7 +952,7 @@ extern "C" fn audiounit_output_callback(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
dump_audio(
|
dump_audio(
|
||||||
stm.core_stream_data.audio_dump_output,
|
stm.core_stream_data.audio_dump_output,
|
||||||
|
|
@ -1001,15 +1002,16 @@ extern "C" fn audiounit_property_listener_callback(
|
||||||
|
|
||||||
// Handle the events
|
// Handle the events
|
||||||
if explicit_device_dead {
|
if explicit_device_dead {
|
||||||
cubeb_log!("The user-selected input or output device is dead, entering error state");
|
if !stm.stopped.swap(true, Ordering::SeqCst) {
|
||||||
stm.stopped.store(true, Ordering::SeqCst);
|
cubeb_log!("The user-selected input or output device is dead, entering error state");
|
||||||
|
|
||||||
// Use a different thread, through the queue, to avoid deadlock when calling
|
// Use a different thread, through the queue, to avoid deadlock when calling
|
||||||
// Get/SetProperties method from inside notify callback
|
// Get/SetProperties method from inside notify callback
|
||||||
stm.queue.clone().run_async(move || {
|
stm.queue.clone().run_async(move || {
|
||||||
stm.core_stream_data.stop_audiounits();
|
stm.core_stream_data.stop_audiounits();
|
||||||
stm.close_on_error();
|
stm.close_on_error();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return NO_ERR;
|
return NO_ERR;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
@ -1026,6 +1028,7 @@ extern "C" fn audiounit_property_listener_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_default_device(devtype: DeviceType) -> Option<AudioObjectID> {
|
fn get_default_device(devtype: DeviceType) -> Option<AudioObjectID> {
|
||||||
|
debug_assert_running_serially();
|
||||||
match get_default_device_id(devtype) {
|
match get_default_device_id(devtype) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
cubeb_log!("Cannot get default {:?} device. Error: {}", devtype, e);
|
cubeb_log!("Cannot get default {:?} device. Error: {}", devtype, e);
|
||||||
|
|
@ -1040,6 +1043,7 @@ fn get_default_device(devtype: DeviceType) -> Option<AudioObjectID> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_default_device_id(devtype: DeviceType) -> std::result::Result<AudioObjectID, OSStatus> {
|
fn get_default_device_id(devtype: DeviceType) -> std::result::Result<AudioObjectID, OSStatus> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
match devtype {
|
match devtype {
|
||||||
DeviceType::INPUT => Property::HardwareDefaultInputDevice,
|
DeviceType::INPUT => Property::HardwareDefaultInputDevice,
|
||||||
|
|
@ -1087,6 +1091,7 @@ fn audiounit_convert_channel_layout(layout: &AudioChannelLayout) -> Result<Vec<m
|
||||||
}
|
}
|
||||||
|
|
||||||
fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let mut rv = NO_ERR;
|
let mut rv = NO_ERR;
|
||||||
let mut size: usize = 0;
|
let mut size: usize = 0;
|
||||||
rv = audio_unit_get_property_info(
|
rv = audio_unit_get_property_info(
|
||||||
|
|
@ -1129,6 +1134,7 @@ fn audiounit_get_preferred_channel_layout(output_unit: AudioUnit) -> Result<Vec<
|
||||||
// This is for output AudioUnit only. Calling this by input-only AudioUnit is prone
|
// This is for output AudioUnit only. Calling this by input-only AudioUnit is prone
|
||||||
// to crash intermittently.
|
// to crash intermittently.
|
||||||
fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let mut rv = NO_ERR;
|
let mut rv = NO_ERR;
|
||||||
let mut size: usize = 0;
|
let mut size: usize = 0;
|
||||||
rv = audio_unit_get_property_info(
|
rv = audio_unit_get_property_info(
|
||||||
|
|
@ -1169,6 +1175,7 @@ fn audiounit_get_current_channel_layout(output_unit: AudioUnit) -> Result<Vec<mi
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
fn get_channel_layout(output_unit: AudioUnit) -> Result<Vec<mixer::Channel>> {
|
||||||
|
debug_assert_running_serially();
|
||||||
audiounit_get_current_channel_layout(output_unit)
|
audiounit_get_current_channel_layout(output_unit)
|
||||||
.or_else(|_| {
|
.or_else(|_| {
|
||||||
// The kAudioUnitProperty_AudioChannelLayout property isn't known before
|
// The kAudioUnitProperty_AudioChannelLayout property isn't known before
|
||||||
|
|
@ -1208,6 +1215,7 @@ fn create_audiounit(device: &device_info) -> Result<AudioUnit> {
|
||||||
assert!(!device
|
assert!(!device
|
||||||
.flags
|
.flags
|
||||||
.contains(device_flags::DEV_INPUT | device_flags::DEV_OUTPUT));
|
.contains(device_flags::DEV_INPUT | device_flags::DEV_OUTPUT));
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let unit = create_blank_audiounit()?;
|
let unit = create_blank_audiounit()?;
|
||||||
let mut bus = AU_OUT_BUS;
|
let mut bus = AU_OUT_BUS;
|
||||||
|
|
@ -1610,6 +1618,7 @@ fn get_channel_count(
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<u32, OSStatus> {
|
) -> std::result::Result<u32, OSStatus> {
|
||||||
assert_ne!(devid, kAudioObjectUnknown);
|
assert_ne!(devid, kAudioObjectUnknown);
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let mut streams = get_device_streams(devid, devtype)?;
|
let mut streams = get_device_streams(devid, devtype)?;
|
||||||
let model_uid =
|
let model_uid =
|
||||||
|
|
@ -1691,6 +1700,7 @@ fn get_range_of_sample_rates(
|
||||||
devid: AudioObjectID,
|
devid: AudioObjectID,
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<(f64, f64), String> {
|
) -> std::result::Result<(f64, f64), String> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let result = get_ranges_of_device_sample_rate(devid, devtype);
|
let result = get_ranges_of_device_sample_rate(devid, devtype);
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
return Err(format!("status {}", e));
|
return Err(format!("status {}", e));
|
||||||
|
|
@ -1712,6 +1722,7 @@ fn get_range_of_sample_rates(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fixed_latency(devid: AudioObjectID, devtype: DeviceType) -> u32 {
|
fn get_fixed_latency(devid: AudioObjectID, devtype: DeviceType) -> u32 {
|
||||||
|
debug_assert_running_serially();
|
||||||
let device_latency = match get_device_latency(devid, devtype) {
|
let device_latency = match get_device_latency(devid, devtype) {
|
||||||
Ok(latency) => latency,
|
Ok(latency) => latency,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
@ -1754,6 +1765,7 @@ fn get_device_group_id(
|
||||||
id: AudioDeviceID,
|
id: AudioDeviceID,
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<CString, OSStatus> {
|
) -> std::result::Result<CString, OSStatus> {
|
||||||
|
debug_assert_running_serially();
|
||||||
match get_device_transport_type(id, devtype) {
|
match get_device_transport_type(id, devtype) {
|
||||||
Ok(kAudioDeviceTransportTypeBuiltIn) => {
|
Ok(kAudioDeviceTransportTypeBuiltIn) => {
|
||||||
cubeb_log!(
|
cubeb_log!(
|
||||||
|
|
@ -1789,6 +1801,8 @@ fn get_device_group_id(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_custom_group_id(id: AudioDeviceID, devtype: DeviceType) -> Option<CString> {
|
fn get_custom_group_id(id: AudioDeviceID, devtype: DeviceType) -> Option<CString> {
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
const IMIC: u32 = 0x696D_6963; // "imic" (internal microphone)
|
const IMIC: u32 = 0x696D_6963; // "imic" (internal microphone)
|
||||||
const ISPK: u32 = 0x6973_706B; // "ispk" (internal speaker)
|
const ISPK: u32 = 0x6973_706B; // "ispk" (internal speaker)
|
||||||
const EMIC: u32 = 0x656D_6963; // "emic" (external microphone)
|
const EMIC: u32 = 0x656D_6963; // "emic" (external microphone)
|
||||||
|
|
@ -1830,10 +1844,12 @@ fn get_device_label(
|
||||||
id: AudioDeviceID,
|
id: AudioDeviceID,
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
) -> std::result::Result<StringRef, OSStatus> {
|
) -> std::result::Result<StringRef, OSStatus> {
|
||||||
|
debug_assert_running_serially();
|
||||||
get_device_source_name(id, devtype).or_else(|_| get_device_name(id, devtype))
|
get_device_source_name(id, devtype).or_else(|_| get_device_name(id, devtype))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_device_global_uid(id: AudioDeviceID) -> std::result::Result<StringRef, OSStatus> {
|
fn get_device_global_uid(id: AudioDeviceID) -> std::result::Result<StringRef, OSStatus> {
|
||||||
|
debug_assert_running_serially();
|
||||||
get_device_uid(id, DeviceType::INPUT | DeviceType::OUTPUT)
|
get_device_uid(id, DeviceType::INPUT | DeviceType::OUTPUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2016,6 +2032,7 @@ fn destroy_cubeb_device_info(device: &mut ffi::cubeb_device_info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn audiounit_get_devices() -> Vec<AudioObjectID> {
|
fn audiounit_get_devices() -> Vec<AudioObjectID> {
|
||||||
|
debug_assert_running_serially();
|
||||||
let mut size: usize = 0;
|
let mut size: usize = 0;
|
||||||
let address = get_property_address(
|
let address = get_property_address(
|
||||||
Property::HardwareDevices,
|
Property::HardwareDevices,
|
||||||
|
|
@ -2042,6 +2059,7 @@ fn audiounit_get_devices() -> Vec<AudioObjectID> {
|
||||||
|
|
||||||
fn audiounit_get_devices_of_type(devtype: DeviceType) -> Vec<AudioObjectID> {
|
fn audiounit_get_devices_of_type(devtype: DeviceType) -> Vec<AudioObjectID> {
|
||||||
assert!(devtype.intersects(DeviceType::INPUT | DeviceType::OUTPUT));
|
assert!(devtype.intersects(DeviceType::INPUT | DeviceType::OUTPUT));
|
||||||
|
debug_assert_running_serially();
|
||||||
|
|
||||||
let mut devices = audiounit_get_devices();
|
let mut devices = audiounit_get_devices();
|
||||||
|
|
||||||
|
|
@ -2708,17 +2726,21 @@ impl ContextOps for AudioUnitContext {
|
||||||
}
|
}
|
||||||
#[cfg(not(target_os = "ios"))]
|
#[cfg(not(target_os = "ios"))]
|
||||||
fn max_channel_count(&mut self) -> Result<u32> {
|
fn max_channel_count(&mut self) -> Result<u32> {
|
||||||
let device = match get_default_device(DeviceType::OUTPUT) {
|
self.serial_queue
|
||||||
None => {
|
.run_sync(|| {
|
||||||
cubeb_log!("Could not get default output device");
|
let device = match get_default_device(DeviceType::OUTPUT) {
|
||||||
return Err(Error::error());
|
None => {
|
||||||
}
|
cubeb_log!("Could not get default output device");
|
||||||
Some(id) => id,
|
return Err(Error::error());
|
||||||
};
|
}
|
||||||
get_channel_count(device, DeviceType::OUTPUT).map_err(|e| {
|
Some(id) => id,
|
||||||
cubeb_log!("Cannot get the channel count. Error: {}", e);
|
};
|
||||||
Error::error()
|
get_channel_count(device, DeviceType::OUTPUT).map_err(|e| {
|
||||||
})
|
cubeb_log!("Cannot get the channel count. Error: {}", e);
|
||||||
|
Error::error()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
|
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
|
||||||
|
|
@ -2726,21 +2748,25 @@ impl ContextOps for AudioUnitContext {
|
||||||
}
|
}
|
||||||
#[cfg(not(target_os = "ios"))]
|
#[cfg(not(target_os = "ios"))]
|
||||||
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
|
fn min_latency(&mut self, _params: StreamParams) -> Result<u32> {
|
||||||
let device = match get_default_device(DeviceType::OUTPUT) {
|
self.serial_queue
|
||||||
None => {
|
.run_sync(|| {
|
||||||
cubeb_log!("Could not get default output device");
|
let device = match get_default_device(DeviceType::OUTPUT) {
|
||||||
return Err(Error::error());
|
None => {
|
||||||
}
|
cubeb_log!("Could not get default output device");
|
||||||
Some(id) => id,
|
return Err(Error::error());
|
||||||
};
|
}
|
||||||
|
Some(id) => id,
|
||||||
|
};
|
||||||
|
|
||||||
let range =
|
let range = get_device_buffer_frame_size_range(device, DeviceType::OUTPUT)
|
||||||
get_device_buffer_frame_size_range(device, DeviceType::OUTPUT).map_err(|e| {
|
.map_err(|e| {
|
||||||
cubeb_log!("Could not get acceptable latency range. Error: {}", e);
|
cubeb_log!("Could not get acceptable latency range. Error: {}", e);
|
||||||
Error::error()
|
Error::error()
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(cmp::max(range.mMinimum as u32, SAFE_MIN_LATENCY_FRAMES))
|
Ok(cmp::max(range.mMinimum as u32, SAFE_MIN_LATENCY_FRAMES))
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "ios")]
|
#[cfg(target_os = "ios")]
|
||||||
fn preferred_sample_rate(&mut self) -> Result<u32> {
|
fn preferred_sample_rate(&mut self) -> Result<u32> {
|
||||||
|
|
@ -2748,21 +2774,25 @@ impl ContextOps for AudioUnitContext {
|
||||||
}
|
}
|
||||||
#[cfg(not(target_os = "ios"))]
|
#[cfg(not(target_os = "ios"))]
|
||||||
fn preferred_sample_rate(&mut self) -> Result<u32> {
|
fn preferred_sample_rate(&mut self) -> Result<u32> {
|
||||||
let device = match get_default_device(DeviceType::OUTPUT) {
|
self.serial_queue
|
||||||
None => {
|
.run_sync(|| {
|
||||||
cubeb_log!("Could not get default output device");
|
let device = match get_default_device(DeviceType::OUTPUT) {
|
||||||
return Err(Error::error());
|
None => {
|
||||||
}
|
cubeb_log!("Could not get default output device");
|
||||||
Some(id) => id,
|
return Err(Error::error());
|
||||||
};
|
}
|
||||||
let rate = get_device_sample_rate(device, DeviceType::OUTPUT).map_err(|e| {
|
Some(id) => id,
|
||||||
cubeb_log!(
|
};
|
||||||
"Cannot get the sample rate of the default output device. Error: {}",
|
let rate = get_device_sample_rate(device, DeviceType::OUTPUT).map_err(|e| {
|
||||||
e
|
cubeb_log!(
|
||||||
);
|
"Cannot get the sample rate of the default output device. Error: {}",
|
||||||
Error::error()
|
e
|
||||||
})?;
|
);
|
||||||
Ok(rate as u32)
|
Error::error()
|
||||||
|
})?;
|
||||||
|
Ok(rate as u32)
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
fn supported_input_processing_params(&mut self) -> Result<InputProcessingParams> {
|
fn supported_input_processing_params(&mut self) -> Result<InputProcessingParams> {
|
||||||
Ok(InputProcessingParams::ECHO_CANCELLATION
|
Ok(InputProcessingParams::ECHO_CANCELLATION
|
||||||
|
|
@ -2774,19 +2804,27 @@ impl ContextOps for AudioUnitContext {
|
||||||
devtype: DeviceType,
|
devtype: DeviceType,
|
||||||
collection: &DeviceCollectionRef,
|
collection: &DeviceCollectionRef,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut device_infos = Vec::new();
|
let device_infos = self
|
||||||
let dev_types = [DeviceType::INPUT, DeviceType::OUTPUT];
|
.serial_queue
|
||||||
for dev_type in dev_types.iter() {
|
.run_sync(|| {
|
||||||
if !devtype.contains(*dev_type) {
|
let mut dev_types = vec![DeviceType::INPUT, DeviceType::OUTPUT];
|
||||||
continue;
|
dev_types.retain(|&dt| devtype.contains(dt));
|
||||||
}
|
let device_ids: Vec<(DeviceType, Vec<AudioObjectID>)> = dev_types
|
||||||
let devices = audiounit_get_devices_of_type(*dev_type);
|
.iter()
|
||||||
for device in devices {
|
.map(|&dt| (dt, audiounit_get_devices_of_type(dt)))
|
||||||
if let Ok(info) = create_cubeb_device_info(device, *dev_type) {
|
.collect();
|
||||||
device_infos.push(info);
|
let count = device_ids.iter().map(|(_dt, ids)| ids.len()).sum();
|
||||||
|
let mut device_infos = Vec::with_capacity(count);
|
||||||
|
for (dt, dev_ids) in device_ids {
|
||||||
|
for dev_id in dev_ids {
|
||||||
|
if let Ok(info) = create_cubeb_device_info(dev_id, dt) {
|
||||||
|
device_infos.push(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
device_infos
|
||||||
}
|
})
|
||||||
|
.unwrap();
|
||||||
let (ptr, len) = if device_infos.is_empty() {
|
let (ptr, len) = if device_infos.is_empty() {
|
||||||
(ptr::null_mut(), 0)
|
(ptr::null_mut(), 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3071,13 +3109,13 @@ struct CoreStreamData<'ctx> {
|
||||||
output_alive_listener: Option<device_property_listener>,
|
output_alive_listener: Option<device_property_listener>,
|
||||||
output_source_listener: Option<device_property_listener>,
|
output_source_listener: Option<device_property_listener>,
|
||||||
input_logging: Option<InputCallbackLogger>,
|
input_logging: Option<InputCallbackLogger>,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session: ffi::cubeb_audio_dump_session_t,
|
audio_dump_session: ffi::cubeb_audio_dump_session_t,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session_running: bool,
|
audio_dump_session_running: bool,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_input: ffi::cubeb_audio_dump_stream_t,
|
audio_dump_input: ffi::cubeb_audio_dump_stream_t,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_output: ffi::cubeb_audio_dump_stream_t,
|
audio_dump_output: ffi::cubeb_audio_dump_stream_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3119,13 +3157,13 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
|
||||||
output_alive_listener: None,
|
output_alive_listener: None,
|
||||||
output_source_listener: None,
|
output_source_listener: None,
|
||||||
input_logging: None,
|
input_logging: None,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session: ptr::null_mut(),
|
audio_dump_session: ptr::null_mut(),
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session_running: false,
|
audio_dump_session_running: false,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_input: ptr::null_mut(),
|
audio_dump_input: ptr::null_mut(),
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_output: ptr::null_mut(),
|
audio_dump_output: ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3174,13 +3212,13 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
output_alive_listener: None,
|
output_alive_listener: None,
|
||||||
output_source_listener: None,
|
output_source_listener: None,
|
||||||
input_logging: None,
|
input_logging: None,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session: ptr::null_mut(),
|
audio_dump_session: ptr::null_mut(),
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_session_running: false,
|
audio_dump_session_running: false,
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_input: ptr::null_mut(),
|
audio_dump_input: ptr::null_mut(),
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
audio_dump_output: ptr::null_mut(),
|
audio_dump_output: ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3539,7 +3577,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
assert!(!self.stm_ptr.is_null());
|
assert!(!self.stm_ptr.is_null());
|
||||||
let stream = unsafe { &(*self.stm_ptr) };
|
let stream = unsafe { &(*self.stm_ptr) };
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::cubeb_audio_dump_init(&mut self.audio_dump_session);
|
ffi::cubeb_audio_dump_init(&mut self.audio_dump_session);
|
||||||
}
|
}
|
||||||
|
|
@ -3584,7 +3622,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
let r = audio_unit_get_property(
|
let r = audio_unit_get_property(
|
||||||
self.input_unit,
|
self.input_unit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Input,
|
kAudioUnitScope_Output,
|
||||||
AU_IN_BUS,
|
AU_IN_BUS,
|
||||||
&mut input_hw_desc,
|
&mut input_hw_desc,
|
||||||
&mut size,
|
&mut size,
|
||||||
|
|
@ -3601,9 +3639,6 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
self.stm_ptr,
|
self.stm_ptr,
|
||||||
input_hw_desc
|
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;
|
|
||||||
// Notice: when we are using aggregate device, the input_hw_desc.mChannelsPerFrame is
|
// 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.
|
// 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
|
// Due to our aggregate device settings, the data captured by the output device's input
|
||||||
|
|
@ -3613,12 +3648,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
// channels to the audio callback.
|
// channels to the audio callback.
|
||||||
let params = unsafe {
|
let params = unsafe {
|
||||||
let mut p = *self.input_stream_params.as_ptr();
|
let mut p = *self.input_stream_params.as_ptr();
|
||||||
p.channels = if using_voice_processing_unit {
|
p.channels = input_hw_desc.mChannelsPerFrame;
|
||||||
// VPIO is always MONO.
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
input_hw_desc.mChannelsPerFrame
|
|
||||||
};
|
|
||||||
// Input AudioUnit must be configured with device's sample rate.
|
// Input AudioUnit must be configured with device's sample rate.
|
||||||
// we will resample inside input callback.
|
// we will resample inside input callback.
|
||||||
p.rate = input_hw_desc.mSampleRate as _;
|
p.rate = input_hw_desc.mSampleRate as _;
|
||||||
|
|
@ -3633,7 +3663,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
let name = format!("input-{:p}.wav", self.stm_ptr);
|
let name = format!("input-{:p}.wav", self.stm_ptr);
|
||||||
let cname = CString::new(name).expect("OK");
|
let cname = CString::new(name).expect("OK");
|
||||||
|
|
@ -3789,7 +3819,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
let r = audio_unit_get_property(
|
let r = audio_unit_get_property(
|
||||||
self.output_unit,
|
self.output_unit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Output,
|
kAudioUnitScope_Input,
|
||||||
AU_OUT_BUS,
|
AU_OUT_BUS,
|
||||||
&mut output_hw_desc,
|
&mut output_hw_desc,
|
||||||
&mut size,
|
&mut size,
|
||||||
|
|
@ -3807,11 +3837,6 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
output_hw_desc
|
output_hw_desc
|
||||||
);
|
);
|
||||||
|
|
||||||
// In some cases with (other streams using) VPIO the stream format's mChannelsPerFrame
|
|
||||||
// is higher than expected. Use get_channel_count as source of truth.
|
|
||||||
output_hw_desc.mChannelsPerFrame =
|
|
||||||
get_channel_count(self.output_device.id, DeviceType::OUTPUT).unwrap_or(0);
|
|
||||||
|
|
||||||
// This has been observed in the wild.
|
// This has been observed in the wild.
|
||||||
if output_hw_desc.mChannelsPerFrame == 0 {
|
if output_hw_desc.mChannelsPerFrame == 0 {
|
||||||
cubeb_log!(
|
cubeb_log!(
|
||||||
|
|
@ -3827,12 +3852,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
// channels will be appended at the end of the raw data given by the output callback.
|
// channels will be appended at the end of the raw data given by the output callback.
|
||||||
let params = unsafe {
|
let params = unsafe {
|
||||||
let mut p = *self.output_stream_params.as_ptr();
|
let mut p = *self.output_stream_params.as_ptr();
|
||||||
p.channels = if using_voice_processing_unit {
|
p.channels = output_hw_desc.mChannelsPerFrame;
|
||||||
// VPIO is always MONO.
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
output_hw_desc.mChannelsPerFrame
|
|
||||||
};
|
|
||||||
if using_voice_processing_unit {
|
if using_voice_processing_unit {
|
||||||
// VPIO will always use the sample rate of the input hw for both input and output,
|
// 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).
|
// as reported to us. (We can override it but we cannot improve quality this way).
|
||||||
|
|
@ -3849,7 +3869,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
let name = format!("output-{:p}.wav", self.stm_ptr);
|
let name = format!("output-{:p}.wav", self.stm_ptr);
|
||||||
let cname = CString::new(name).expect("OK");
|
let cname = CString::new(name).expect("OK");
|
||||||
|
|
@ -4038,7 +4058,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
self.input_logging = Some(InputCallbackLogger::new());
|
self.input_logging = Some(InputCallbackLogger::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
unsafe { ffi::cubeb_audio_dump_start(self.audio_dump_session) };
|
unsafe { ffi::cubeb_audio_dump_start(self.audio_dump_session) };
|
||||||
self.audio_dump_session_running = true;
|
self.audio_dump_session_running = true;
|
||||||
|
|
@ -4217,7 +4237,7 @@ impl<'ctx> CoreStreamData<'ctx> {
|
||||||
// Return the VPIO unit if present.
|
// Return the VPIO unit if present.
|
||||||
self.voiceprocessing_unit_handle = None;
|
self.voiceprocessing_unit_handle = None;
|
||||||
|
|
||||||
#[cfg(feature = "audio_dump")]
|
#[cfg(feature = "audio-dump")]
|
||||||
{
|
{
|
||||||
if !self.audio_dump_session.is_null() {
|
if !self.audio_dump_session.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
@ -4682,6 +4702,11 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
||||||
self.core_stream_data.stop_audiounits();
|
self.core_stream_data.stop_audiounits();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.stopped.load(Ordering::SeqCst) {
|
||||||
|
// Something stopped the stream, we must not reinit.
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
!self.core_stream_data.input_unit.is_null()
|
!self.core_stream_data.input_unit.is_null()
|
||||||
|| !self.core_stream_data.output_unit.is_null()
|
|| !self.core_stream_data.output_unit.is_null()
|
||||||
|
|
@ -4840,9 +4865,8 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
||||||
// which locks a mutex inside CoreAudio framework, then this call will block the current
|
// 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
|
// thread until the callback is finished since this call asks to lock a mutex inside
|
||||||
// CoreAudio framework that is used by the data callback.
|
// CoreAudio framework that is used by the data callback.
|
||||||
if !self.stopped.load(Ordering::SeqCst) {
|
if !self.stopped.swap(true, Ordering::SeqCst) {
|
||||||
self.core_stream_data.stop_audiounits();
|
self.core_stream_data.stop_audiounits();
|
||||||
self.stopped.store(true, Ordering::SeqCst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.destroy_internal();
|
self.destroy_internal();
|
||||||
|
|
@ -4886,18 +4910,18 @@ impl<'ctx> StreamOps for AudioUnitStream<'ctx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn stop(&mut self) -> Result<()> {
|
fn stop(&mut self) -> Result<()> {
|
||||||
self.stopped.store(true, Ordering::SeqCst);
|
if !self.stopped.swap(true, Ordering::SeqCst) {
|
||||||
|
// Execute stop in serial queue to avoid racing with destroy or reinit.
|
||||||
|
self.queue
|
||||||
|
.run_sync(|| self.core_stream_data.stop_audiounits());
|
||||||
|
|
||||||
// Execute stop in serial queue to avoid racing with destroy or reinit.
|
self.notify_state_changed(State::Stopped);
|
||||||
self.queue
|
|
||||||
.run_sync(|| self.core_stream_data.stop_audiounits());
|
|
||||||
|
|
||||||
self.notify_state_changed(State::Stopped);
|
cubeb_log!(
|
||||||
|
"Cubeb stream ({:p}) stopped successfully.",
|
||||||
cubeb_log!(
|
self as *const AudioUnitStream
|
||||||
"Cubeb stream ({:p}) stopped successfully.",
|
);
|
||||||
self as *const AudioUnitStream
|
}
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn position(&mut self) -> Result<u64> {
|
fn position(&mut self) -> Result<u64> {
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ fn test_aggregate_activate_clock_drift_compensation() {
|
||||||
assert_eq!(devices.len(), compensations.len());
|
assert_eq!(devices.len(), compensations.len());
|
||||||
|
|
||||||
for (device, compensation) in zip(devices, compensations) {
|
for (device, compensation) in zip(devices, compensations) {
|
||||||
let uid = get_device_uid(device);
|
let uid = run_serially(|| get_device_uid(device));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
compensation,
|
compensation,
|
||||||
if uid == master_device_uid {
|
if uid == master_device_uid {
|
||||||
|
|
|
||||||
|
|
@ -1123,7 +1123,11 @@ fn test_get_channel_count_of_unknwon_type() {
|
||||||
|
|
||||||
fn test_channel_count(scope: Scope) {
|
fn test_channel_count(scope: Scope) {
|
||||||
if let Some(device) = test_get_default_device(scope.clone()) {
|
if let Some(device) = test_get_default_device(scope.clone()) {
|
||||||
assert!(get_channel_count(device, DeviceType::UNKNOWN).is_err());
|
assert!(run_serially_forward_panics(|| get_channel_count(
|
||||||
|
device,
|
||||||
|
DeviceType::UNKNOWN
|
||||||
|
)
|
||||||
|
.is_err()));
|
||||||
} else {
|
} else {
|
||||||
panic!("Panic by default: No device for {:?}.", scope);
|
panic!("Panic by default: No device for {:?}.", scope);
|
||||||
}
|
}
|
||||||
|
|
@ -1181,7 +1185,8 @@ fn test_get_device_presentation_latency() {
|
||||||
fn test_get_device_presentation_latencies_in_scope(scope: Scope) {
|
fn test_get_device_presentation_latencies_in_scope(scope: Scope) {
|
||||||
if let Some(device) = test_get_default_device(scope.clone()) {
|
if let Some(device) = test_get_default_device(scope.clone()) {
|
||||||
// TODO: The latencies very from devices to devices. Check nothing here.
|
// TODO: The latencies very from devices to devices. Check nothing here.
|
||||||
let latency = run_serially(|| get_fixed_latency(device, scope.clone().into()));
|
let latency =
|
||||||
|
run_serially_forward_panics(|| get_fixed_latency(device, scope.clone().into()));
|
||||||
println!(
|
println!(
|
||||||
"present latency on the device {} in scope {:?}: {}",
|
"present latency on the device {} in scope {:?}: {}",
|
||||||
device, scope, latency
|
device, scope, latency
|
||||||
|
|
@ -1197,7 +1202,7 @@ fn test_get_device_presentation_latency() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_device_group_id() {
|
fn test_get_device_group_id() {
|
||||||
if let Some(device) = test_get_default_device(Scope::Input) {
|
if let Some(device) = test_get_default_device(Scope::Input) {
|
||||||
match run_serially(|| get_device_group_id(device, DeviceType::INPUT)) {
|
match run_serially_forward_panics(|| get_device_group_id(device, DeviceType::INPUT)) {
|
||||||
Ok(id) => println!("input group id: {:?}", id),
|
Ok(id) => println!("input group id: {:?}", id),
|
||||||
Err(e) => println!("No input group id. Error: {}", e),
|
Err(e) => println!("No input group id. Error: {}", e),
|
||||||
}
|
}
|
||||||
|
|
@ -1206,7 +1211,7 @@ fn test_get_device_group_id() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(device) = test_get_default_device(Scope::Output) {
|
if let Some(device) = test_get_default_device(Scope::Output) {
|
||||||
match run_serially(|| get_device_group_id(device, DeviceType::OUTPUT)) {
|
match run_serially_forward_panics(|| get_device_group_id(device, DeviceType::OUTPUT)) {
|
||||||
Ok(id) => println!("output group id: {:?}", id),
|
Ok(id) => println!("output group id: {:?}", id),
|
||||||
Err(e) => println!("No output group id. Error: {}", e),
|
Err(e) => println!("No output group id. Error: {}", e),
|
||||||
}
|
}
|
||||||
|
|
@ -1229,8 +1234,10 @@ fn test_get_same_group_id_for_builtin_device_pairs() {
|
||||||
let mut input_group_ids = HashMap::<u32, String>::new();
|
let mut input_group_ids = HashMap::<u32, String>::new();
|
||||||
let input_devices = test_get_devices_in_scope(Scope::Input);
|
let input_devices = test_get_devices_in_scope(Scope::Input);
|
||||||
for device in input_devices.iter() {
|
for device in input_devices.iter() {
|
||||||
match run_serially(|| get_device_source(*device, DeviceType::INPUT)) {
|
match run_serially_forward_panics(|| get_device_source(*device, DeviceType::INPUT)) {
|
||||||
Ok(source) => match run_serially(|| get_device_group_id(*device, DeviceType::INPUT)) {
|
Ok(source) => match run_serially_forward_panics(|| {
|
||||||
|
get_device_group_id(*device, DeviceType::INPUT)
|
||||||
|
}) {
|
||||||
Ok(id) => assert!(input_group_ids
|
Ok(id) => assert!(input_group_ids
|
||||||
.insert(source, id.into_string().unwrap())
|
.insert(source, id.into_string().unwrap())
|
||||||
.is_none()),
|
.is_none()),
|
||||||
|
|
@ -1245,8 +1252,10 @@ fn test_get_same_group_id_for_builtin_device_pairs() {
|
||||||
let mut output_group_ids = HashMap::<u32, String>::new();
|
let mut output_group_ids = HashMap::<u32, String>::new();
|
||||||
let output_devices = test_get_devices_in_scope(Scope::Output);
|
let output_devices = test_get_devices_in_scope(Scope::Output);
|
||||||
for device in output_devices.iter() {
|
for device in output_devices.iter() {
|
||||||
match run_serially(|| get_device_source(*device, DeviceType::OUTPUT)) {
|
match run_serially_forward_panics(|| get_device_source(*device, DeviceType::OUTPUT)) {
|
||||||
Ok(source) => match run_serially(|| get_device_group_id(*device, DeviceType::OUTPUT)) {
|
Ok(source) => match run_serially_forward_panics(|| {
|
||||||
|
get_device_group_id(*device, DeviceType::OUTPUT)
|
||||||
|
}) {
|
||||||
Ok(id) => assert!(output_group_ids
|
Ok(id) => assert!(output_group_ids
|
||||||
.insert(source, id.into_string().unwrap())
|
.insert(source, id.into_string().unwrap())
|
||||||
.is_none()),
|
.is_none()),
|
||||||
|
|
@ -1286,14 +1295,16 @@ fn test_get_device_group_id_by_unknown_device() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_device_label() {
|
fn test_get_device_label() {
|
||||||
if let Some(device) = test_get_default_device(Scope::Input) {
|
if let Some(device) = test_get_default_device(Scope::Input) {
|
||||||
let name = run_serially(|| get_device_label(device, DeviceType::INPUT)).unwrap();
|
let name =
|
||||||
|
run_serially_forward_panics(|| get_device_label(device, DeviceType::INPUT)).unwrap();
|
||||||
println!("input device label: {}", name.into_string());
|
println!("input device label: {}", name.into_string());
|
||||||
} else {
|
} else {
|
||||||
println!("No input device.");
|
println!("No input device.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(device) = test_get_default_device(Scope::Output) {
|
if let Some(device) = test_get_default_device(Scope::Output) {
|
||||||
let name = run_serially(|| get_device_label(device, DeviceType::OUTPUT)).unwrap();
|
let name =
|
||||||
|
run_serially_forward_panics(|| get_device_label(device, DeviceType::OUTPUT)).unwrap();
|
||||||
println!("output device label: {}", name.into_string());
|
println!("output device label: {}", name.into_string());
|
||||||
} else {
|
} else {
|
||||||
println!("No output device.");
|
println!("No output device.");
|
||||||
|
|
@ -1316,14 +1327,14 @@ fn test_get_device_label_by_unknown_device() {
|
||||||
fn test_get_device_global_uid() {
|
fn test_get_device_global_uid() {
|
||||||
// Input device.
|
// Input device.
|
||||||
if let Some(input) = test_get_default_device(Scope::Input) {
|
if let Some(input) = test_get_default_device(Scope::Input) {
|
||||||
let uid = run_serially(|| get_device_global_uid(input)).unwrap();
|
let uid = run_serially_forward_panics(|| get_device_global_uid(input)).unwrap();
|
||||||
let uid = uid.into_string();
|
let uid = uid.into_string();
|
||||||
assert!(!uid.is_empty());
|
assert!(!uid.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output device.
|
// Output device.
|
||||||
if let Some(output) = test_get_default_device(Scope::Output) {
|
if let Some(output) = test_get_default_device(Scope::Output) {
|
||||||
let uid = run_serially(|| get_device_global_uid(output)).unwrap();
|
let uid = run_serially_forward_panics(|| get_device_global_uid(output)).unwrap();
|
||||||
let uid = uid.into_string();
|
let uid = uid.into_string();
|
||||||
assert!(!uid.is_empty());
|
assert!(!uid.is_empty());
|
||||||
}
|
}
|
||||||
|
|
@ -1333,7 +1344,7 @@ fn test_get_device_global_uid() {
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
fn test_get_device_global_uid_by_unknwon_device() {
|
fn test_get_device_global_uid_by_unknwon_device() {
|
||||||
// Unknown device.
|
// Unknown device.
|
||||||
assert!(get_device_global_uid(kAudioObjectUnknown).is_err());
|
assert!(run_serially_forward_panics(|| get_device_global_uid(kAudioObjectUnknown)).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create_cubeb_device_info
|
// create_cubeb_device_info
|
||||||
|
|
@ -1381,7 +1392,9 @@ fn test_create_cubeb_device_info() {
|
||||||
let dev_types = [DeviceType::INPUT, DeviceType::OUTPUT];
|
let dev_types = [DeviceType::INPUT, DeviceType::OUTPUT];
|
||||||
let mut results = VecDeque::new();
|
let mut results = VecDeque::new();
|
||||||
for dev_type in dev_types.iter() {
|
for dev_type in dev_types.iter() {
|
||||||
results.push_back(run_serially(|| create_cubeb_device_info(id, *dev_type)));
|
results.push_back(run_serially_forward_panics(|| {
|
||||||
|
create_cubeb_device_info(id, *dev_type)
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
@ -1441,9 +1454,11 @@ fn test_create_device_info_with_unknown_type() {
|
||||||
|
|
||||||
fn test_create_device_info_with_unknown_type_by_scope(scope: Scope) {
|
fn test_create_device_info_with_unknown_type_by_scope(scope: Scope) {
|
||||||
if let Some(device) = test_get_default_device(scope.clone()) {
|
if let Some(device) = test_get_default_device(scope.clone()) {
|
||||||
assert!(
|
assert!(run_serially_forward_panics(|| create_cubeb_device_info(
|
||||||
run_serially(|| create_cubeb_device_info(device, DeviceType::UNKNOWN)).is_err()
|
device,
|
||||||
);
|
DeviceType::UNKNOWN
|
||||||
|
))
|
||||||
|
.is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1475,7 +1490,7 @@ fn test_create_device_from_hwdev_with_inout_type() {
|
||||||
fn test_create_device_from_hwdev_with_inout_type_by_scope(scope: Scope) {
|
fn test_create_device_from_hwdev_with_inout_type_by_scope(scope: Scope) {
|
||||||
if let Some(device) = test_get_default_device(scope.clone()) {
|
if let Some(device) = test_get_default_device(scope.clone()) {
|
||||||
// Get a kAudioHardwareUnknownPropertyError in get_channel_count actually.
|
// Get a kAudioHardwareUnknownPropertyError in get_channel_count actually.
|
||||||
assert!(run_serially(|| create_cubeb_device_info(
|
assert!(run_serially_forward_panics(|| create_cubeb_device_info(
|
||||||
device,
|
device,
|
||||||
DeviceType::INPUT | DeviceType::OUTPUT
|
DeviceType::INPUT | DeviceType::OUTPUT
|
||||||
))
|
))
|
||||||
|
|
@ -1492,10 +1507,13 @@ fn test_create_device_from_hwdev_with_inout_type() {
|
||||||
fn test_get_devices_of_type() {
|
fn test_get_devices_of_type() {
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
let all_devices =
|
let all_devices = run_serially_forward_panics(|| {
|
||||||
run_serially(|| audiounit_get_devices_of_type(DeviceType::INPUT | DeviceType::OUTPUT));
|
audiounit_get_devices_of_type(DeviceType::INPUT | DeviceType::OUTPUT)
|
||||||
let input_devices = run_serially(|| audiounit_get_devices_of_type(DeviceType::INPUT));
|
});
|
||||||
let output_devices = run_serially(|| audiounit_get_devices_of_type(DeviceType::OUTPUT));
|
let input_devices =
|
||||||
|
run_serially_forward_panics(|| audiounit_get_devices_of_type(DeviceType::INPUT));
|
||||||
|
let output_devices =
|
||||||
|
run_serially_forward_panics(|| 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::ExcludeCubebAggregateAndVPIO);
|
||||||
expected_all.sort();
|
expected_all.sort();
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ extern crate itertools;
|
||||||
|
|
||||||
use self::itertools::iproduct;
|
use self::itertools::iproduct;
|
||||||
use super::utils::{
|
use super::utils::{
|
||||||
draining_data_callback, get_devices_info_in_scope, noop_data_callback,
|
draining_data_callback, get_devices_info_in_scope, noop_data_callback, state_tracking_cb,
|
||||||
test_device_channels_in_scope, test_get_default_device, test_ops_context_operation,
|
test_device_channels_in_scope, test_get_default_device, test_ops_context_operation,
|
||||||
test_ops_stream_operation, test_ops_stream_operation_on_context, Scope,
|
test_ops_stream_operation, test_ops_stream_operation_on_context, Scope, StateCallbackData,
|
||||||
};
|
};
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
@ -1177,6 +1177,77 @@ fn test_ops_stream_device_destroy() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn reiniting_and_erroring_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());
|
||||||
|
|
||||||
|
let stm = unsafe { &mut *(stream as *mut AudioUnitStream) };
|
||||||
|
|
||||||
|
// Feed silence data to output buffer
|
||||||
|
if !output_buffer.is_null() {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger an async reinit before the backend handles the error below.
|
||||||
|
// This scenario could happen in the backend's internal input callback.
|
||||||
|
stm.reinit_async();
|
||||||
|
|
||||||
|
ffi::CUBEB_ERROR.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ops_stream_racy_reinit() {
|
||||||
|
// Make sure the parameters meet the requirements of AudioUnitContext::stream_init
|
||||||
|
// (in the comments).
|
||||||
|
let mut input_params = ffi::cubeb_stream_params::default();
|
||||||
|
input_params.format = ffi::CUBEB_SAMPLE_FLOAT32NE;
|
||||||
|
input_params.rate = 48000;
|
||||||
|
input_params.channels = 1;
|
||||||
|
input_params.layout = ffi::CUBEB_LAYOUT_UNDEFINED;
|
||||||
|
input_params.prefs = ffi::CUBEB_STREAM_PREF_NONE;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
let mut data = StateCallbackData::default();
|
||||||
|
test_ops_stream_operation(
|
||||||
|
"stream: racy reinit",
|
||||||
|
ptr::null_mut(), // Use default input device.
|
||||||
|
&mut input_params,
|
||||||
|
ptr::null_mut(), // Use default output device.
|
||||||
|
&mut output_params,
|
||||||
|
4096, // TODO: Get latency by get_min_latency instead ?
|
||||||
|
Some(reiniting_and_erroring_data_callback),
|
||||||
|
Some(state_tracking_cb),
|
||||||
|
&mut data as *mut StateCallbackData as *mut c_void,
|
||||||
|
|stream| {
|
||||||
|
assert_eq!(unsafe { OPS.stream_start.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||||
|
while data.error_cnt() == 0 && data.stopped_cnt() == 0 {
|
||||||
|
thread::sleep(Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
assert_eq!(unsafe { OPS.stream_stop.unwrap()(stream) }, ffi::CUBEB_OK);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert_eq!(data.started_cnt(), 1);
|
||||||
|
assert_eq!(data.stopped_cnt(), 0);
|
||||||
|
assert_eq!(data.drained_cnt(), 0);
|
||||||
|
assert_eq!(data.error_cnt(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ops_stream_register_device_changed_callback() {
|
fn test_ops_stream_register_device_changed_callback() {
|
||||||
extern "C" fn callback(_: *mut c_void) {}
|
extern "C" fn callback(_: *mut c_void) {}
|
||||||
|
|
|
||||||
|
|
@ -441,7 +441,7 @@ fn test_stream_tester() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut params = InputProcessingParams::NONE;
|
let mut params = InputProcessingParams::NONE;
|
||||||
{
|
run_serially(|| {
|
||||||
let mut bypass = u32::from(true);
|
let mut bypass = u32::from(true);
|
||||||
let mut size: usize = mem::size_of::<u32>();
|
let mut size: usize = mem::size_of::<u32>();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
@ -477,7 +477,7 @@ fn test_stream_tester() {
|
||||||
if agc == 1 {
|
if agc == 1 {
|
||||||
params.set(InputProcessingParams::AUTOMATIC_GAIN_CONTROL, true);
|
params.set(InputProcessingParams::AUTOMATIC_GAIN_CONTROL, true);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
let mut done = false;
|
let mut done = false;
|
||||||
while !done {
|
while !done {
|
||||||
println!(
|
println!(
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,56 @@ pub extern "C" fn draining_data_callback(
|
||||||
nframes - 1
|
nframes - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct StateCallbackData {
|
||||||
|
started_cnt: AtomicU32,
|
||||||
|
stopped_cnt: AtomicU32,
|
||||||
|
drained_cnt: AtomicU32,
|
||||||
|
error_cnt: AtomicU32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StateCallbackData {
|
||||||
|
pub fn started_cnt(&self) -> u32 {
|
||||||
|
self.started_cnt.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
pub fn stopped_cnt(&self) -> u32 {
|
||||||
|
self.stopped_cnt.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
pub fn drained_cnt(&self) -> u32 {
|
||||||
|
self.drained_cnt.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
pub fn error_cnt(&self) -> u32 {
|
||||||
|
self.error_cnt.load(Ordering::SeqCst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn state_tracking_cb(
|
||||||
|
stream: *mut ffi::cubeb_stream,
|
||||||
|
_usr_ptr: *mut c_void,
|
||||||
|
state: u32,
|
||||||
|
) {
|
||||||
|
let data = unsafe { (_usr_ptr as *mut StateCallbackData).as_mut() }.unwrap();
|
||||||
|
match state {
|
||||||
|
ffi::CUBEB_STATE_STARTED => {
|
||||||
|
data.started_cnt.fetch_add(1, Ordering::SeqCst);
|
||||||
|
cubeb_log!("({:p}) state is now started", stream);
|
||||||
|
}
|
||||||
|
ffi::CUBEB_STATE_STOPPED => {
|
||||||
|
data.stopped_cnt.fetch_add(1, Ordering::SeqCst);
|
||||||
|
cubeb_log!("({:p}) state is now stopped", stream);
|
||||||
|
}
|
||||||
|
ffi::CUBEB_STATE_DRAINED => {
|
||||||
|
data.drained_cnt.fetch_add(1, Ordering::SeqCst);
|
||||||
|
cubeb_log!("({:p}) state is now drained", stream);
|
||||||
|
}
|
||||||
|
ffi::CUBEB_STATE_ERROR => {
|
||||||
|
data.error_cnt.fetch_add(1, Ordering::SeqCst);
|
||||||
|
cubeb_log!("({:p}) state is now error", stream);
|
||||||
|
}
|
||||||
|
_ => unreachable!("unknown state"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum Scope {
|
pub enum Scope {
|
||||||
Input,
|
Input,
|
||||||
|
|
@ -357,14 +407,14 @@ impl TestDeviceInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_label(id: AudioObjectID, scope: Scope) -> String {
|
fn get_label(id: AudioObjectID, scope: Scope) -> String {
|
||||||
match get_device_uid(id, scope.into()) {
|
match run_serially_forward_panics(|| get_device_uid(id, scope.into())) {
|
||||||
Ok(uid) => uid.into_string(),
|
Ok(uid) => uid.into_string(),
|
||||||
Err(status) => format!("Unknow. Error: {}", status).to_string(),
|
Err(status) => format!("Unknow. Error: {}", status).to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_uid(id: AudioObjectID, scope: Scope) -> String {
|
fn get_uid(id: AudioObjectID, scope: Scope) -> String {
|
||||||
match get_device_label(id, scope.into()) {
|
match run_serially_forward_panics(|| get_device_label(id, scope.into())) {
|
||||||
Ok(label) => label.into_string(),
|
Ok(label) => label.into_string(),
|
||||||
Err(status) => format!("Unknown. Error: {}", status).to_string(),
|
Err(status) => format!("Unknown. Error: {}", status).to_string(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"477366d58c9dc059dbe4a158a6e910f23a3e9ecac7411f73616e06375583b764","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"4bdd3962429c676eda59de96cad567478bb20b01c785c9ce3ba03b2e7837dd67","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"51dbf887e78aed5cd5e2255ac98f50c287960d8949ea3f66f2b05214b76800d8","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"dfb30ec497d6215e4535e936fea8fe3a407ef24dc1cec43b52c0ffa923d9229c","src/backend/stream.rs":"b3dcaa382981cbaa3af3c445b0ed6b5012b61d420d2e52a5ebd3cb0dd09a917c","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
|
{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"477366d58c9dc059dbe4a158a6e910f23a3e9ecac7411f73616e06375583b764","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"8a0a450ae4990e1df322464867212e48587b474dfdc7f8c270fac06980be176a","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"c0db5f2447de1d6df5aa2812fa342a085e73156a072c221c7379b9a6a9b86786","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"dfb30ec497d6215e4535e936fea8fe3a407ef24dc1cec43b52c0ffa923d9229c","src/backend/stream.rs":"dfe5b747e100cae4aeae36cf2ebb9dc4715b411b4116721a40eec2944eb0ec23","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
|
||||||
2
third_party/rust/cubeb-pulse/Cargo.toml
vendored
2
third_party/rust/cubeb-pulse/Cargo.toml
vendored
|
|
@ -24,7 +24,7 @@ crate-type = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cubeb-backend = "0.12.0"
|
cubeb-backend = "0.13"
|
||||||
ringbuf = "0.2"
|
ringbuf = "0.2"
|
||||||
semver = "1.0"
|
semver = "1.0"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -515,7 +515,7 @@ impl ContextOps for PulseContext {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn stream_init(
|
fn stream_init(
|
||||||
&mut self,
|
&mut self,
|
||||||
stream_name: Option<&CStr>,
|
stream_name: Option<&CStr>,
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ pub struct PulseStream<'ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> PulseStream<'ctx> {
|
impl<'ctx> PulseStream<'ctx> {
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::too_many_arguments))]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
context: &'ctx PulseContext,
|
context: &'ctx PulseContext,
|
||||||
stream_name: Option<&CStr>,
|
stream_name: Option<&CStr>,
|
||||||
|
|
@ -447,9 +447,9 @@ impl<'ctx> PulseStream<'ctx> {
|
||||||
latency_frames * stm.output_sample_spec.frame_size() as u32;
|
latency_frames * stm.output_sample_spec.frame_size() as u32;
|
||||||
|
|
||||||
let battr = pa_buffer_attr {
|
let battr = pa_buffer_attr {
|
||||||
maxlength: u32::max_value(),
|
maxlength: u32::MAX,
|
||||||
prebuf: u32::max_value(),
|
prebuf: u32::MAX,
|
||||||
fragsize: u32::max_value(),
|
fragsize: u32::MAX,
|
||||||
tlength: buffer_size_bytes * 2,
|
tlength: buffer_size_bytes * 2,
|
||||||
minreq: buffer_size_bytes / 4,
|
minreq: buffer_size_bytes / 4,
|
||||||
};
|
};
|
||||||
|
|
@ -490,8 +490,8 @@ impl<'ctx> PulseStream<'ctx> {
|
||||||
let buffer_size_bytes =
|
let buffer_size_bytes =
|
||||||
latency_frames * stm.input_sample_spec.frame_size() as u32;
|
latency_frames * stm.input_sample_spec.frame_size() as u32;
|
||||||
let battr = pa_buffer_attr {
|
let battr = pa_buffer_attr {
|
||||||
maxlength: u32::max_value(),
|
maxlength: u32::MAX,
|
||||||
prebuf: u32::max_value(),
|
prebuf: u32::MAX,
|
||||||
fragsize: buffer_size_bytes,
|
fragsize: buffer_size_bytes,
|
||||||
tlength: buffer_size_bytes,
|
tlength: buffer_size_bytes,
|
||||||
minreq: buffer_size_bytes,
|
minreq: buffer_size_bytes,
|
||||||
|
|
@ -1033,7 +1033,7 @@ impl<'ctx> PulseStream<'ctx> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn trigger_user_callback(&mut self, input_data: *const c_void, nbytes: usize) {
|
fn trigger_user_callback(&mut self, input_data: *const c_void, nbytes: usize) {
|
||||||
fn drained_cb(
|
fn drained_cb(
|
||||||
a: &pulse::MainloopApi,
|
a: &pulse::MainloopApi,
|
||||||
|
|
@ -1074,7 +1074,7 @@ impl<'ctx> PulseStream<'ctx> {
|
||||||
read_offset
|
read_offset
|
||||||
);
|
);
|
||||||
let read_ptr = unsafe { (input_data as *const u8).add(read_offset) };
|
let read_ptr = unsafe { (input_data as *const u8).add(read_offset) };
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(clippy::unnecessary_cast))]
|
#[allow(clippy::unnecessary_cast)]
|
||||||
let mut got = unsafe {
|
let mut got = unsafe {
|
||||||
self.data_callback.unwrap()(
|
self.data_callback.unwrap()(
|
||||||
self as *const _ as *mut _,
|
self as *const _ as *mut _,
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
2
third_party/rust/cubeb-sys/Cargo.toml
vendored
2
third_party/rust/cubeb-sys/Cargo.toml
vendored
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cubeb-sys"
|
name = "cubeb-sys"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
links = "cubeb"
|
links = "cubeb"
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ endif()
|
||||||
|
|
||||||
add_library(cubeb
|
add_library(cubeb
|
||||||
src/cubeb.c
|
src/cubeb.c
|
||||||
|
src/cubeb_audio_dump.cpp
|
||||||
src/cubeb_mixer.cpp
|
src/cubeb_mixer.cpp
|
||||||
src/cubeb_resampler.cpp
|
src/cubeb_resampler.cpp
|
||||||
src/cubeb_log.cpp
|
src/cubeb_log.cpp
|
||||||
|
|
@ -264,7 +265,7 @@ if(USE_WASAPI)
|
||||||
target_sources(cubeb PRIVATE
|
target_sources(cubeb PRIVATE
|
||||||
src/cubeb_wasapi.cpp)
|
src/cubeb_wasapi.cpp)
|
||||||
target_compile_definitions(cubeb PRIVATE USE_WASAPI)
|
target_compile_definitions(cubeb PRIVATE USE_WASAPI)
|
||||||
target_link_libraries(cubeb PRIVATE avrt ole32 ksuser)
|
target_link_libraries(cubeb PRIVATE ole32 ksuser)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_include_files("windows.h;mmsystem.h" USE_WINMM)
|
check_include_files("windows.h;mmsystem.h" USE_WINMM)
|
||||||
|
|
@ -406,6 +407,7 @@ if(BUILD_TESTS)
|
||||||
cubeb_add_test(duplex)
|
cubeb_add_test(duplex)
|
||||||
cubeb_add_test(logging)
|
cubeb_add_test(logging)
|
||||||
cubeb_add_test(triple_buffer)
|
cubeb_add_test(triple_buffer)
|
||||||
|
cubeb_add_test(audio_dump)
|
||||||
|
|
||||||
if (USE_WASAPI)
|
if (USE_WASAPI)
|
||||||
cubeb_add_test(overload_callback)
|
cubeb_add_test(overload_callback)
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ typedef enum {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
cubeb_sample_format format; /**< Requested sample format. One of
|
cubeb_sample_format format; /**< Requested sample format. One of
|
||||||
#cubeb_sample_format. */
|
#cubeb_sample_format. */
|
||||||
uint32_t rate; /**< Requested sample rate. Valid range is [1000, 192000]. */
|
uint32_t rate; /**< Requested sample rate. Valid range is [1000, 384000]. */
|
||||||
uint32_t channels; /**< Requested channel count. Valid range is [1, 8]. */
|
uint32_t channels; /**< Requested channel count. Valid range is [1, 8]. */
|
||||||
cubeb_channel_layout
|
cubeb_channel_layout
|
||||||
layout; /**< Requested channel layout. This must be consistent with the
|
layout; /**< Requested channel layout. This must be consistent with the
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ validate_stream_params(cubeb_stream_params * input_stream_params,
|
||||||
XASSERT(input_stream_params || output_stream_params);
|
XASSERT(input_stream_params || output_stream_params);
|
||||||
if (output_stream_params) {
|
if (output_stream_params) {
|
||||||
if (output_stream_params->rate < 1000 ||
|
if (output_stream_params->rate < 1000 ||
|
||||||
output_stream_params->rate > 192000 ||
|
output_stream_params->rate > 768000 ||
|
||||||
output_stream_params->channels < 1 ||
|
output_stream_params->channels < 1 ||
|
||||||
output_stream_params->channels > UINT8_MAX) {
|
output_stream_params->channels > UINT8_MAX) {
|
||||||
return CUBEB_ERROR_INVALID_FORMAT;
|
return CUBEB_ERROR_INVALID_FORMAT;
|
||||||
|
|
@ -103,7 +103,7 @@ validate_stream_params(cubeb_stream_params * input_stream_params,
|
||||||
}
|
}
|
||||||
if (input_stream_params) {
|
if (input_stream_params) {
|
||||||
if (input_stream_params->rate < 1000 ||
|
if (input_stream_params->rate < 1000 ||
|
||||||
input_stream_params->rate > 192000 ||
|
input_stream_params->rate > 768000 ||
|
||||||
input_stream_params->channels < 1 ||
|
input_stream_params->channels < 1 ||
|
||||||
input_stream_params->channels > UINT8_MAX) {
|
input_stream_params->channels > UINT8_MAX) {
|
||||||
return CUBEB_ERROR_INVALID_FORMAT;
|
return CUBEB_ERROR_INVALID_FORMAT;
|
||||||
|
|
@ -533,7 +533,7 @@ int
|
||||||
cubeb_stream_set_input_processing_params(cubeb_stream * stream,
|
cubeb_stream_set_input_processing_params(cubeb_stream * stream,
|
||||||
cubeb_input_processing_params params)
|
cubeb_input_processing_params params)
|
||||||
{
|
{
|
||||||
if (!stream || !params) {
|
if (!stream) {
|
||||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,13 +244,24 @@ shutdown_with_error(cubeb_stream * stm)
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t poll_frequency_ns = NS_PER_S * stm->out_frame_size / stm->sample_rate;
|
int64_t poll_frequency_ns = NS_PER_S * stm->out_frame_size / stm->sample_rate;
|
||||||
|
int rv;
|
||||||
if (stm->istream) {
|
if (stm->istream) {
|
||||||
wait_for_state_change(stm->istream, AAUDIO_STREAM_STATE_STOPPED,
|
rv = wait_for_state_change(stm->istream, AAUDIO_STREAM_STATE_STOPPED,
|
||||||
poll_frequency_ns);
|
poll_frequency_ns);
|
||||||
|
if (rv != CUBEB_OK) {
|
||||||
|
LOG("Failure when waiting for stream change on the input side when "
|
||||||
|
"shutting down in error");
|
||||||
|
// Not much we can do, carry on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (stm->ostream) {
|
if (stm->ostream) {
|
||||||
wait_for_state_change(stm->ostream, AAUDIO_STREAM_STATE_STOPPED,
|
rv = wait_for_state_change(stm->ostream, AAUDIO_STREAM_STATE_STOPPED,
|
||||||
poll_frequency_ns);
|
poll_frequency_ns);
|
||||||
|
if (rv != CUBEB_OK) {
|
||||||
|
LOG("Failure when waiting for stream change on the output side when "
|
||||||
|
"shutting down in error");
|
||||||
|
// Not much we can do, carry on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!stm->in_data_callback.load());
|
assert(!stm->in_data_callback.load());
|
||||||
|
|
@ -920,7 +931,7 @@ aaudio_error_cb(AAudioStream * astream, void * user_data, aaudio_result_t error)
|
||||||
assert(stm->ostream == astream || stm->istream == astream);
|
assert(stm->ostream == astream || stm->istream == astream);
|
||||||
|
|
||||||
// Device change -- reinitialize on the new default device.
|
// Device change -- reinitialize on the new default device.
|
||||||
if (error == AAUDIO_ERROR_DISCONNECTED) {
|
if (error == AAUDIO_ERROR_DISCONNECTED || error == AAUDIO_ERROR_TIMEOUT) {
|
||||||
LOG("Audio device change, reinitializing stream");
|
LOG("Audio device change, reinitializing stream");
|
||||||
reinitialize_stream(stm);
|
reinitialize_stream(stm);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
231
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audio_dump.cpp
vendored
Normal file
231
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audio_dump.cpp
vendored
Normal file
|
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2023 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* This program is made available under an ISC-style license. See the
|
||||||
|
* accompanying file LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
|
||||||
|
#include "cubeb_audio_dump.h"
|
||||||
|
#include "cubeb/cubeb.h"
|
||||||
|
#include "cubeb_ringbuffer.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <limits>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::thread;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
bytes_per_sample(cubeb_stream_params params)
|
||||||
|
{
|
||||||
|
switch (params.format) {
|
||||||
|
case CUBEB_SAMPLE_S16LE:
|
||||||
|
case CUBEB_SAMPLE_S16BE:
|
||||||
|
return sizeof(int16_t);
|
||||||
|
case CUBEB_SAMPLE_FLOAT32LE:
|
||||||
|
case CUBEB_SAMPLE_FLOAT32BE:
|
||||||
|
return sizeof(float);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cubeb_audio_dump_stream {
|
||||||
|
public:
|
||||||
|
explicit cubeb_audio_dump_stream(cubeb_stream_params params)
|
||||||
|
: sample_size(bytes_per_sample(params)),
|
||||||
|
ringbuffer(
|
||||||
|
static_cast<int>(params.rate * params.channels * sample_size))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int open(const char * name)
|
||||||
|
{
|
||||||
|
file = fopen(name, "wb");
|
||||||
|
if (!file) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
int close()
|
||||||
|
{
|
||||||
|
if (fclose(file)) {
|
||||||
|
return CUBEB_ERROR;
|
||||||
|
}
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Directly write to the file. Useful to write the header.
|
||||||
|
size_t write(uint8_t * data, uint32_t count)
|
||||||
|
{
|
||||||
|
return fwrite(data, count, 1, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t write_all()
|
||||||
|
{
|
||||||
|
size_t written = 0;
|
||||||
|
const int buf_sz = 16 * 1024;
|
||||||
|
uint8_t buf[buf_sz];
|
||||||
|
while (int rv = ringbuffer.dequeue(buf, buf_sz)) {
|
||||||
|
written += fwrite(buf, rv, 1, file);
|
||||||
|
}
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
int dump(void * samples, uint32_t count)
|
||||||
|
{
|
||||||
|
int bytes = static_cast<int>(count * sample_size);
|
||||||
|
int rv = ringbuffer.enqueue(static_cast<uint8_t *>(samples), bytes);
|
||||||
|
return rv == bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t sample_size;
|
||||||
|
FILE * file{};
|
||||||
|
lock_free_queue<uint8_t> ringbuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cubeb_audio_dump_session {
|
||||||
|
public:
|
||||||
|
cubeb_audio_dump_session() = default;
|
||||||
|
~cubeb_audio_dump_session()
|
||||||
|
{
|
||||||
|
assert(streams.empty());
|
||||||
|
session_thread.join();
|
||||||
|
}
|
||||||
|
cubeb_audio_dump_session(const cubeb_audio_dump_session &) = delete;
|
||||||
|
cubeb_audio_dump_session &
|
||||||
|
operator=(const cubeb_audio_dump_session &) = delete;
|
||||||
|
cubeb_audio_dump_session & operator=(cubeb_audio_dump_session &&) = delete;
|
||||||
|
|
||||||
|
cubeb_audio_dump_stream_t create_stream(cubeb_stream_params params,
|
||||||
|
const char * name)
|
||||||
|
{
|
||||||
|
if (running) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto * stream = new cubeb_audio_dump_stream(params);
|
||||||
|
streams.push_back(stream);
|
||||||
|
int rv = stream->open(name);
|
||||||
|
if (rv != CUBEB_OK) {
|
||||||
|
delete stream;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct riff_header {
|
||||||
|
char chunk_id[4] = {'R', 'I', 'F', 'F'};
|
||||||
|
int32_t chunk_size = 0;
|
||||||
|
char format[4] = {'W', 'A', 'V', 'E'};
|
||||||
|
|
||||||
|
char subchunk_id_1[4] = {'f', 'm', 't', 0x20};
|
||||||
|
int32_t subchunk_1_size = 16;
|
||||||
|
int16_t audio_format{};
|
||||||
|
int16_t num_channels{};
|
||||||
|
int32_t sample_rate{};
|
||||||
|
int32_t byte_rate{};
|
||||||
|
int16_t block_align{};
|
||||||
|
int16_t bits_per_sample{};
|
||||||
|
|
||||||
|
char subchunk_id_2[4] = {'d', 'a', 't', 'a'};
|
||||||
|
int32_t subchunkd_2_size = std::numeric_limits<int32_t>::max();
|
||||||
|
};
|
||||||
|
|
||||||
|
riff_header header;
|
||||||
|
// 1 is integer PCM, 3 is float PCM
|
||||||
|
header.audio_format = bytes_per_sample(params) == 2 ? 1 : 3;
|
||||||
|
header.num_channels = params.channels;
|
||||||
|
header.sample_rate = params.rate;
|
||||||
|
header.byte_rate = bytes_per_sample(params) * params.rate * params.channels;
|
||||||
|
header.block_align = params.channels * bytes_per_sample(params);
|
||||||
|
header.bits_per_sample = bytes_per_sample(params) * 8;
|
||||||
|
|
||||||
|
stream->write(reinterpret_cast<uint8_t *>(&header), sizeof(riff_header));
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
int delete_stream(cubeb_audio_dump_stream * stream)
|
||||||
|
{
|
||||||
|
assert(!running);
|
||||||
|
stream->close();
|
||||||
|
streams.erase(std::remove(streams.begin(), streams.end(), stream),
|
||||||
|
streams.end());
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
int start()
|
||||||
|
{
|
||||||
|
assert(!running);
|
||||||
|
running = true;
|
||||||
|
session_thread = std::thread([this] {
|
||||||
|
while (running) {
|
||||||
|
for (auto * stream : streams) {
|
||||||
|
stream->write_all();
|
||||||
|
}
|
||||||
|
const int DUMP_INTERVAL = 10;
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(DUMP_INTERVAL));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
int stop()
|
||||||
|
{
|
||||||
|
assert(running);
|
||||||
|
running = false;
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
thread session_thread;
|
||||||
|
vector<cubeb_audio_dump_stream_t> streams{};
|
||||||
|
std::atomic<bool> running = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_init(cubeb_audio_dump_session_t * session)
|
||||||
|
{
|
||||||
|
*session = new cubeb_audio_dump_session;
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_shutdown(cubeb_audio_dump_session_t session)
|
||||||
|
{
|
||||||
|
delete session;
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stream_init(cubeb_audio_dump_session_t session,
|
||||||
|
cubeb_audio_dump_stream_t * stream,
|
||||||
|
cubeb_stream_params stream_params,
|
||||||
|
const char * name)
|
||||||
|
{
|
||||||
|
*stream = session->create_stream(stream_params, name);
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stream_shutdown(cubeb_audio_dump_session_t session,
|
||||||
|
cubeb_audio_dump_stream_t stream)
|
||||||
|
{
|
||||||
|
return session->delete_stream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_start(cubeb_audio_dump_session_t session)
|
||||||
|
{
|
||||||
|
return session->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stop(cubeb_audio_dump_session_t session)
|
||||||
|
{
|
||||||
|
return session->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_write(cubeb_audio_dump_stream_t stream, void * audio_samples,
|
||||||
|
uint32_t count)
|
||||||
|
{
|
||||||
|
stream->dump(audio_samples, count);
|
||||||
|
return CUBEB_OK;
|
||||||
|
}
|
||||||
108
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audio_dump.h
vendored
Normal file
108
third_party/rust/cubeb-sys/libcubeb/src/cubeb_audio_dump.h
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2023 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* This program is made available under an ISC-style license. See the
|
||||||
|
* accompanying file LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CUBEB_AUDIO_DUMP
|
||||||
|
#define CUBEB_AUDIO_DUMP
|
||||||
|
|
||||||
|
#include "cubeb/cubeb.h"
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct cubeb_audio_dump_stream * cubeb_audio_dump_stream_t;
|
||||||
|
typedef struct cubeb_audio_dump_session * cubeb_audio_dump_session_t;
|
||||||
|
|
||||||
|
// Start audio dumping session
|
||||||
|
// This can only be called if the other API functions
|
||||||
|
// aren't currently being called: synchronized externally.
|
||||||
|
// This is not real-time safe.
|
||||||
|
//
|
||||||
|
// This is generally called when deciding to start logging some audio.
|
||||||
|
//
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_init(cubeb_audio_dump_session_t * session);
|
||||||
|
|
||||||
|
// End audio dumping session
|
||||||
|
// This can only be called if the other API functions
|
||||||
|
// aren't currently being called: synchronized externally.
|
||||||
|
//
|
||||||
|
// This is generally called when deciding to stop logging some audio.
|
||||||
|
//
|
||||||
|
// This is not real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_shutdown(cubeb_audio_dump_session_t session);
|
||||||
|
|
||||||
|
// Register a stream for dumping to a file
|
||||||
|
// This can only be called if cubeb_audio_dump_write
|
||||||
|
// isn't currently being called: synchronized externally.
|
||||||
|
//
|
||||||
|
// This is generally called when setting up a system-level stream side (either
|
||||||
|
// input or output).
|
||||||
|
//
|
||||||
|
// This is not real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stream_init(cubeb_audio_dump_session_t session,
|
||||||
|
cubeb_audio_dump_stream_t * stream,
|
||||||
|
cubeb_stream_params stream_params,
|
||||||
|
const char * name);
|
||||||
|
|
||||||
|
// Unregister a stream for dumping to a file
|
||||||
|
// This can only be called if cubeb_audio_dump_write
|
||||||
|
// isn't currently being called: synchronized externally.
|
||||||
|
//
|
||||||
|
// This is generally called when a system-level audio stream side
|
||||||
|
// (input/output) has been stopped and drained, and the audio callback isn't
|
||||||
|
// going to be called.
|
||||||
|
//
|
||||||
|
// This is not real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stream_shutdown(cubeb_audio_dump_session_t session,
|
||||||
|
cubeb_audio_dump_stream_t stream);
|
||||||
|
|
||||||
|
// Start dumping.
|
||||||
|
// cubeb_audio_dump_write can now be called.
|
||||||
|
//
|
||||||
|
// This starts dumping the audio to disk. Generally this is called when
|
||||||
|
// cubeb_stream_start is caled is called, but can be called at the beginning of
|
||||||
|
// the application.
|
||||||
|
//
|
||||||
|
// This is not real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_start(cubeb_audio_dump_session_t session);
|
||||||
|
|
||||||
|
// Stop dumping.
|
||||||
|
// cubeb_audio_dump_write can't be called at this point.
|
||||||
|
//
|
||||||
|
// This stops dumping the audio to disk cubeb_stream_stop is caled is called,
|
||||||
|
// but can be called before exiting the application.
|
||||||
|
//
|
||||||
|
// This is not real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_stop(cubeb_audio_dump_session_t session);
|
||||||
|
|
||||||
|
// Dump some audio samples for audio stream id.
|
||||||
|
//
|
||||||
|
// This is generally called from the real-time audio callback.
|
||||||
|
//
|
||||||
|
// This is real-time safe.
|
||||||
|
// Returns 0 in case of success.
|
||||||
|
int
|
||||||
|
cubeb_audio_dump_write(cubeb_audio_dump_stream_t stream, void * audio_samples,
|
||||||
|
uint32_t count);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -377,6 +377,15 @@ cubeb_channel_to_channel_label(cubeb_channel channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_common_sample_rate(Float64 sample_rate)
|
||||||
|
{
|
||||||
|
/* Some commonly used sample rates and their multiples and divisors. */
|
||||||
|
return sample_rate == 8000 || sample_rate == 16000 || sample_rate == 22050 ||
|
||||||
|
sample_rate == 32000 || sample_rate == 44100 || sample_rate == 48000 ||
|
||||||
|
sample_rate == 88200 || sample_rate == 96000;
|
||||||
|
}
|
||||||
|
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
typedef UInt32 AudioDeviceID;
|
typedef UInt32 AudioDeviceID;
|
||||||
typedef UInt32 AudioObjectID;
|
typedef UInt32 AudioObjectID;
|
||||||
|
|
@ -2502,6 +2511,12 @@ audiounit_configure_output(cubeb_stream * stm)
|
||||||
return CUBEB_ERROR;
|
return CUBEB_ERROR;
|
||||||
}
|
}
|
||||||
stm->output_hw_rate = output_hw_desc.mSampleRate;
|
stm->output_hw_rate = output_hw_desc.mSampleRate;
|
||||||
|
if (!is_common_sample_rate(stm->output_desc.mSampleRate)) {
|
||||||
|
/* For uncommon sample rates, we may run into issues with the OS
|
||||||
|
resampler if we don't do the resampling ourselves, so set the
|
||||||
|
AudioUnit sample rate to the hardware rate and resample. */
|
||||||
|
stm->output_desc.mSampleRate = stm->output_hw_rate;
|
||||||
|
}
|
||||||
LOG("(%p) Output device sampling rate: %.2f", stm,
|
LOG("(%p) Output device sampling rate: %.2f", stm,
|
||||||
output_hw_desc.mSampleRate);
|
output_hw_desc.mSampleRate);
|
||||||
stm->context->channels = output_hw_desc.mChannelsPerFrame;
|
stm->context->channels = output_hw_desc.mChannelsPerFrame;
|
||||||
|
|
@ -2709,11 +2724,16 @@ audiounit_setup_stream(cubeb_stream * stm)
|
||||||
input_unconverted_params.rate = stm->input_hw_rate;
|
input_unconverted_params.rate = stm->input_hw_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create resampler. Output params are unchanged
|
cubeb_stream_params output_unconverted_params;
|
||||||
* because we do not need conversion on the output. */
|
if (has_output(stm)) {
|
||||||
|
output_unconverted_params = stm->output_stream_params;
|
||||||
|
output_unconverted_params.rate = stm->output_desc.mSampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create resampler. */
|
||||||
stm->resampler.reset(cubeb_resampler_create(
|
stm->resampler.reset(cubeb_resampler_create(
|
||||||
stm, has_input(stm) ? &input_unconverted_params : NULL,
|
stm, has_input(stm) ? &input_unconverted_params : NULL,
|
||||||
has_output(stm) ? &stm->output_stream_params : NULL, target_sample_rate,
|
has_output(stm) ? &output_unconverted_params : NULL, target_sample_rate,
|
||||||
stm->data_callback, stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
stm->data_callback, stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DESKTOP,
|
||||||
CUBEB_RESAMPLER_RECLOCK_NONE));
|
CUBEB_RESAMPLER_RECLOCK_NONE));
|
||||||
if (!stm->resampler) {
|
if (!stm->resampler) {
|
||||||
|
|
|
||||||
|
|
@ -204,6 +204,11 @@ struct auto_stream_ref {
|
||||||
cubeb_stream * stm;
|
cubeb_stream * stm;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using set_mm_thread_characteristics_function =
|
||||||
|
decltype(&AvSetMmThreadCharacteristicsW);
|
||||||
|
using revert_mm_thread_characteristics_function =
|
||||||
|
decltype(&AvRevertMmThreadCharacteristics);
|
||||||
|
|
||||||
extern cubeb_ops const wasapi_ops;
|
extern cubeb_ops const wasapi_ops;
|
||||||
|
|
||||||
static com_heap_ptr<wchar_t>
|
static com_heap_ptr<wchar_t>
|
||||||
|
|
@ -301,6 +306,13 @@ struct cubeb {
|
||||||
nullptr;
|
nullptr;
|
||||||
void * output_collection_changed_user_ptr = nullptr;
|
void * output_collection_changed_user_ptr = nullptr;
|
||||||
UINT64 performance_counter_frequency;
|
UINT64 performance_counter_frequency;
|
||||||
|
/* Library dynamically opened to increase the render thread priority, and
|
||||||
|
the two function pointers we need. */
|
||||||
|
HMODULE mmcss_module = nullptr;
|
||||||
|
set_mm_thread_characteristics_function set_mm_thread_characteristics =
|
||||||
|
nullptr;
|
||||||
|
revert_mm_thread_characteristics_function revert_mm_thread_characteristics =
|
||||||
|
nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wasapi_endpoint_notification_client;
|
class wasapi_endpoint_notification_client;
|
||||||
|
|
@ -1401,7 +1413,8 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||||
|
|
||||||
/* We could consider using "Pro Audio" here for WebAudio and
|
/* We could consider using "Pro Audio" here for WebAudio and
|
||||||
maybe WebRTC. */
|
maybe WebRTC. */
|
||||||
mmcss_handle = AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index);
|
mmcss_handle =
|
||||||
|
stm->context->set_mm_thread_characteristics(L"Audio", &mmcss_task_index);
|
||||||
if (!mmcss_handle) {
|
if (!mmcss_handle) {
|
||||||
/* This is not fatal, but we might glitch under heavy load. */
|
/* This is not fatal, but we might glitch under heavy load. */
|
||||||
LOG("Unable to use mmcss to bump the render thread priority: %lx",
|
LOG("Unable to use mmcss to bump the render thread priority: %lx",
|
||||||
|
|
@ -1509,7 +1522,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mmcss_handle) {
|
if (mmcss_handle) {
|
||||||
AvRevertMmThreadCharacteristics(mmcss_handle);
|
stm->context->revert_mm_thread_characteristics(mmcss_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
|
@ -1522,6 +1535,18 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||||
void
|
void
|
||||||
wasapi_destroy(cubeb * context);
|
wasapi_destroy(cubeb * context);
|
||||||
|
|
||||||
|
HANDLE WINAPI
|
||||||
|
set_mm_thread_characteristics_noop(LPCWSTR, LPDWORD mmcss_task_index)
|
||||||
|
{
|
||||||
|
return (HANDLE)1;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI
|
||||||
|
revert_mm_thread_characteristics_noop(HANDLE mmcss_handle)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT
|
HRESULT
|
||||||
register_notification_client(cubeb_stream * stm)
|
register_notification_client(cubeb_stream * stm)
|
||||||
{
|
{
|
||||||
|
|
@ -1757,6 +1782,31 @@ wasapi_init(cubeb ** context, char const * context_name)
|
||||||
ctx->performance_counter_frequency = 0;
|
ctx->performance_counter_frequency = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx->mmcss_module = LoadLibraryW(L"Avrt.dll");
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
if (ctx->mmcss_module) {
|
||||||
|
ctx->set_mm_thread_characteristics =
|
||||||
|
reinterpret_cast<set_mm_thread_characteristics_function>(
|
||||||
|
GetProcAddress(ctx->mmcss_module, "AvSetMmThreadCharacteristicsW"));
|
||||||
|
ctx->revert_mm_thread_characteristics =
|
||||||
|
reinterpret_cast<revert_mm_thread_characteristics_function>(
|
||||||
|
GetProcAddress(ctx->mmcss_module,
|
||||||
|
"AvRevertMmThreadCharacteristics"));
|
||||||
|
success = ctx->set_mm_thread_characteristics &&
|
||||||
|
ctx->revert_mm_thread_characteristics;
|
||||||
|
}
|
||||||
|
if (!success) {
|
||||||
|
// This is not a fatal error, but we might end up glitching when
|
||||||
|
// the system is under high load.
|
||||||
|
LOG("Could not load avrt.dll or fetch AvSetMmThreadCharacteristicsW "
|
||||||
|
"AvRevertMmThreadCharacteristics: %lx",
|
||||||
|
GetLastError());
|
||||||
|
ctx->set_mm_thread_characteristics = &set_mm_thread_characteristics_noop;
|
||||||
|
ctx->revert_mm_thread_characteristics =
|
||||||
|
&revert_mm_thread_characteristics_noop;
|
||||||
|
}
|
||||||
|
|
||||||
*context = ctx;
|
*context = ctx;
|
||||||
|
|
||||||
return CUBEB_OK;
|
return CUBEB_OK;
|
||||||
|
|
@ -1813,6 +1863,10 @@ wasapi_destroy(cubeb * context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (context->mmcss_module) {
|
||||||
|
FreeLibrary(context->mmcss_module);
|
||||||
|
}
|
||||||
|
|
||||||
delete context;
|
delete context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
74
third_party/rust/cubeb-sys/libcubeb/test/test_audio_dump.cpp
vendored
Normal file
74
third_party/rust/cubeb-sys/libcubeb/test/test_audio_dump.cpp
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2023 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* This program is made available under an ISC-style license. See the
|
||||||
|
* accompanying file LICENSE for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
|
||||||
|
#include "cubeb/cubeb.h"
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
|
#include "cubeb_audio_dump.h"
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include <chrono>
|
||||||
|
#include <cmath>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
TEST(cubeb, audio_dump)
|
||||||
|
{
|
||||||
|
cubeb_audio_dump_session_t session;
|
||||||
|
int rv = cubeb_audio_dump_init(&session);
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
cubeb_stream_params params;
|
||||||
|
params.rate = 44100;
|
||||||
|
params.channels = 2;
|
||||||
|
params.format = CUBEB_SAMPLE_FLOAT32NE;
|
||||||
|
|
||||||
|
cubeb_audio_dump_stream_t dump_stream;
|
||||||
|
rv = cubeb_audio_dump_stream_init(session, &dump_stream, params, "test.wav");
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
rv = cubeb_audio_dump_start(session);
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
float phase = 0;
|
||||||
|
const size_t buf_sz = 2 * 44100 / 50;
|
||||||
|
float buf[buf_sz];
|
||||||
|
for (uint32_t iteration = 0; iteration < 50; iteration++) {
|
||||||
|
uint32_t write_idx = 0;
|
||||||
|
for (uint32_t i = 0; i < buf_sz / params.channels; i++) {
|
||||||
|
for (uint32_t j = 0; j < params.channels; j++) {
|
||||||
|
buf[write_idx++] = sin(phase);
|
||||||
|
}
|
||||||
|
phase += 440 * M_PI * 2 / 44100;
|
||||||
|
if (phase > 2 * M_PI) {
|
||||||
|
phase -= 2 * M_PI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rv = cubeb_audio_dump_write(dump_stream, buf, 2 * 44100 / 50);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
|
rv = cubeb_audio_dump_stop(session);
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
rv = cubeb_audio_dump_stream_shutdown(session, dump_stream);
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
rv = cubeb_audio_dump_shutdown(session);
|
||||||
|
ASSERT_EQ(rv, 0);
|
||||||
|
|
||||||
|
std::ifstream file("test.wav");
|
||||||
|
ASSERT_TRUE(file.good());
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef NOMINMAX
|
||||||
|
|
@ -201,6 +201,7 @@ TEST(cubeb, duplex_collection_change)
|
||||||
ASSERT_EQ(r, CUBEB_OK);
|
ASSERT_EQ(r, CUBEB_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GTEST_HAS_DEATH_TEST
|
||||||
TEST(cubeb, duplex_collection_change_no_unregister)
|
TEST(cubeb, duplex_collection_change_no_unregister)
|
||||||
{
|
{
|
||||||
cubeb * ctx;
|
cubeb * ctx;
|
||||||
|
|
@ -221,6 +222,7 @@ TEST(cubeb, duplex_collection_change_no_unregister)
|
||||||
|
|
||||||
duplex_collection_change_impl(ctx);
|
duplex_collection_change_impl(ctx);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
long
|
long
|
||||||
data_cb_input(cubeb_stream * stream, void * user, const void * inputbuffer,
|
data_cb_input(cubeb_stream * stream, void * user, const void * inputbuffer,
|
||||||
|
|
|
||||||
35
third_party/rust/cubeb-sys/src/audio_dump.rs
vendored
Normal file
35
third_party/rust/cubeb-sys/src/audio_dump.rs
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright © 2017-2023 Mozilla Foundation
|
||||||
|
//
|
||||||
|
// This program is made available under an ISC-style license. See the
|
||||||
|
// accompanying file LICENSE for details.
|
||||||
|
|
||||||
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
|
use stream::cubeb_stream_params;
|
||||||
|
|
||||||
|
pub enum cubeb_audio_dump_stream {}
|
||||||
|
pub enum cubeb_audio_dump_session {}
|
||||||
|
pub type cubeb_audio_dump_stream_t = *mut cubeb_audio_dump_stream;
|
||||||
|
pub type cubeb_audio_dump_session_t = *mut cubeb_audio_dump_session;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
pub fn cubeb_audio_dump_init(session: *mut cubeb_audio_dump_session_t) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_shutdown(session: cubeb_audio_dump_session_t) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_stream_init(
|
||||||
|
session: cubeb_audio_dump_session_t,
|
||||||
|
stream: *mut cubeb_audio_dump_stream_t,
|
||||||
|
stream_params: cubeb_stream_params,
|
||||||
|
name: *const c_char,
|
||||||
|
) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_stream_shutdown(
|
||||||
|
session: cubeb_audio_dump_session_t,
|
||||||
|
stream: cubeb_audio_dump_stream_t,
|
||||||
|
) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_start(session: cubeb_audio_dump_session_t) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_stop(session: cubeb_audio_dump_session_t) -> c_int;
|
||||||
|
pub fn cubeb_audio_dump_write(
|
||||||
|
stream: cubeb_audio_dump_stream_t,
|
||||||
|
audio_samples: *mut c_void,
|
||||||
|
count: u32,
|
||||||
|
) -> c_int;
|
||||||
|
|
||||||
|
}
|
||||||
2
third_party/rust/cubeb-sys/src/lib.rs
vendored
2
third_party/rust/cubeb-sys/src/lib.rs
vendored
|
|
@ -8,6 +8,7 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
|
mod audio_dump;
|
||||||
mod callbacks;
|
mod callbacks;
|
||||||
mod channel;
|
mod channel;
|
||||||
mod context;
|
mod context;
|
||||||
|
|
@ -19,6 +20,7 @@ mod mixer;
|
||||||
mod resampler;
|
mod resampler;
|
||||||
mod stream;
|
mod stream;
|
||||||
|
|
||||||
|
pub use audio_dump::*;
|
||||||
pub use callbacks::*;
|
pub use callbacks::*;
|
||||||
pub use channel::*;
|
pub use channel::*;
|
||||||
pub use context::*;
|
pub use context::*;
|
||||||
|
|
|
||||||
2
third_party/rust/cubeb/.cargo-checksum.json
vendored
2
third_party/rust/cubeb/.cargo-checksum.json
vendored
|
|
@ -1 +1 @@
|
||||||
{"files":{"Cargo.lock":"d3b573eee37b0b0f709f168d4026071803c499f8c0d3efb830367d762c40754f","Cargo.toml":"8b0bd9b5b8f74492a893f3281dd14ca6ebd0f47ce3368c9927f16b76498fc340","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"3363405f3d21ad120617473a0288c337a7b15eb79f5bb1035cfd258bd9bedf2b","examples/devices.rs":"ff5dcd588e7036165c4b4c20ec355d036e0ae90cf88b3b0f5cd86621fe2ce61d","examples/tone.rs":"8f5f9851b6d99f6f16c597fcb9312e3ef81769cbfb89341d2ea2522ca2e2214e","src/context.rs":"176f0923c13245acdc3934f649608fea1c17ad254daa3396d8929f38374e932e","src/frame.rs":"649cedaa2e9e1c5d2c3146bd0d66fd28bb230e68142493a9ea7dbab4a15f5adc","src/lib.rs":"58c78cad9541ebaef0ea96c67bc1db7d25e68e4e3d2f9a90f371c473e25c181f","src/sample.rs":"0d4645cc1d6ac26f198f6f59a44e193422e5646ecef0de46224653bef79d1a10","src/stream.rs":"0f51eab71d08685afdd0e748b85513541b9a612da1cad329c8c897dc0f79607c"},"package":"6db57570f2617f0214c11721e8d2325816d9dc936c2c472661ac5d90a30fba98"}
|
{"files":{"Cargo.lock":"d86a793ee92e01a15c886f5f73c9823eead21298f88455fa71717aeefa9b1af3","Cargo.toml":"4642a8d5f6fce1799a16b9e43d326e5aee5b886f51c2dded8617c6d6b659f81c","LICENSE":"8c044baa5d883274736eeece0b955249076c2697b826e576fce59496235b2cf5","README.md":"408c573ec240927cf5b9c036098e94e374ec41f71991415422586f450586b214","examples/common/mod.rs":"3363405f3d21ad120617473a0288c337a7b15eb79f5bb1035cfd258bd9bedf2b","examples/devices.rs":"ff5dcd588e7036165c4b4c20ec355d036e0ae90cf88b3b0f5cd86621fe2ce61d","examples/tone.rs":"8f5f9851b6d99f6f16c597fcb9312e3ef81769cbfb89341d2ea2522ca2e2214e","src/context.rs":"176f0923c13245acdc3934f649608fea1c17ad254daa3396d8929f38374e932e","src/frame.rs":"649cedaa2e9e1c5d2c3146bd0d66fd28bb230e68142493a9ea7dbab4a15f5adc","src/lib.rs":"58c78cad9541ebaef0ea96c67bc1db7d25e68e4e3d2f9a90f371c473e25c181f","src/sample.rs":"a8ed35c007541722e4322df82035086f160072ce549b34a73d54052148bcae07","src/stream.rs":"0f51eab71d08685afdd0e748b85513541b9a612da1cad329c8c897dc0f79607c"},"package":"3d105547cf8036cdb30e796ce0d06832af4766106a44574402fa2fd3c861a042"}
|
||||||
18
third_party/rust/cubeb/Cargo.lock
generated
vendored
18
third_party/rust/cubeb/Cargo.lock
generated
vendored
|
|
@ -10,9 +10,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.79"
|
version = "1.0.97"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
|
|
@ -25,16 +25,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb"
|
name = "cubeb"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cubeb-core",
|
"cubeb-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-core"
|
name = "cubeb-core"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2380c03a7df0ea3744f6a210d6340f423935e53cbf2fd68ada84b5e808e46ac7"
|
checksum = "ac08d314dd1ec6d41d9ccdeec70899c98ed3b89845367000dd6096099481bc73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cubeb-sys",
|
"cubeb-sys",
|
||||||
|
|
@ -42,9 +42,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cubeb-sys"
|
name = "cubeb-sys"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c20c457d7b34dad6e0c1a9c759c96b4420b9e9917a572998b81835799a07e1d"
|
checksum = "26073cd50c7b6ba4272204839f56921557609a0d67e092882cbb903df94cab39"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cmake",
|
"cmake",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
|
@ -52,6 +52,6 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.27"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||||
|
|
|
||||||
4
third_party/rust/cubeb/Cargo.toml
vendored
4
third_party/rust/cubeb/Cargo.toml
vendored
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "cubeb"
|
name = "cubeb"
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
authors = ["Dan Glastonbury <dglastonbury@mozilla.com>"]
|
||||||
description = """
|
description = """
|
||||||
Bindings to libcubeb for interacting with system audio from rust.
|
Bindings to libcubeb for interacting with system audio from rust.
|
||||||
|
|
@ -24,7 +24,7 @@ license = "ISC"
|
||||||
repository = "https://github.com/mozilla/cubeb-rs"
|
repository = "https://github.com/mozilla/cubeb-rs"
|
||||||
|
|
||||||
[dependencies.cubeb-core]
|
[dependencies.cubeb-core]
|
||||||
version = "0.12.0"
|
version = "0.13.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
gecko-in-tree = ["cubeb-core/gecko-in-tree"]
|
gecko-in-tree = ["cubeb-core/gecko-in-tree"]
|
||||||
|
|
|
||||||
2
third_party/rust/cubeb/src/sample.rs
vendored
2
third_party/rust/cubeb/src/sample.rs
vendored
|
|
@ -13,7 +13,7 @@ pub trait Sample: Send + Copy {
|
||||||
|
|
||||||
impl Sample for i16 {
|
impl Sample for i16 {
|
||||||
fn from_float(x: f32) -> i16 {
|
fn from_float(x: f32) -> i16 {
|
||||||
(x * f32::from(i16::max_value())) as i16
|
(x * f32::from(i16::MAX)) as i16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@ static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
|
||||||
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
|
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
|
||||||
mozurl = { path = "../../../../netwerk/base/mozurl" }
|
mozurl = { path = "../../../../netwerk/base/mozurl" }
|
||||||
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
|
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
|
||||||
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "4ca174cf83ebe32b3198478c2211d69678845bc7", optional = true }
|
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "0989726a1b9b640a30dfdf3ea005a12c73ab8155", optional = true }
|
||||||
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="8ff972c8e2ec1782ff262ac4071c0415e69b1367", optional = true, features=["pulse-dlopen"] }
|
cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="8678dcab1c287de79c4c184ccc2e065bc62b70e2", optional = true, features=["pulse-dlopen"] }
|
||||||
cubeb-sys = { version = "0.12.0", optional = true, features=["gecko-in-tree"] }
|
cubeb-sys = { version = "0.13", optional = true, features=["gecko-in-tree"] }
|
||||||
audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "409e11f8de6288e9ddfe269654523735302e59e6", optional = true }
|
audioipc2-client = { git = "https://github.com/mozilla/audioipc", rev = "3495905752a4263827f5d43737f9ca3ed0243ce0", optional = true }
|
||||||
audioipc2-server = { git = "https://github.com/mozilla/audioipc", rev = "409e11f8de6288e9ddfe269654523735302e59e6", optional = true }
|
audioipc2-server = { git = "https://github.com/mozilla/audioipc", rev = "3495905752a4263827f5d43737f9ca3ed0243ce0", optional = true }
|
||||||
encoding_glue = { path = "../../../../intl/encoding_glue" }
|
encoding_glue = { path = "../../../../intl/encoding_glue" }
|
||||||
authrs_bridge = { path = "../../../../dom/webauthn/authrs_bridge" }
|
authrs_bridge = { path = "../../../../dom/webauthn/authrs_bridge" }
|
||||||
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
|
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue