pipewire: show QEMU audio streams in Application Volumes#2986
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates PipeWire stream classification and identity handling to better match wpctl/pavucontrol behavior, especially for QEMU/libvirt PipeWire audio streams.
Changes:
- Treat
target.objectstreams as user-controllable “program output nodes” (no longer excluded). - Add a QEMU/libvirt-specific fallback to derive
applicationName(and sometimesapplicationId) fromtarget.objectwhen metadata is missing.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dcff959 to
3a1002d
Compare
3a1002d to
47b33c2
Compare
Collaborator
|
Thanks! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclaimer
I know that this is a very edge cases and is intended for people who uses QEMU VMs and want the audio to appear on the "Application Volumes" widget. This will solve the below issues for me and I'll be really grateful if this is merged.
!nd.targetObject.empty()causes the QEMU VMs to be filtered out from the list** This change was made with the help of Claude Fable 5. **
Summary
QEMU's PipeWire audio stream (libvirt
<audio type="pipewire">) is aStream/Output/Audionode withtarget.objectset to the libvirt<input>/<output>name (e.g. "Windows 11"). Noctalia'sisProgramOutputNodefilter deliberately excluded any node with a non-emptytarget.objectas a "loopback/filter endpoint", so QEMU streams were hidden from Application Volumes even thoughpavucontrolandwpctlshow them. This makes the QEMU volume uncontrollable from the panel while the VM is playing audio.Two changes:
Drop the
!nd.targetObject.empty()exclusion inisProgramOutputNode.node.link-groupandnode.passiveremain excluded (those still correctly hide Wine/Proton link-grouped stubs and real loopback/filter endpoints). Onlytarget.objectis relaxed. The comment is updated to match the new behaviour and to explain why virtual streams that feed another endpoint (QEMU → VM HDA) are user-controllable application volumes.Promote
target.objecttoapplicationNameinrefreshNodeIdentityfor anyStream/Output/Audionode whosenode.namestarts withqemu-system-(covering every QEMU system emulator binary:qemu-system-x86_64,qemu-system-aarch64,qemu-system-riscv64,qemu-system-arm,qemu-system-ppc64, ...). QEMU's PipeWire backend does not exposeapplication.name/application.idfrom process metadata, so without this the stream would show as the bare process name. When the libvirt<input>/<output>has anameattribute, that name is used; when it does not, the stream falls back to the generic label"QEMU". The block synthesises a stableapplicationIdoforg.qemu.vm.<name>so the stream doesn't collide with any other process's identity.The block runs unconditionally for any matching node — not gated on whether
applicationNameis already set — becauserefreshNodeIdentityis called from bothonClientInfo(which fires before the node'starget.objectis populated, and would otherwise pinapplicationNameto"QEMU"for the lifetime of the stream) andonNodeInfo(which fills intarget.objectlater). QEMU's PipeWire backend never setsapplication.nameon its own, so there is no other source of application identity for this stream that we could be clobbering.Reproduction
On a libvirt-managed QEMU VM with
<audio type="pipewire">and a<sound>device, open the audio panel's "Application Volumes". The QEMU stream is missing. The same stream is visible inpavucontroland listed inwpctl statusas a Stream.pw-cli info <id>on the QEMUStream/Output/Audionode confirms:node.name = "qemu-system-<arch>"target.object = "<libvirt <input>/<output> name>"application.nameandapplication.idnot setVerification
meson setup build && ninja -C build— 688/688 targets compile and link cleanly.meson test -C build— 22/22 pass.src/pipewire/pipewire_service.cpp, +31 / −3).Result
based on QEMU config:
Risk
With this change, any PipeWire node with
target.objectset (e.g. a virtual sink feeding another virtual sink) will now appear in Application Volumes. On the reporter's system there are zero such nodes besides QEMU; if a future use case needs to keep hiding a particular category oftarget.objectstreams, that should be added as a follow-up with a more specific predicate.