mirror of
https://github.com/arabianq/pipewire-soundpad.git
synced 2026-07-26 05:46:59 +00:00
chore: update cargo lock and flatpak sources
After removing criterion, the cargo lockfile and flatpak sources have been refreshed to properly remove the offline build dependencies issue. Co-authored-by: arabianq <55220741+arabianq@users.noreply.github.com>
This commit is contained in:
co-authored by
arabianq
parent
dea12ddc0f
commit
27379d8e78
@@ -45,9 +45,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: 1.96.0
|
toolchain: 1.96.0
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: swatinem/rust-cache@v2
|
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --locked
|
run: cargo test --locked
|
||||||
|
|
||||||
@@ -138,9 +135,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: 1.96.0
|
toolchain: 1.96.0
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: swatinem/rust-cache@v2
|
|
||||||
|
|
||||||
- name: Build all binaries (debug-speed compilation into target/release)
|
- name: Build all binaries (debug-speed compilation into target/release)
|
||||||
env:
|
env:
|
||||||
CARGO_PROFILE_RELEASE_OPT_LEVEL: 0
|
CARGO_PROFILE_RELEASE_OPT_LEVEL: 0
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ jobs:
|
|||||||
echo "default-branch: ${{ steps.set_branch.outputs.branch }}" >> packages/flatpak/ru.arabianq.pwsp.yaml
|
echo "default-branch: ${{ steps.set_branch.outputs.branch }}" >> packages/flatpak/ru.arabianq.pwsp.yaml
|
||||||
|
|
||||||
- name: Install SDK Extensions
|
- name: Install SDK Extensions
|
||||||
run: |
|
run:
|
||||||
flatpak install -y flathub org.freedesktop.Sdk.Extension.rust-stable//25.08
|
flatpak install -y flathub org.freedesktop.Sdk.Extension.rust-stable//25.08
|
||||||
flatpak install -y flathub org.freedesktop.Sdk.Extension.llvm20//25.08
|
org.freedesktop.Sdk.Extension.llvm20//25.08
|
||||||
|
|
||||||
- name: Build Flatpak
|
- name: Build Flatpak
|
||||||
uses: andyholmes/flatter@main
|
uses: andyholmes/flatter@main
|
||||||
@@ -72,7 +72,6 @@ jobs:
|
|||||||
upload-bundles: false
|
upload-bundles: false
|
||||||
upload-pages-artifact: false
|
upload-pages-artifact: false
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
cache: true
|
|
||||||
|
|
||||||
flatter-arm64:
|
flatter-arm64:
|
||||||
name: Flatter (aarch64)
|
name: Flatter (aarch64)
|
||||||
@@ -114,9 +113,9 @@ jobs:
|
|||||||
echo "default-branch: ${{ steps.set_branch.outputs.branch }}" >> packages/flatpak/ru.arabianq.pwsp.yaml
|
echo "default-branch: ${{ steps.set_branch.outputs.branch }}" >> packages/flatpak/ru.arabianq.pwsp.yaml
|
||||||
|
|
||||||
- name: Install SDK Extensions
|
- name: Install SDK Extensions
|
||||||
run: |
|
run:
|
||||||
flatpak install -y flathub org.freedesktop.Sdk.Extension.rust-stable//25.08
|
flatpak install -y flathub org.freedesktop.Sdk.Extension.rust-stable//25.08
|
||||||
flatpak install -y flathub org.freedesktop.Sdk.Extension.llvm20//25.08
|
org.freedesktop.Sdk.Extension.llvm20//25.08
|
||||||
|
|
||||||
- name: Build Flatpak
|
- name: Build Flatpak
|
||||||
uses: andyholmes/flatter@main
|
uses: andyholmes/flatter@main
|
||||||
@@ -126,7 +125,6 @@ jobs:
|
|||||||
upload-bundles: false
|
upload-bundles: false
|
||||||
upload-pages-artifact: true
|
upload-pages-artifact: true
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
cache: true
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
name: Deploy to GitHub Pages
|
name: Deploy to GitHub Pages
|
||||||
|
|||||||
@@ -97,9 +97,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: 1.96.0
|
toolchain: 1.96.0
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: swatinem/rust-cache@v2
|
|
||||||
|
|
||||||
- name: Extract all binary names
|
- name: Extract all binary names
|
||||||
id: cargo-meta
|
id: cargo-meta
|
||||||
run: |
|
run: |
|
||||||
@@ -183,9 +180,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
toolchain: 1.96.0
|
toolchain: 1.96.0
|
||||||
|
|
||||||
- name: Rust Cache
|
|
||||||
uses: swatinem/rust-cache@v2
|
|
||||||
|
|
||||||
- name: Build all release binaries
|
- name: Build all release binaries
|
||||||
run: cargo build --release --locked
|
run: cargo build --release --locked
|
||||||
|
|
||||||
@@ -260,8 +254,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.config
|
mkdir -p ~/.config
|
||||||
echo "$COPR_CONFIG" > ~/.config/copr
|
echo "$COPR_CONFIG" > ~/.config/copr
|
||||||
copr-cli buildscm --nowait \
|
copr-cli buildscm --clone-url https://github.com/arabianq/pipewire-soundpad.git \
|
||||||
--clone-url https://github.com/arabianq/pipewire-soundpad.git \
|
|
||||||
--commit ${{ needs.prepare.outputs.tag }} \
|
--commit ${{ needs.prepare.outputs.tag }} \
|
||||||
--spec packages/rpm/pwsp.spec \
|
--spec packages/rpm/pwsp.spec \
|
||||||
arabianq/pwsp
|
arabianq/pwsp
|
||||||
|
|||||||
Generated
+75
-58
@@ -151,9 +151,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.6"
|
version = "0.7.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
checksum = "f02882884d3e1bc524fb12c79f107f6ad0e1cfd498c536ffb494301740995dfe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "as-raw-xcb-connection"
|
name = "as-raw-xcb-connection"
|
||||||
@@ -386,9 +386,9 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitvec"
|
name = "bitvec"
|
||||||
version = "1.0.1"
|
version = "1.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"funty",
|
"funty",
|
||||||
"radium",
|
"radium",
|
||||||
@@ -429,13 +429,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "1.12.1"
|
version = "1.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab"
|
checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata",
|
||||||
"serde",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -472,9 +472,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.11.1"
|
version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33"
|
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
@@ -529,9 +529,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.64"
|
version = "1.2.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dad887fd958be91b5098c0248def011f4523ab786cd411be668777e55063501f"
|
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -776,7 +776,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "cpal"
|
name = "cpal"
|
||||||
version = "0.18.1"
|
version = "0.18.1"
|
||||||
source = "git+https://github.com/RustAudio/cpal#6ea4fcd74e002cfe660158a33014d7bb499de94c"
|
source = "git+https://github.com/RustAudio/cpal#e22fb7ecb4800649b7790bcbe8422ca347a62cd0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alsa",
|
"alsa",
|
||||||
"block2 0.6.2",
|
"block2 0.6.2",
|
||||||
@@ -878,7 +878,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users",
|
"redox_users",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[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.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1513,11 +1513,22 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi 5.3.0",
|
||||||
"wasip2",
|
"wasip2",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"r-efi 6.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gl_generator"
|
name = "gl_generator"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
@@ -1639,9 +1650,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.14"
|
version = "0.4.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733"
|
checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2104,9 +2115,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.102"
|
version = "0.3.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03d04c30968dffe80775bd4d7fb676131cd04a1fb46d2686dbffbaec2d9dfd31"
|
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -2263,9 +2274,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.32"
|
version = "0.4.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru-slab"
|
name = "lru-slab"
|
||||||
@@ -2287,9 +2298,9 @@ checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
version = "0.9.10"
|
version = "0.9.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3"
|
checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -3314,9 +3325,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn"
|
name = "quinn"
|
||||||
version = "0.11.9"
|
version = "0.11.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
|
checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
@@ -3334,9 +3345,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-proto"
|
name = "quinn-proto"
|
||||||
version = "0.11.14"
|
version = "0.11.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098"
|
checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -3370,9 +3381,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.45"
|
version = "1.0.46"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -3383,6 +3394,12 @@ 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"
|
||||||
@@ -3735,14 +3752,14 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.40"
|
version = "0.23.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -3792,7 +3809,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4141,7 +4158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4376,9 +4393,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -4478,10 +4495,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.4.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4826,7 +4843,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4886,9 +4903,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.23.3"
|
version = "1.23.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "144d6b123cef80b301b8f72a9e2ca4370ddec21950d0a103dd22c437006d2db7"
|
checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
@@ -4969,9 +4986,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.125"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ddb3f79143bced6de84270411622a2699cee572fc0875aeaf1e7867cf9fca1a"
|
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -4982,9 +4999,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.75"
|
version = "0.4.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "503b14d284f2c8dac03b819967e155ea753f573586193b2b2c95990cb5d69280"
|
checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -4992,9 +5009,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.125"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e21a184b13fb19e157296e2c46056aec9092264fab83e4ba59e68c61b323c3d"
|
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -5002,9 +5019,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.125"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fecefd9c35bd935a20fc3fc344b5f29138961e4f47fb03297d88f2587afb5ebd"
|
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -5015,9 +5032,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.125"
|
version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23939e44bb9a5d7576fa2b563dc2e136628f1224e88a8deed09e04858b77871f"
|
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -5072,9 +5089,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols"
|
name = "wayland-protocols"
|
||||||
version = "0.32.12"
|
version = "0.32.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f"
|
checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.0",
|
"bitflags 2.13.0",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -5159,9 +5176,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.102"
|
version = "0.3.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a6430a72df5eb332242960fe84b3002a241163998241eb596d4f739b9757061d"
|
checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -5195,9 +5212,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webpki-root-certs"
|
name = "webpki-root-certs"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c"
|
checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
@@ -5327,7 +5344,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.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
+145
-119
File diff suppressed because one or more lines are too long
@@ -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
|
||||||
|
|||||||
@@ -316,8 +316,7 @@ impl SoundpadGui {
|
|||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
read.push(child_path);
|
read.push(child_path);
|
||||||
@@ -343,7 +342,8 @@ impl SoundpadGui {
|
|||||||
let search_query = search_query.trim();
|
let search_query = search_query.trim();
|
||||||
|
|
||||||
for child in children {
|
for child in children {
|
||||||
if !child.is_dir() && !search_query.is_empty() {
|
if !child.is_dir()
|
||||||
|
&& !search_query.is_empty() {
|
||||||
let file_name = child
|
let file_name = child
|
||||||
.file_name()
|
.file_name()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
|
|||||||
@@ -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