Demi Marie Obenour writes: > WirePlumber is completely overkill as a session manager here, and > ideally a trivial session manager would be used instead. I did build a > Spectrum OS image and found that PipeWire and WirePlumber both > successfully started. PipeWire is configured to listen on the > PulseAudio socket, so PulseAudio compatibility works. This does bring a > log of unnecessary files into the VMs, which will hopefully be removed > later as part of a debloating effort. > > Signed-off-by: Demi Marie Obenour > --- > img/app/Makefile | 17 +- > img/app/default.nix | 3 + > img/app/etc/mdev.conf | 3 + > img/app/etc/pipewire/pipewire.conf | 199 +++++++ > .../etc/s6-rc/app/dependencies.d/wireplumber | 0 > .../s6-rc/pipewire/dependencies.d/directories | 0 > .../etc/s6-rc/pipewire/dependencies.d/mdevd | 0 > img/app/etc/s6-rc/pipewire/notification-fd | 1 + > .../s6-rc/pipewire/notification-fd.license | 2 + > img/app/etc/s6-rc/pipewire/run | 25 + > 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 + > img/app/etc/wireplumber/wireplumber.conf | 536 ++++++++++++++++++ > 18 files changed, 794 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/directories > create mode 100644 img/app/etc/s6-rc/pipewire/dependencies.d/mdevd > 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 > > diff --git a/img/app/Makefile b/img/app/Makefile > index e11be09a3c6ca801d9211e49b58e3d05d57e344e..734a76f018dfc1deaa9bf2cfbd4fa0d6885f0546 100644 > --- a/img/app/Makefile > +++ b/img/app/Makefile > @@ -53,7 +53,10 @@ VM_FILES = \ > etc/s6-linux-init/scripts/rc.init \ > etc/s6-linux-init/scripts/rc.shutdown \ > etc/s6-linux-init/scripts/rc.shutdown.final \ > - etc/xdg/xdg-desktop-portal/portals.conf > + etc/xdg/xdg-desktop-portal/portals.conf \ > + etc/pipewire/pipewire.conf \ > + etc/wireplumber/wireplumber.conf Sorting > diff --git a/img/app/etc/pipewire/pipewire.conf b/img/app/etc/pipewire/pipewire.conf > new file mode 100644 > index 0000000000000000000000000000000000000000..cbea25d2c7ca274db8a3c8772439b0d3a8279f13 > --- /dev/null > +++ b/img/app/etc/pipewire/pipewire.conf > @@ -0,0 +1,199 @@ > +# SPDX-License-Identifier: MIT > + > +# Copyright © 2018 Wim Taymans > +# Copyright © 2025 Demi Marie Obenour > +# > +# 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. > + > +# This file is based on the upstream default configuration. This can be > +# found in upstream GitLab or in any distro with a recent version of PipeWire. > +# The following changes have been made: > +# > +# - Conditions that have known values in Spectrum VMs are omitted. > +# - Modules for hardware devices Spectrum VMs don't have are not loaded. > +# - The PulseAudio emulation server is loaded. > +# - Settings for VMs are applied unconditionally. > +# - Most comments in the upstream files have been removed. > +# - Device nodes for virtio-sound devices have been added. > +# - Integration with udev and logind is removed. > +context.properties = { > + # Upstream defaults. > + link.max-buffers = 16 > + core.daemon = true > + core.name = pipewire-0 > + # Account for running in a VM > + default.clock.min-quantum = 1024 > +} > + > +# Upstream defaults, with support for AVB, V4L2, libcamera > +# bluez, Vulkan, JACK, and video conversion omitted. > +context.spa-libs = { > + audio.convert.* = audioconvert/libspa-audioconvert > + api.alsa.* = alsa/libspa-alsa > + support.* = support/libspa-support > +} Any reason not to enable JACK? > + > +context.modules = [ > + # Upstream defaults > + { name = libpipewire-module-rt > + args = { nice.level = -11, rt.prio = 88 } > + } > + { name = libpipewire-module-protocol-native } > + { name = libpipewire-module-metadata } > + { name = libpipewire-module-spa-device-factory } > + { name = libpipewire-module-spa-node-factory } > + { name = libpipewire-module-client-node } > + { name = libpipewire-module-access } > + { name = libpipewire-module-client-device } > + { name = libpipewire-module-portal } > + { name = libpipewire-module-adapter } > + { name = libpipewire-module-link-factory } > + { name = libpipewire-module-session-manager } > + > + # Load the PulseAudio server into PipeWire. > + # This avoids needing a separate pipewire-pulse > + # process. The args are those used when running > + # in a VM. > + { name = libpipewire-module-protocol-pulse > + args = { > + server.address = [ "unix:native" ] > + pulse.min.quantum = 1024/48000 > + } > + } So does upstream not load it into PipeWire? > +] > + > +context.objects = [ > + # Upstream defaults > + { factory = spa-node-factory > + args = { > + factory.name = support.node.driver > + node.name = Dummy-Driver > + node.group = pipewire.dummy > + node.sync-group = sync.dummy > + priority.driver = 200000 > + } > + } > + { factory = spa-node-factory > + args = { > + factory.name = support.node.driver > + node.name = Freewheel-Driver > + priority.driver = 190000 > + node.group = pipewire.freewheel > + node.sync-group = sync.dummy > + node.freewheel = true > + } > + } > + > + # Spectrum doesn't use udev, so device nodes must be created statically. > + # Creating them with pw-cli works as long as pw-cli is running, but > + # the nodes are destroyed when pw-cli exits. > + { factory = adapter > + args = { > + alsa.card = 0, > + alsa.card_name = "VirtIO SoundCard" > + alsa.device = 0 > + alsa.driver_name = "virtio_snd" > + alsa.id = "SoundCard" > + alsa.long_card_name = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" > + alsa.name = "VirtIO SoundCard" > + alsa.subdevice = 0 > + alsa.subdevice_name = "subdevice #0" > + api.alsa.card.longname = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" > + api.alsa.card.name = "VirtIO SoundCard" > + api.alsa.headroom = 0 > + api.alsa.path = "hw:0,0,0" > + api.alsa.pcm.card = 0, > + api.alsa.pcm.stream = "playback" > + audio.allowed-rates = [ ] > + audio.channels = 2 > + audio.format = "S32" > + audio.position = "FL,FR" > + audio.rate = 48000 > + factory.name = "api.alsa.pcm.sink" > + media.class = "Audio/Sink" > + node.name = "alsa_output" > + node.suspend-on-idle = true > + } > + } > + { factory = adapter > + args = { > + alsa.card = 0, > + alsa.card_name = "VirtIO SoundCard" > + alsa.device = 0 > + alsa.driver_name = "virtio_snd" > + alsa.id = "SoundCard" > + alsa.long_card_name = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" > + alsa.name = "VirtIO SoundCard" > + alsa.subdevice = 0 > + alsa.subdevice_name = "subdevice #0" > + api.alsa.card.longname = "VirtIO SoundCard at pci/0000:00:01.0/virtio0" > + api.alsa.card.name = "VirtIO SoundCard" > + api.alsa.headroom = 0 > + api.alsa.path = "hw:0,0,0" > + api.alsa.pcm.card = 0, > + api.alsa.pcm.stream = "capture" > + audio.allowed-rates = [ ] > + audio.channels = 2 > + audio.format = "S32" > + audio.position = "FL,FR" > + audio.rate = 48000 > + factory.name = "api.alsa.pcm.source" > + media.class = "Audio/Source" > + node.name = "alsa_input" > + node.suspend-on-idle = true > + } > + } > +] > + > +# Load the modules that are in the default config *except* > +# for ones whose job is to maintain state. > +pulse.cmd = [ > + { cmd = "load-module" args = "module-always-sink" flags = [ ] } > + { cmd = "load-module" args = "module-device-manager" flags = [ ] } > +] > + > +# More default stuff. > +pulse.rules = [ > + { > + matches = [ > + { application.process.binary = "teams" } > + { application.process.binary = "teams-insiders" } > + { application.process.binary = "teams-for-linux" } > + { application.process.binary = "skypeforlinux" } > + ] > + actions = { quirks = [ force-s16-info ] } > + } > + { > + matches = [ { application.process.binary = "firefox" } ] > + actions = { quirks = [ remove-capture-dont-move ] } > + } > + { > + matches = [ { application.name = "~speech-dispatcher.*" } ] > + actions = { > + update-props = { > + pulse.min.req = 512/48000 > + pulse.min.quantum = 512/48000 > + pulse.idle.timeout = 5 > + } > + } > + } > +] > + > +context.exec = [] I like this a lot better now, thanks! > diff --git a/img/app/etc/s6-rc/pipewire/dependencies.d/mdevd b/img/app/etc/s6-rc/pipewire/dependencies.d/mdevd > new file mode 100644 > index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 Probably not necessary, given we wait for the device anyway? > diff --git a/img/app/etc/wireplumber/wireplumber.conf b/img/app/etc/wireplumber/wireplumber.conf > new file mode 100644 > index 0000000000000000000000000000000000000000..68871e93083572976bba29b44f07eb35b86c0275 > --- /dev/null > +++ b/img/app/etc/wireplumber/wireplumber.conf > @@ -0,0 +1,536 @@ > +# SPDX-License-Identifier: MIT > + > +# Copyright © 2019-2021 Collabora Ltd. > +# > +# 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. > + > +# This file is based on the upstream default configuration. This can be > +# found in upstream GitLab or in any distro with a recent version of WirePlumber. > +# The following changes have been made: > +# > +# - Conditions that have known values in Spectrum VMs are omitted. > +# - Modules for hardware devices Spectrum VMs don't have are not loaded. > +# - Settings for VMs are applied unconditionally. > +# - Most comments in the upstream files have been removed. > +# - Integration with udev and logind is removed. > +# - RT scheduling for the data thread is enabled. > +# - The settings are those appropriate for a system-wide instance. > + > +context.spa-libs = { > + api.alsa.* = alsa/libspa-alsa > + audio.convert.* = audioconvert/libspa-audioconvert > + support.* = support/libspa-support > +} > + > +# Upstream default, with RT scheduling enabled. > +context.modules = [ > + { > + name = libpipewire-module-rt > + args = { nice.level = -11, rt.prio = 88 } > + } > + { name = libpipewire-module-protocol-native } > + { name = libpipewire-module-metadata } > +] > + > +wireplumber.profiles = { > + main = { > + metadata.sm-settings = required > + metadata.sm-objects = required > + > + policy.standard = required > + > + hardware.audio = required > + > + # PipeWire Media Session is not running. > + # Do not bother to check. > + check.no-media-session = disabled > + > + # No Bluetooth > + hardware.bluetooth = disabled > + bluetooth.use-persistent-storage = disabled > + bluetooth.autoswitch-to-headset-profile = disabled It's enabled by default?