On 7/29/25 09:08, Alyssa Ross wrote: > Demi Marie Obenour writes: > >> WirePlumber is completely overkill as a session manager here, and >> ideally a trivial session manager would be used instead. PipeWire is >> configured to listen on the PulseAudio socket, so PulseAudio >> compatibility works. pw-record and pw-play both work, and if PulseAudio >> is installed paplay and parecord also work. This does install a lot of >> unnecessary files into the VMs, which will hopefully be removed >> later as part of a debloating effort. >> >> Only run-qemu has had a virtio-sound device added, as crosvm and Cloud >> Hypervisor require a virtio-user sound device and that is more complex >> to set up. >> >> Signed-off-by: Demi Marie Obenour >> --- >> Changes since v8: >> - Add longer explanation for the priority.driver and priority.session >> values. >> - Give credit to George Kiagiadakis. >> - Fix spelling errors in comments. >> >> Changes since v7: >> - Give the capture node a higher priority.session than the playback >> node, so WirePlumber links recording applications to the capture node >> instead of the monitor of the playback node. >> - Give the capture node a higher priority.driver than the playback node, >> so PipeWire has the capture node drive the graph. This is better >> because capture xruns lead to permanently corrupted data, whereas >> playback xruns do not. >> - Re-enable monitor node creation in WirePlumber. >> >> Changes since v6: >> - Fix spelling errors in commit messages. >> - Sort lines in Makefile. >> - Don't disable support.settings as a comment in wireplumber.conf says >> to not do that. Instead, tell WirePlumber to not create monitor >> nodes. This is a workaround for WirePlumber bug 829. >> - Don't remove "-cpu host" from make run-qemu's QEMU command line. This >> was needed for local testing with KVM disabled but should not have >> been submitted upstream. Hardware with KVM support should be used >> instead. >> >> Changes since v5: >> >> - Use a drop-in configuration file for WirePlumber instead of overriding >> wireplumber.conf. This should be more robust to future WirePlumber >> changes. >> --- >> img/app/Makefile | 16 +- >> img/app/default.nix | 3 + >> img/app/etc/mdev.conf | 1 + >> img/app/etc/pipewire/pipewire.conf | 229 ++++++++++++++++++ >> .../etc/s6-rc/app/dependencies.d/wireplumber | 0 >> .../etc/s6-rc/pipewire/dependencies.d/dbus | 0 >> img/app/etc/s6-rc/pipewire/notification-fd | 1 + >> .../s6-rc/pipewire/notification-fd.license | 2 + >> img/app/etc/s6-rc/pipewire/run | 23 ++ >> img/app/etc/s6-rc/pipewire/type | 1 + >> img/app/etc/s6-rc/pipewire/type.license | 2 + >> .../etc/s6-rc/wireplumber/dependencies.d/dbus | 0 >> .../s6-rc/wireplumber/dependencies.d/pipewire | 0 >> img/app/etc/s6-rc/wireplumber/run | 4 + >> img/app/etc/s6-rc/wireplumber/type | 1 + >> img/app/etc/s6-rc/wireplumber/type.license | 2 + >> .../wireplumber.conf.d/99_spectrum.conf | 42 ++++ >> 17 files changed, 325 insertions(+), 2 deletions(-) >> create mode 100644 img/app/etc/pipewire/pipewire.conf >> create mode 100644 img/app/etc/s6-rc/app/dependencies.d/wireplumber >> create mode 100644 img/app/etc/s6-rc/pipewire/dependencies.d/dbus >> create mode 100644 img/app/etc/s6-rc/pipewire/notification-fd >> create mode 100644 img/app/etc/s6-rc/pipewire/notification-fd.license >> create mode 100644 img/app/etc/s6-rc/pipewire/run >> create mode 100644 img/app/etc/s6-rc/pipewire/type >> create mode 100644 img/app/etc/s6-rc/pipewire/type.license >> create mode 100644 img/app/etc/s6-rc/wireplumber/dependencies.d/dbus >> create mode 100644 img/app/etc/s6-rc/wireplumber/dependencies.d/pipewire >> create mode 100644 img/app/etc/s6-rc/wireplumber/run >> create mode 100644 img/app/etc/s6-rc/wireplumber/type >> create mode 100644 img/app/etc/s6-rc/wireplumber/type.license >> create mode 100644 img/app/etc/wireplumber/wireplumber.conf.d/99_spectrum.conf > > We have app depending on wireplumber, but no notification-fd for > wireplumber. What's actually required here? Does Wireplumber actually > need to be running (for whatever definition thereof) by the time an > application starts, or does it just need to start at some reasonable > point? The latter. In systemd terms, this is WantedBy=. I will fix this by having ok-all depend on WirePlumber, while the app no longer does. >> + # PipeWire chooses the node with the highest priority.driver value as >> + # graph driver, which is the node that decides when the processing graph >> + # is going to run. If both the capture node and playback node are in >> + # the same graph, the capture node should be chosen as the driver. This >> + # is because the driver gets to choose the rate of the graph and so is >> + # much less likely to xrun. Since capture xruns result in corrupted >> + # audio recordings, while playback xruns just result in a glitch, it >> + # is more important to avoid capture xruns. >> + # >> + # When there are multiple sources or sinks that could be used, >> + # WirePlumber links application nodes to the one with the highest >> + # priority.session value. In the configuration created here, >> + # there are two valid audio sources: the virtio sound card's >> + # capture stream and the monitor of its playback stream. The >> + # capture stream is the correct choice, so its priority.session >> + # should be higher. >> + # >> + # The recommendation to give the capture device higher values >> + # for priority.driver and priority.session comes from George >> + # Kiagiadakis of Collabora, who also provided the values >> + # used (2000 and 1000) and why they must be different. >> + # The explanation for why it is more important to avoid >> + # capture xruns than playback xruns comes from past discussions >> + # that I (Demi Marie Obenour) had with Wim Taymans. > > Just checking: they're okay with being credited, right? (Important for > me to be confident before mentioning anybody in an immutable log.) That's actually not something I had checked. I asked both if they are okay with this. Should I sent V10 without these, or should I wait for a response from them? >> diff --git a/img/app/etc/s6-rc/app/dependencies.d/wireplumber b/img/app/etc/s6-rc/app/dependencies.d/wireplumber >> new file mode 100644 >> index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 >> diff --git a/img/app/etc/s6-rc/pipewire/dependencies.d/dbus b/img/app/etc/s6-rc/pipewire/dependencies.d/dbus This dependency wasn't needed and wasn't included in the VMs. v10 will leave it out. >> --- /dev/null >> +++ b/img/app/etc/s6-rc/pipewire/run >> @@ -0,0 +1,23 @@ >> +#!/bin/execlineb -P >> +# SPDX-License-Identifier: EUPL-1.2+ >> +# SPDX-FileCopyrightText: 2023-2024 Alyssa Ross >> +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour >> + >> +s6-ipcserver-socketbinder -B /run/user/0/pipewire-0 >> +fdmove -c 3 0 >> + >> +s6-ipcserver-socketbinder -B /run/user/0/pipewire-0-manager >> +fdmove -c 4 0 >> + >> +redirfd -r 0 /dev/null >> + >> +# Wait for sound devices to be available >> +if { /etc/mdev/wait controlC0 } >> + >> +# Notify readiness. >> +if { fdmove 1 5 echo } >> +fdclose 5 > > We could move this earlier, right? If things connect before the sound > devices are available, PipeWire won't have been started yet so the > connection will just not be accepted until they are. That is indeed correct. Will change in v10. >> diff --git a/img/app/etc/wireplumber/wireplumber.conf.d/99_spectrum.conf b/img/app/etc/wireplumber/wireplumber.conf.d/99_spectrum.conf >> new file mode 100644 >> index 0000000000000000000000000000000000000000..277e6019c46582afba12af9b1a27bb16ddd9e804 >> --- /dev/null >> +++ b/img/app/etc/wireplumber/wireplumber.conf.d/99_spectrum.conf >> @@ -0,0 +1,42 @@ >> +# SPDX-License-Identifier: MIT >> +# SPDX-FileCopyrightText: 2019-2021 Collabora Ltd. >> +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour >> + >> +# Copyright © 2019-2021 Collabora Ltd. > > Once again I'm surprised any of this is © Collabora… It's out of an abundance of caution. All of this is taken from the wireplumber.conf files in Arch and Nixpkgs, which I believe are just the upstream ones. I suspect you are correct, but it's much better to keep a copyright notice that is not needed than to remove one that actually *is* needed. >> +# >> +# Permission is hereby granted, free of charge, to any person obtaining a >> +# copy of this software and associated documentation files (the "Software"), >> +# to deal in the Software without restriction, including without limitation >> +# the rights to use, copy, modify, merge, publish, distribute, sublicense, >> +# and/or sell copies of the Software, and to permit persons to whom the >> +# Software is furnished to do so, subject to the following conditions: >> +# >> +# The above copyright notice and this permission notice (including the next >> +# paragraph) shall be included in all copies or substantial portions of the >> +# Software. >> +# >> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR >> +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, >> +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL >> +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER >> +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING >> +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER >> +# DEALINGS IN THE SOFTWARE. >> + >> +wireplumber.profiles = { >> + spectrum = { >> + # Spectrum VMs are essentially embedded systems, in that they are >> + # not at all general-purpose. >> + inherits = [ main-embedded ] >> + # Disable video and Bluetooth >> + hardware.video-capture = disabled >> + hardware.bluetooth = disabled >> + # Media Session is definitely not running >> + check.no-media-session = disabled >> + } >> +} >> + >> +wireplumber.settings = { >> + # Default to 100% sink volume. The host will adjust this as needed. >> + device.routes.default-sink-volume = 1.0 >> +} -- Sincerely, Demi Marie Obenour (she/her/hers)