From 52c6cc09c554daca6e8b38ccb4086000c444aff2 Mon Sep 17 00:00:00 2001 From: kpqi5858 Date: Mon, 24 Aug 2026 06:25:48 +0900 Subject: [PATCH 1/2] feat(pipewire): set node.rate prop --- CHANGELOG.md | 1 + src/host/pipewire/device.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 679a956ef..2ef3f9d6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Renamed the `wasm-beep` and `audioworklet-beep` examples to `webaudio` and `audioworklet`. - **ALSA**: Update `alsa` dependency to 0.12. - **Linux**: `realtime` can now promote threads without requiring `realtime-dbus`. +- **PipeWire**: Set `node.rate` property so that `default.clock.allowed-rates` PipeWire config works. ### Deprecated diff --git a/src/host/pipewire/device.rs b/src/host/pipewire/device.rs index 833300e30..7d6c3719d 100644 --- a/src/host/pipewire/device.rs +++ b/src/host/pipewire/device.rs @@ -176,6 +176,8 @@ impl Device { // preventing phase drift between simultaneous input/output streams. properties.insert("node.group", format!("cpal-{}", std::process::id())); + properties.insert(*pw::keys::NODE_RATE, format!("1/{}", config.sample_rate)); + if let BufferSize::Fixed(buffer_size) = config.buffer_size { properties.insert( *pw::keys::NODE_LATENCY, From 40ab8d12cb382fc2c3ca27fe7c6872b8b78d240d Mon Sep 17 00:00:00 2001 From: kpqi5858 Date: Mon, 31 Aug 2026 13:02:46 +0900 Subject: [PATCH 2/2] refactor(pipewire): use more exposed keys from pipewire --- src/host/pipewire/device.rs | 13 ++++++++----- src/host/pipewire/utils.rs | 5 ----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/host/pipewire/device.rs b/src/host/pipewire/device.rs index 7d6c3719d..588fd3241 100644 --- a/src/host/pipewire/device.rs +++ b/src/host/pipewire/device.rs @@ -38,7 +38,7 @@ use crate::{ stream::{ DefaultDeviceMonitor, PwInitGuard, SUPPORTED_FORMATS, StreamCommand, StreamData, }, - utils::{DEVICE_ICON_NAME, METADATA_NAME, audio, clock, default, node}, + utils::{DEVICE_ICON_NAME, METADATA_NAME, audio, clock, default}, }, }, iter::{SupportedInputConfigs, SupportedOutputConfigs}, @@ -174,7 +174,10 @@ impl Device { // Group input and output nodes so PipeWire schedules them in the same quantum, // preventing phase drift between simultaneous input/output streams. - properties.insert("node.group", format!("cpal-{}", std::process::id())); + properties.insert( + *pw::keys::NODE_GROUP, + format!("cpal-{}", std::process::id()), + ); properties.insert(*pw::keys::NODE_RATE, format!("1/{}", config.sample_rate)); @@ -991,7 +994,7 @@ pub fn init_devices(connect_automatically: Arc) -> Option InterfaceType::Bluetooth, - _ => match props.get("device.bus") { + _ => match props.get(*pw::keys::DEVICE_BUS) { Some("pci") => InterfaceType::Pci, Some("usb") => InterfaceType::Usb, Some("firewire") => InterfaceType::FireWire, @@ -1010,7 +1013,7 @@ pub fn init_devices(connect_automatically: Arc) -> Option = props - .get(node::RATE) + .get(&pw::keys::NODE_RATE) .and_then(parse_fraction) .filter(|(_, den)| *den > 0) .map(|(_, den)| den); @@ -1021,7 +1024,7 @@ pub fn init_devices(connect_automatically: Arc) -> Option, Option, ) = props - .get(node::LATENCY) + .get(&pw::keys::NODE_LATENCY) .and_then(parse_fraction) .filter(|(num, den)| *num > 0 && *den > 0) .unzip(); diff --git a/src/host/pipewire/utils.rs b/src/host/pipewire/utils.rs index 732c6afe3..aa9e324bc 100644 --- a/src/host/pipewire/utils.rs +++ b/src/host/pipewire/utils.rs @@ -20,11 +20,6 @@ pub mod clock { pub const MAX_QUANTUM: &str = "clock.max-quantum"; } -pub mod node { - pub const RATE: &str = "node.rate"; - pub const LATENCY: &str = "node.latency"; -} - pub mod default { pub const NAME: &str = "default"; pub const SINK: &str = "default.audio.sink";