mirror of
https://github.com/arabianq/pipewire-soundpad.git
synced 2026-06-19 12:13:32 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 78ca2ddf68 |
Generated
+14
-209
@@ -878,7 +878,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1227,7 +1227,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1337,12 +1337,6 @@ version = "1.0.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foldhash"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -1519,24 +1513,11 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 5.3.0",
|
"r-efi",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"r-efi 6.0.0",
|
|
||||||
"wasip2",
|
|
||||||
"wasip3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gl_generator"
|
name = "gl_generator"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
@@ -1687,15 +1668,6 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.15.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|
||||||
dependencies = [
|
|
||||||
"foldhash 0.1.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.16.1"
|
version = "0.16.1"
|
||||||
@@ -1704,7 +1676,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"foldhash 0.2.0",
|
"foldhash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1929,12 +1901,6 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "id-arena"
|
|
||||||
version = "2.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -2027,8 +1993,6 @@ checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
"serde",
|
|
||||||
"serde_core",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2174,12 +2138,6 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "leb128fmt"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.186"
|
version = "0.2.186"
|
||||||
@@ -2929,9 +2887,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opener"
|
name = "opener"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2fa337e0cf13357c13ef1dc108df1333eb192f75fc170bea03fcf1fd404c2ee"
|
checksum = "b2b03ff07a220d0d0ec9a1f0f238951b7967a5a2e96aefcd21a117b1083415e9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bstr",
|
"bstr",
|
||||||
"normpath",
|
"normpath",
|
||||||
@@ -3222,16 +3180,6 @@ dependencies = [
|
|||||||
"zerocopy",
|
"zerocopy",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prettyplease"
|
|
||||||
version = "0.2.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
@@ -3436,12 +3384,6 @@ version = "5.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "r-efi"
|
|
||||||
version = "6.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "radium"
|
name = "radium"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -3794,7 +3736,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3851,7 +3793,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4200,7 +4142,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4537,10 +4479,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.4.2",
|
"getrandom 0.3.4",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4885,7 +4827,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4912,12 +4854,6 @@ version = "0.2.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-xid"
|
|
||||||
version = "0.2.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unsafe-libyaml"
|
name = "unsafe-libyaml"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
@@ -5029,16 +4965,7 @@ version = "1.0.3+wasi-0.2.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
|
checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen 0.57.1",
|
"wit-bindgen",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasip3"
|
|
||||||
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
|
||||||
dependencies = [
|
|
||||||
"wit-bindgen 0.51.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5096,40 +5023,6 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-encoder"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
|
||||||
dependencies = [
|
|
||||||
"leb128fmt",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-metadata"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"indexmap",
|
|
||||||
"wasm-encoder",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasmparser"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.12.1",
|
|
||||||
"hashbrown 0.15.5",
|
|
||||||
"indexmap",
|
|
||||||
"semver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.3.15"
|
version = "0.3.15"
|
||||||
@@ -5435,7 +5328,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5793,100 +5686,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
||||||
dependencies = [
|
|
||||||
"wit-bindgen-rust-macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.57.1"
|
version = "0.57.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-core"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"heck",
|
|
||||||
"wit-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-rust"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"heck",
|
|
||||||
"indexmap",
|
|
||||||
"prettyplease",
|
|
||||||
"syn",
|
|
||||||
"wasm-metadata",
|
|
||||||
"wit-bindgen-core",
|
|
||||||
"wit-component",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-bindgen-rust-macro"
|
|
||||||
version = "0.51.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"wit-bindgen-core",
|
|
||||||
"wit-bindgen-rust",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-component"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"bitflags 2.12.1",
|
|
||||||
"indexmap",
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"wasm-encoder",
|
|
||||||
"wasm-metadata",
|
|
||||||
"wasmparser",
|
|
||||||
"wit-parser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wit-parser"
|
|
||||||
version = "0.244.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|
||||||
dependencies = [
|
|
||||||
"anyhow",
|
|
||||||
"id-arena",
|
|
||||||
"indexmap",
|
|
||||||
"log",
|
|
||||||
"semver",
|
|
||||||
"serde",
|
|
||||||
"serde_derive",
|
|
||||||
"serde_json",
|
|
||||||
"unicode-xid",
|
|
||||||
"wasmparser",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
|
|||||||
@@ -1732,19 +1732,6 @@
|
|||||||
"dest": "cargo/vendor/fnv-1.0.7",
|
"dest": "cargo/vendor/fnv-1.0.7",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/foldhash/foldhash-0.1.5.crate",
|
|
||||||
"sha256": "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2",
|
|
||||||
"dest": "cargo/vendor/foldhash-0.1.5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/foldhash-0.1.5",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -2005,19 +1992,6 @@
|
|||||||
"dest": "cargo/vendor/getrandom-0.3.4",
|
"dest": "cargo/vendor/getrandom-0.3.4",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/getrandom/getrandom-0.4.2.crate",
|
|
||||||
"sha256": "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555",
|
|
||||||
"dest": "cargo/vendor/getrandom-0.4.2"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/getrandom-0.4.2",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -2174,19 +2148,6 @@
|
|||||||
"dest": "cargo/vendor/half-2.7.1",
|
"dest": "cargo/vendor/half-2.7.1",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/hashbrown/hashbrown-0.15.5.crate",
|
|
||||||
"sha256": "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1",
|
|
||||||
"dest": "cargo/vendor/hashbrown-0.15.5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/hashbrown-0.15.5",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -2460,19 +2421,6 @@
|
|||||||
"dest": "cargo/vendor/icu_provider-2.2.0",
|
"dest": "cargo/vendor/icu_provider-2.2.0",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/id-arena/id-arena-2.3.0.crate",
|
|
||||||
"sha256": "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954",
|
|
||||||
"dest": "cargo/vendor/id-arena-2.3.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/id-arena-2.3.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -2772,19 +2720,6 @@
|
|||||||
"dest": "cargo/vendor/lazy_static-1.5.0",
|
"dest": "cargo/vendor/lazy_static-1.5.0",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/leb128fmt/leb128fmt-0.1.0.crate",
|
|
||||||
"sha256": "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2",
|
|
||||||
"dest": "cargo/vendor/leb128fmt-0.1.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/leb128fmt-0.1.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -3724,14 +3659,14 @@
|
|||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
"url": "https://static.crates.io/crates/opener/opener-0.8.4.crate",
|
"url": "https://static.crates.io/crates/opener/opener-0.8.5.crate",
|
||||||
"sha256": "a2fa337e0cf13357c13ef1dc108df1333eb192f75fc170bea03fcf1fd404c2ee",
|
"sha256": "b2b03ff07a220d0d0ec9a1f0f238951b7967a5a2e96aefcd21a117b1083415e9",
|
||||||
"dest": "cargo/vendor/opener-0.8.4"
|
"dest": "cargo/vendor/opener-0.8.5"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "inline",
|
"type": "inline",
|
||||||
"contents": "{\"package\": \"a2fa337e0cf13357c13ef1dc108df1333eb192f75fc170bea03fcf1fd404c2ee\", \"files\": {}}",
|
"contents": "{\"package\": \"b2b03ff07a220d0d0ec9a1f0f238951b7967a5a2e96aefcd21a117b1083415e9\", \"files\": {}}",
|
||||||
"dest": "cargo/vendor/opener-0.8.4",
|
"dest": "cargo/vendor/opener-0.8.5",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -4124,19 +4059,6 @@
|
|||||||
"dest": "cargo/vendor/ppv-lite86-0.2.21",
|
"dest": "cargo/vendor/ppv-lite86-0.2.21",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/prettyplease/prettyplease-0.2.37.crate",
|
|
||||||
"sha256": "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b",
|
|
||||||
"dest": "cargo/vendor/prettyplease-0.2.37"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/prettyplease-0.2.37",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -4306,19 +4228,6 @@
|
|||||||
"dest": "cargo/vendor/r-efi-5.3.0",
|
"dest": "cargo/vendor/r-efi-5.3.0",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/r-efi/r-efi-6.0.0.crate",
|
|
||||||
"sha256": "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf",
|
|
||||||
"dest": "cargo/vendor/r-efi-6.0.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/r-efi-6.0.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -6170,19 +6079,6 @@
|
|||||||
"dest": "cargo/vendor/unicode-width-0.2.2",
|
"dest": "cargo/vendor/unicode-width-0.2.2",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/unicode-xid/unicode-xid-0.2.6.crate",
|
|
||||||
"sha256": "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853",
|
|
||||||
"dest": "cargo/vendor/unicode-xid-0.2.6"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/unicode-xid-0.2.6",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -6352,19 +6248,6 @@
|
|||||||
"dest": "cargo/vendor/wasip2-1.0.3+wasi-0.2.9",
|
"dest": "cargo/vendor/wasip2-1.0.3+wasi-0.2.9",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wasip3/wasip3-0.4.0+wasi-0.3.0-rc-2026-01-06.crate",
|
|
||||||
"sha256": "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5",
|
|
||||||
"dest": "cargo/vendor/wasip3-0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wasip3-0.4.0+wasi-0.3.0-rc-2026-01-06",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -6430,45 +6313,6 @@
|
|||||||
"dest": "cargo/vendor/wasm-bindgen-shared-0.2.122",
|
"dest": "cargo/vendor/wasm-bindgen-shared-0.2.122",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wasm-encoder/wasm-encoder-0.244.0.crate",
|
|
||||||
"sha256": "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319",
|
|
||||||
"dest": "cargo/vendor/wasm-encoder-0.244.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wasm-encoder-0.244.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wasm-metadata/wasm-metadata-0.244.0.crate",
|
|
||||||
"sha256": "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909",
|
|
||||||
"dest": "cargo/vendor/wasm-metadata-0.244.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wasm-metadata-0.244.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wasmparser/wasmparser-0.244.0.crate",
|
|
||||||
"sha256": "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe",
|
|
||||||
"dest": "cargo/vendor/wasmparser-0.244.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wasmparser-0.244.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -7249,19 +7093,6 @@
|
|||||||
"dest": "cargo/vendor/winnow-1.0.3",
|
"dest": "cargo/vendor/winnow-1.0.3",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-bindgen/wit-bindgen-0.51.0.crate",
|
|
||||||
"sha256": "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-0.51.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-0.51.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
@@ -7275,71 +7106,6 @@
|
|||||||
"dest": "cargo/vendor/wit-bindgen-0.57.1",
|
"dest": "cargo/vendor/wit-bindgen-0.57.1",
|
||||||
"dest-filename": ".cargo-checksum.json"
|
"dest-filename": ".cargo-checksum.json"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-bindgen-core/wit-bindgen-core-0.51.0.crate",
|
|
||||||
"sha256": "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-core-0.51.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-core-0.51.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-bindgen-rust/wit-bindgen-rust-0.51.0.crate",
|
|
||||||
"sha256": "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-rust-0.51.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-rust-0.51.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-bindgen-rust-macro/wit-bindgen-rust-macro-0.51.0.crate",
|
|
||||||
"sha256": "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-rust-macro-0.51.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-bindgen-rust-macro-0.51.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-component/wit-component-0.244.0.crate",
|
|
||||||
"sha256": "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2",
|
|
||||||
"dest": "cargo/vendor/wit-component-0.244.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-component-0.244.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "archive",
|
|
||||||
"archive-type": "tar-gzip",
|
|
||||||
"url": "https://static.crates.io/crates/wit-parser/wit-parser-0.244.0.crate",
|
|
||||||
"sha256": "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736",
|
|
||||||
"dest": "cargo/vendor/wit-parser-0.244.0"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "inline",
|
|
||||||
"contents": "{\"package\": \"ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736\", \"files\": {}}",
|
|
||||||
"dest": "cargo/vendor/wit-parser-0.244.0",
|
|
||||||
"dest-filename": ".cargo-checksum.json"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "archive",
|
"type": "archive",
|
||||||
"archive-type": "tar-gzip",
|
"archive-type": "tar-gzip",
|
||||||
|
|||||||
@@ -28,10 +28,7 @@ async fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_daemon_config(); // Initialize daemon config
|
get_daemon_config(); // Initialize daemon config
|
||||||
|
create_virtual_mic()?;
|
||||||
// Virtual mic object must be kept alive by some variable until daemon exits
|
|
||||||
let _virtual_mic = create_virtual_mic().await?;
|
|
||||||
|
|
||||||
if let Err(err) = get_audio_player().await {
|
if let Err(err) = get_audio_player().await {
|
||||||
eprintln!("Failed to initialize audio player: {}", err);
|
eprintln!("Failed to initialize audio player: {}", err);
|
||||||
} // Initialize audio player
|
} // Initialize audio player
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
types::pipewire::DeviceType,
|
types::pipewire::{DeviceType, Terminate},
|
||||||
utils::{
|
utils::{
|
||||||
daemon::get_daemon_config,
|
daemon::get_daemon_config,
|
||||||
pipewire::{PwTerminator, create_link, get_device, link_player_to_virtual_mic},
|
pipewire::{create_link, get_device, link_player_to_virtual_mic},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
@@ -58,8 +58,8 @@ pub struct AudioPlayer {
|
|||||||
pub tracks: HashMap<u32, PlayingSound>,
|
pub tracks: HashMap<u32, PlayingSound>,
|
||||||
pub next_id: u32,
|
pub next_id: u32,
|
||||||
|
|
||||||
input_link_sender: Option<PwTerminator>,
|
input_link_sender: Option<pipewire::channel::Sender<Terminate>>,
|
||||||
player_link_sender: Option<PwTerminator>,
|
player_link_sender: Option<pipewire::channel::Sender<Terminate>>,
|
||||||
pub input_device_name: Option<String>,
|
pub input_device_name: Option<String>,
|
||||||
|
|
||||||
pub volume: f32, // Master volume
|
pub volume: f32, // Master volume
|
||||||
@@ -108,16 +108,24 @@ impl AudioPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn abort_link_thread(&mut self) {
|
fn abort_link_thread(&mut self) {
|
||||||
if self.input_link_sender.is_some() {
|
if let Some(sender) = &self.input_link_sender {
|
||||||
|
if sender.send(Terminate {}).is_ok() {
|
||||||
println!("Sent terminate signal to input link thread");
|
println!("Sent terminate signal to input link thread");
|
||||||
self.input_link_sender = None;
|
self.input_link_sender = None;
|
||||||
|
} else {
|
||||||
|
eprintln!("Failed to send terminate signal to input link thread");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn abort_player_link_thread(&mut self) {
|
fn abort_player_link_thread(&mut self) {
|
||||||
if self.player_link_sender.is_some() {
|
if let Some(sender) = &self.player_link_sender {
|
||||||
|
if sender.send(Terminate {}).is_ok() {
|
||||||
println!("Sent terminate signal to player link thread");
|
println!("Sent terminate signal to player link thread");
|
||||||
self.player_link_sender = None;
|
self.player_link_sender = None;
|
||||||
|
} else {
|
||||||
|
eprintln!("Failed to send terminate signal to player link thread");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +187,7 @@ impl AudioPlayer {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
self.input_link_sender = Some(create_link(output_fl, output_fr, input_fl, input_fr).await?);
|
self.input_link_sender = Some(create_link(output_fl, output_fr, input_fl, input_fr)?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+249
-273
@@ -1,224 +1,14 @@
|
|||||||
use crate::types::pipewire::{AudioDevice, DeviceType, Port};
|
use crate::types::pipewire::{AudioDevice, DeviceType, Port, Terminate};
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use pipewire::{
|
use pipewire::{
|
||||||
context::ContextRc, link::Link, main_loop::MainLoopRc, properties::properties,
|
context::ContextRc, link::Link, main_loop::MainLoopRc, properties::properties,
|
||||||
registry::GlobalObject, spa::utils::dict::DictRef,
|
registry::GlobalObject, spa::utils::dict::DictRef,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::OnceLock, thread};
|
use std::{collections::HashMap, thread};
|
||||||
use tokio::sync::oneshot;
|
use tokio::{
|
||||||
|
sync::mpsc,
|
||||||
pub enum PwCommand {
|
time::{Duration, timeout},
|
||||||
GetDevices {
|
};
|
||||||
resp: oneshot::Sender<(Vec<AudioDevice>, Vec<AudioDevice>)>,
|
|
||||||
},
|
|
||||||
CreateVirtualMic {
|
|
||||||
resp: oneshot::Sender<Result<u32, String>>,
|
|
||||||
},
|
|
||||||
CreateLink {
|
|
||||||
output_fl: Port,
|
|
||||||
output_fr: Port,
|
|
||||||
input_fl: Port,
|
|
||||||
input_fr: Port,
|
|
||||||
resp: oneshot::Sender<Result<(u32, u32), String>>,
|
|
||||||
},
|
|
||||||
DestroyObject {
|
|
||||||
id: u32,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AppState {
|
|
||||||
input_devices: HashMap<u32, AudioDevice>,
|
|
||||||
output_devices: HashMap<u32, AudioDevice>,
|
|
||||||
ports: HashMap<u32, Port>,
|
|
||||||
proxies: HashMap<u32, Box<dyn std::any::Any>>,
|
|
||||||
proxy_id_counter: u32,
|
|
||||||
ready_tx: Option<std::sync::mpsc::Sender<()>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct PipewireManager {
|
|
||||||
pub sender: pipewire::channel::Sender<PwCommand>,
|
|
||||||
}
|
|
||||||
|
|
||||||
static MANAGER: OnceLock<PipewireManager> = OnceLock::new();
|
|
||||||
|
|
||||||
pub fn get_manager() -> &'static PipewireManager {
|
|
||||||
MANAGER.get_or_init(|| {
|
|
||||||
let (pw_sender, pw_receiver) = pipewire::channel::channel::<PwCommand>();
|
|
||||||
let (ready_tx, ready_rx) = std::sync::mpsc::channel();
|
|
||||||
|
|
||||||
thread::spawn(move || {
|
|
||||||
let (main_loop, context) = setup_pipewire_context().expect("Failed to setup pipewire");
|
|
||||||
|
|
||||||
// Leak main_loop and context so their borrows can be 'static
|
|
||||||
let main_loop = Box::leak(Box::new(main_loop));
|
|
||||||
let context = Box::leak(Box::new(context));
|
|
||||||
|
|
||||||
// Leak to fix lifetime issues since this thread lives forever
|
|
||||||
let core = Box::leak(Box::new(
|
|
||||||
context
|
|
||||||
.connect(None)
|
|
||||||
.expect("Failed to connect to pipewire"),
|
|
||||||
));
|
|
||||||
let registry = Box::leak(Box::new(
|
|
||||||
core.get_registry().expect("Failed to get registry"),
|
|
||||||
));
|
|
||||||
|
|
||||||
let state = Rc::new(RefCell::new(AppState {
|
|
||||||
input_devices: HashMap::new(),
|
|
||||||
output_devices: HashMap::new(),
|
|
||||||
ports: HashMap::new(),
|
|
||||||
proxies: HashMap::new(),
|
|
||||||
proxy_id_counter: 10000,
|
|
||||||
ready_tx: Some(ready_tx),
|
|
||||||
}));
|
|
||||||
|
|
||||||
let state_for_registry_add = state.clone();
|
|
||||||
let state_for_registry_remove = state.clone();
|
|
||||||
|
|
||||||
let _listener = registry
|
|
||||||
.add_listener_local()
|
|
||||||
.global(move |global| {
|
|
||||||
let (device, port) = parse_global_object(global);
|
|
||||||
let mut s = state_for_registry_add.borrow_mut();
|
|
||||||
if let Some(device) = device {
|
|
||||||
match device.device_type {
|
|
||||||
DeviceType::Input => {
|
|
||||||
s.input_devices.insert(device.id, device);
|
|
||||||
}
|
|
||||||
DeviceType::Output => {
|
|
||||||
s.output_devices.insert(device.id, device);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if let Some(port) = port {
|
|
||||||
let node_id = port.node_id;
|
|
||||||
s.ports.insert(port.port_id, port.clone());
|
|
||||||
if let Some(d) = s.input_devices.get_mut(&node_id) {
|
|
||||||
d.add_port(port.clone());
|
|
||||||
} else if let Some(d) = s.output_devices.get_mut(&node_id) {
|
|
||||||
d.add_port(port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.global_remove(move |id| {
|
|
||||||
let mut s = state_for_registry_remove.borrow_mut();
|
|
||||||
s.input_devices.remove(&id);
|
|
||||||
s.output_devices.remove(&id);
|
|
||||||
s.ports.retain(|_, port| port.node_id != id);
|
|
||||||
s.ports.remove(&id);
|
|
||||||
})
|
|
||||||
.register();
|
|
||||||
|
|
||||||
// sync to signal ready
|
|
||||||
let state_for_sync = state.clone();
|
|
||||||
let _core_listener = core
|
|
||||||
.add_listener_local()
|
|
||||||
.done(move |id, _seq| {
|
|
||||||
if id == 0 {
|
|
||||||
let mut s = state_for_sync.borrow_mut();
|
|
||||||
if let Some(tx) = s.ready_tx.take() {
|
|
||||||
let _ = tx.send(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.register();
|
|
||||||
|
|
||||||
let _pending = core.sync(0).expect("sync failed");
|
|
||||||
|
|
||||||
let state_for_cmd = state.clone();
|
|
||||||
let _receiver = pw_receiver.attach(main_loop.loop_(), move |cmd| {
|
|
||||||
let mut s = state_for_cmd.borrow_mut();
|
|
||||||
match cmd {
|
|
||||||
PwCommand::GetDevices { resp } => {
|
|
||||||
let mut inputs: Vec<AudioDevice> =
|
|
||||||
s.input_devices.values().cloned().collect();
|
|
||||||
let mut outputs: Vec<AudioDevice> =
|
|
||||||
s.output_devices.values().cloned().collect();
|
|
||||||
inputs.sort_by_key(|a| a.id);
|
|
||||||
outputs.sort_by_key(|a| a.id);
|
|
||||||
let _ = resp.send((inputs, outputs));
|
|
||||||
}
|
|
||||||
PwCommand::CreateVirtualMic { resp } => {
|
|
||||||
let props = properties!(
|
|
||||||
"factory.name" => "support.null-audio-sink",
|
|
||||||
"node.name" => "pwsp-virtual-mic",
|
|
||||||
"node.description" => "PWSP Virtual Mic",
|
|
||||||
"media.class" => "Audio/Source/Virtual",
|
|
||||||
"audio.position" => "[ FL FR ]",
|
|
||||||
"audio.channels" => "2",
|
|
||||||
"object.linger" => "false",
|
|
||||||
);
|
|
||||||
match core.create_object::<pipewire::node::Node>("adapter", &props) {
|
|
||||||
Ok(node) => {
|
|
||||||
s.proxy_id_counter += 1;
|
|
||||||
let id = s.proxy_id_counter;
|
|
||||||
s.proxies.insert(id, Box::new(node));
|
|
||||||
let _ = resp.send(Ok(id));
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
let _ = resp.send(Err(e.to_string()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PwCommand::CreateLink {
|
|
||||||
output_fl,
|
|
||||||
output_fr,
|
|
||||||
input_fl,
|
|
||||||
input_fr,
|
|
||||||
resp,
|
|
||||||
} => {
|
|
||||||
let props_fl = properties! {
|
|
||||||
"link.output.node" => format!("{}", output_fl.node_id).as_str(),
|
|
||||||
"link.output.port" => format!("{}", output_fl.port_id).as_str(),
|
|
||||||
"link.input.node" => format!("{}", input_fl.node_id).as_str(),
|
|
||||||
"link.input.port" => format!("{}", input_fl.port_id).as_str(),
|
|
||||||
};
|
|
||||||
let props_fr = properties! {
|
|
||||||
"link.output.node" => format!("{}", output_fr.node_id).as_str(),
|
|
||||||
"link.output.port" => format!("{}", output_fr.port_id).as_str(),
|
|
||||||
"link.input.node" => format!("{}", input_fr.node_id).as_str(),
|
|
||||||
"link.input.port" => format!("{}", input_fr.port_id).as_str(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let link_fl = match core.create_object::<Link>("link-factory", &props_fl) {
|
|
||||||
Ok(link) => link,
|
|
||||||
Err(e) => {
|
|
||||||
let _ = resp.send(Err(e.to_string()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let link_fr = match core.create_object::<Link>("link-factory", &props_fr) {
|
|
||||||
Ok(link) => link,
|
|
||||||
Err(e) => {
|
|
||||||
let _ = resp.send(Err(e.to_string()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
s.proxy_id_counter += 1;
|
|
||||||
let id_fl = s.proxy_id_counter;
|
|
||||||
s.proxies.insert(id_fl, Box::new(link_fl));
|
|
||||||
|
|
||||||
s.proxy_id_counter += 1;
|
|
||||||
let id_fr = s.proxy_id_counter;
|
|
||||||
s.proxies.insert(id_fr, Box::new(link_fr));
|
|
||||||
|
|
||||||
let _ = resp.send(Ok((id_fl, id_fr)));
|
|
||||||
}
|
|
||||||
PwCommand::DestroyObject { id } => {
|
|
||||||
s.proxies.remove(&id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
main_loop.run();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait for the pipewire thread to be fully up and processed initial events
|
|
||||||
let _ = ready_rx.recv();
|
|
||||||
|
|
||||||
PipewireManager { sender: pw_sender }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_pipewire_context() -> Result<(MainLoopRc, ContextRc), String> {
|
pub fn setup_pipewire_context() -> Result<(MainLoopRc, ContextRc), String> {
|
||||||
pipewire::init();
|
pipewire::init();
|
||||||
@@ -281,17 +71,127 @@ fn parse_global_object(
|
|||||||
(None, None)
|
(None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn pw_get_global_objects_thread(
|
||||||
|
main_sender: mpsc::Sender<(Option<AudioDevice>, Option<Port>)>,
|
||||||
|
pw_receiver: pipewire::channel::Receiver<Terminate>,
|
||||||
|
init_sender: tokio::sync::oneshot::Sender<Result<(), String>>,
|
||||||
|
) {
|
||||||
|
let (main_loop, context) = match setup_pipewire_context() {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Stop main loop on Terminate message
|
||||||
|
let _receiver = pw_receiver.attach(main_loop.loop_(), {
|
||||||
|
let _main_loop = main_loop.clone();
|
||||||
|
move |_| _main_loop.quit()
|
||||||
|
});
|
||||||
|
|
||||||
|
let core = match context.connect(None) {
|
||||||
|
Ok(core) => core,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(format!("Failed to connect to pipewire context: {}", e)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let registry = match core.get_registry() {
|
||||||
|
Ok(registry) => registry,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(format!(
|
||||||
|
"Failed to get registry from pipewire context: {}",
|
||||||
|
e
|
||||||
|
)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _listener = registry
|
||||||
|
.add_listener_local()
|
||||||
|
.global(move |global| {
|
||||||
|
// Try to parse every global object pipewire finds
|
||||||
|
let (device, port) = parse_global_object(global);
|
||||||
|
|
||||||
|
// Send message to the main thread
|
||||||
|
let sender_clone = main_sender.clone();
|
||||||
|
tokio::task::spawn(async move {
|
||||||
|
sender_clone.send((device, port)).await.ok();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.register();
|
||||||
|
|
||||||
|
// Signal successful initialization
|
||||||
|
if init_sender.send(Ok(())).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
main_loop.run();
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>)> {
|
pub async fn get_all_devices() -> Result<(Vec<AudioDevice>, Vec<AudioDevice>)> {
|
||||||
let (tx, rx) = oneshot::channel();
|
// Channels to communicate with pipewire thread
|
||||||
let manager = get_manager();
|
let (main_sender, mut main_receiver) = mpsc::channel(10);
|
||||||
manager
|
let (pw_sender, pw_receiver) = pipewire::channel::channel();
|
||||||
.sender
|
let (init_sender, init_receiver) = tokio::sync::oneshot::channel();
|
||||||
.send(PwCommand::GetDevices { resp: tx })
|
|
||||||
.map_err(|_| anyhow!("Failed to send GetDevices to manager"))?;
|
// Spawn pipewire thread in background
|
||||||
let res = rx
|
let _pw_thread = tokio::spawn(async move {
|
||||||
.await
|
pw_get_global_objects_thread(main_sender, pw_receiver, init_sender).await
|
||||||
.map_err(|e| anyhow!("Failed to receive response: {}", e))?;
|
});
|
||||||
Ok(res)
|
|
||||||
|
// Wait for initialization to complete
|
||||||
|
if let Err(e) = init_receiver.await {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut input_devices: HashMap<u32, AudioDevice> = HashMap::new();
|
||||||
|
let mut output_devices: HashMap<u32, AudioDevice> = HashMap::new();
|
||||||
|
let mut ports: Vec<Port> = vec![];
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// If we don't receive a message in 100ms, we can assume that pipewire thread is finished
|
||||||
|
match timeout(Duration::from_millis(100), main_receiver.recv()).await {
|
||||||
|
Ok(Some((device, port))) => {
|
||||||
|
if let Some(device) = device {
|
||||||
|
match device.device_type {
|
||||||
|
DeviceType::Input => {
|
||||||
|
input_devices.insert(device.id, device);
|
||||||
|
}
|
||||||
|
DeviceType::Output => {
|
||||||
|
output_devices.insert(device.id, device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let Some(port) = port {
|
||||||
|
ports.push(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(None) | Err(_) => {
|
||||||
|
// Pipewire thread is finished and we can collect our devices
|
||||||
|
let _ = pw_sender.send(Terminate {});
|
||||||
|
|
||||||
|
for port in ports {
|
||||||
|
let node_id = port.node_id;
|
||||||
|
|
||||||
|
if let Some(input_device) = input_devices.get_mut(&node_id) {
|
||||||
|
input_device.add_port(port);
|
||||||
|
} else if let Some(output_device) = output_devices.get_mut(&node_id) {
|
||||||
|
output_device.add_port(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut input_devices: Vec<AudioDevice> = input_devices.into_values().collect();
|
||||||
|
let mut output_devices: Vec<AudioDevice> = output_devices.into_values().collect();
|
||||||
|
|
||||||
|
input_devices.sort_by_key(|a| a.id);
|
||||||
|
output_devices.sort_by_key(|a| a.id);
|
||||||
|
|
||||||
|
return Ok((input_devices, output_devices));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_device(device_name: &str) -> Result<AudioDevice> {
|
pub async fn get_device(device_name: &str) -> Result<AudioDevice> {
|
||||||
@@ -309,36 +209,65 @@ pub async fn get_device(device_name: &str) -> Result<AudioDevice> {
|
|||||||
.ok_or_else(|| anyhow!("Device not found"))
|
.ok_or_else(|| anyhow!("Device not found"))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PwTerminator {
|
pub fn create_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>> {
|
||||||
ids: Vec<u32>,
|
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
|
||||||
}
|
let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0);
|
||||||
|
|
||||||
impl Drop for PwTerminator {
|
let _pw_thread = thread::spawn(move || {
|
||||||
fn drop(&mut self) {
|
let (main_loop, context) = match setup_pipewire_context() {
|
||||||
let manager = get_manager();
|
Ok(res) => res,
|
||||||
for id in &self.ids {
|
Err(e) => {
|
||||||
let _ = manager.sender.send(PwCommand::DestroyObject { id: *id });
|
let _ = init_sender.send(Err(e));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
let core = match context.connect(None) {
|
||||||
|
Ok(core) => core,
|
||||||
|
Err(e) => {
|
||||||
|
let _ =
|
||||||
|
init_sender.send(Err(format!("Failed to connect to pipewire context: {}", e)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let props = properties!(
|
||||||
|
"factory.name" => "support.null-audio-sink",
|
||||||
|
"node.name" => "pwsp-virtual-mic",
|
||||||
|
"node.description" => "PWSP Virtual Mic",
|
||||||
|
"media.class" => "Audio/Source/Virtual",
|
||||||
|
"audio.position" => "[ FL FR ]",
|
||||||
|
"audio.channels" => "2",
|
||||||
|
"object.linger" => "false", // Destroy the node on app exit
|
||||||
|
);
|
||||||
|
|
||||||
|
let _node = match core.create_object::<pipewire::node::Node>("adapter", &props) {
|
||||||
|
Ok(node) => node,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(format!("Failed to create virtual mic: {}", e)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _receiver = pw_receiver.attach(main_loop.loop_(), {
|
||||||
|
let _main_loop = main_loop.clone();
|
||||||
|
move |_| _main_loop.quit()
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("Virtual mic created");
|
||||||
|
if init_sender.send(Ok(())).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
main_loop.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(e) = init_receiver.recv()? {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(pw_sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_virtual_mic() -> Result<PwTerminator> {
|
pub async fn link_player_to_virtual_mic() -> Result<pipewire::channel::Sender<Terminate>> {
|
||||||
let (tx, rx) = oneshot::channel();
|
|
||||||
let manager = get_manager();
|
|
||||||
manager
|
|
||||||
.sender
|
|
||||||
.send(PwCommand::CreateVirtualMic { resp: tx })
|
|
||||||
.map_err(|_| anyhow!("Failed to send CreateVirtualMic to manager"))?;
|
|
||||||
|
|
||||||
let res = rx
|
|
||||||
.await
|
|
||||||
.map_err(|e| anyhow!("Failed to receive response: {}", e))?;
|
|
||||||
|
|
||||||
let id = res.map_err(|e| anyhow!(e))?;
|
|
||||||
Ok(PwTerminator { ids: vec![id] })
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn link_player_to_virtual_mic() -> Result<PwTerminator> {
|
|
||||||
let pwsp_daemon_output = match get_device("pwsp-daemon").await {
|
let pwsp_daemon_output = match get_device("pwsp-daemon").await {
|
||||||
Ok(device) => device,
|
Ok(device) => device,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
@@ -374,34 +303,81 @@ pub async fn link_player_to_virtual_mic() -> Result<PwTerminator> {
|
|||||||
None => return Err(anyhow!("Failed to get pwsp-virtual-mic input_fr")),
|
None => return Err(anyhow!("Failed to get pwsp-virtual-mic input_fr")),
|
||||||
};
|
};
|
||||||
|
|
||||||
create_link(output_fl, output_fr, input_fl, input_fr).await
|
create_link(output_fl, output_fr, input_fl, input_fr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_link(
|
pub fn create_link(
|
||||||
output_fl: Port,
|
output_fl: Port,
|
||||||
output_fr: Port,
|
output_fr: Port,
|
||||||
input_fl: Port,
|
input_fl: Port,
|
||||||
input_fr: Port,
|
input_fr: Port,
|
||||||
) -> Result<PwTerminator> {
|
) -> Result<pipewire::channel::Sender<Terminate>> {
|
||||||
let (tx, rx) = oneshot::channel();
|
let (pw_sender, pw_receiver) = pipewire::channel::channel::<Terminate>();
|
||||||
let manager = get_manager();
|
let (init_sender, init_receiver) = std::sync::mpsc::sync_channel(0);
|
||||||
manager
|
|
||||||
.sender
|
|
||||||
.send(PwCommand::CreateLink {
|
|
||||||
output_fl,
|
|
||||||
output_fr,
|
|
||||||
input_fl,
|
|
||||||
input_fr,
|
|
||||||
resp: tx,
|
|
||||||
})
|
|
||||||
.map_err(|_| anyhow!("Failed to send CreateLink to manager"))?;
|
|
||||||
|
|
||||||
let res = rx
|
let _pw_thread = thread::spawn(move || {
|
||||||
.await
|
let (main_loop, context) = match setup_pipewire_context() {
|
||||||
.map_err(|e| anyhow!("Failed to receive response: {}", e))?;
|
Ok(res) => res,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(e));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let core = match context.connect(None) {
|
||||||
|
Ok(core) => core,
|
||||||
|
Err(e) => {
|
||||||
|
let _ =
|
||||||
|
init_sender.send(Err(format!("Failed to connect to pipewire context: {}", e)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let (id_fl, id_fr) = res.map_err(|e| anyhow!(e))?;
|
let props_fl = properties! {
|
||||||
Ok(PwTerminator {
|
"link.output.node" => format!("{}", output_fl.node_id).as_str(),
|
||||||
ids: vec![id_fl, id_fr],
|
"link.output.port" => format!("{}", output_fl.port_id).as_str(),
|
||||||
})
|
"link.input.node" => format!("{}", input_fl.node_id).as_str(),
|
||||||
|
"link.input.port" => format!("{}", input_fl.port_id).as_str(),
|
||||||
|
};
|
||||||
|
let props_fr = properties! {
|
||||||
|
"link.output.node" => format!("{}", output_fr.node_id).as_str(),
|
||||||
|
"link.output.port" => format!("{}", output_fr.port_id).as_str(),
|
||||||
|
"link.input.node" => format!("{}", input_fr.node_id).as_str(),
|
||||||
|
"link.input.port" => format!("{}", input_fr.port_id).as_str(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let _link_fl = match core.create_object::<Link>("link-factory", &props_fl) {
|
||||||
|
Ok(link) => link,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(format!("Failed to create link FL: {}", e)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let _link_fr = match core.create_object::<Link>("link-factory", &props_fr) {
|
||||||
|
Ok(link) => link,
|
||||||
|
Err(e) => {
|
||||||
|
let _ = init_sender.send(Err(format!("Failed to create link FR: {}", e)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _receiver = pw_receiver.attach(main_loop.loop_(), {
|
||||||
|
let _main_loop = main_loop.clone();
|
||||||
|
move |_| _main_loop.quit()
|
||||||
|
});
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Link created: FL: {}-{} FR: {}-{}",
|
||||||
|
output_fl.node_id, input_fl.node_id, output_fr.node_id, input_fr.node_id
|
||||||
|
);
|
||||||
|
if init_sender.send(Ok(())).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
main_loop.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(e) = init_receiver.recv()? {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(pw_sender)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user