You are not logged in.

#1 2025-05-31 17:02:10

Gozbyn
Member
Registered: 2025-03-17
Posts: 5

WirePlumber .conf Won't Load "section '[...]' has no value"

I have been trying to set up some custom audio routing logic with some virtual audio devices. Put simply, I want to route my applications through some virtual Audio/Duplex nodes so that I can micromanage the volume of groups of apps through some scripting activated by my Stream Deck.

The issue is that I have been unable to correctly configure a .conf file to make routing of application audio automatic. It fails to load when WirePlumber starts, with an error message logged which I have been unable to find sufficient documentation on.

I have been able to verify that I have set up and can use the virtual audio devices in the way I desire by using qpwgraph/QjackCtl to manually connect nodes while audio sources are active. However, I have been unable to achieve persistence of routing rules/configurations.

Due to applications' identifiers being dynamic and some names being shared between sources (such as different apps being separate instances of Chromium), the solution I believe should work best is using .conf files to tell WirePlumber how to route certain programs by default. My hope is that setting these rules will allow for certain Stream/Output/Audio nodes to be automatically routed to a predefined virtual Audio/Duplex node immediately upon being created.

Put more simply, the logic I desire WirePlumber to enact is "automatically route these applications to this audio sink instead of the default device."

Here is my current .conf file stored in /home/my_username/.config/wireplumber/wireplumber.conf.d:

# 51-custom-app-routing.conf

# to help find usable attributes for new routing rules, the following command has been useful:
# pw-dump | jq '.[] | select(.type == "PipeWire:Interface:Node") | {name: .info.props."application.name", applicationBinary: .info.props."application.process.binary", processBinary: .info.props."process.binary", class: .info.props."media.class", role: .info.props."media.role", target: .info.props."node.target"}'

wireplumber.settings = {
    device.rules = [

        # -- route games
        {
            # windows games launched by Steam run under the Wine binary
            matches = [ { .info.props."application.process.binary" = "wine64-preloader" } ]
            actions = { update-props = { node.target = "gameAudio" } }
        },
        {
            # it seems native linux games launched by Steam are only identifiable by their name being SDL Application
            matches = [ { .info.props."application.name" = "SDL Application" } ]
            actions = { update-props = { node.target = "gameAudio" } }
        },
        {
            # as a fallback, hopefully all games will have their role set to game
            matches = [ { .info.props."media.role" = "Game" } ]
            actions = { update-props = { node.target = "gameAudio" } }
        },

        # -- route music app audio
        {
            matches = [ { .info.props."application.process.binary" = "Cider" } ]
            actions = { update-props = { node.target = "musicAudio" } }
        },

        # -- route browser audio
        {
            matches = [ { .info.props."application.process.binary" = "firefox" } ]
            actions = { update-props = { node.target = "browserAudio" } }
        },

        # -- route wallpaper/background audio
        {
            matches = [ { .info.props."application.name" = "mpv" } ]
            actions = { update-props = { node.target = "wallAudio" } }
        },

        # -- route Discord (vesktop)
        {
            matches = [ { .info.props."application.process.binary" = "vesktop" } ]
            actions = { update-props = { node.target = "voiceAudio" }}
        },

        # -- Route all other applications to systemAudio as a catch-all case
        {
            matches = [ { } ]
            actions = { update-props = { node.target = "systemAudio" } }
        }
    ]
}

I first tried to program the solution in a .lua file, which has much more documentation and published examples from other users, but then learnt that it must be in a .conf under the new SPA-JSON format since WirePlumber 0.5. It seems that there is significantly less documentation on the 0.5+ SPA-JSON format, so I have been unable to verify the correct approach to creating the logic I desire.

Throughout reformating the signature of the file to many different variations in an attempt to change the outcome, I have consistently gotten variants of the same following error message upon WirePlumber being started:

Jun 01 00:40:06 my_pc_name wireplumber[79689]: wp-conf: <WpConf:0x559d1fbeb840> failed to open '/home/my_username/.config/wireplumber/wireplumber.conf.d/51-custom-app-routing.conf': section 'wireplumber.settings' has no value

when running:

systemctl --user restart wireplumber

then:

journalctl --user-unit wireplumber -b

The returned error/warning for the failed opening has stayed consistent with all of the formats for the wrapper/s of my rules (e.g. monitor.alsa.rules, monitor.rules, context.objects). I am hoping I just haven't tried the correct wording/format with braces and brackets for this yet, but would appreciate any pointers about this or anything else I could try.

I have looked at the following pages as part of my research, but have been unable to find solid information on how to format the SPA-JSON correctly for my own use-case. Most of the example cases I have found are based on editing simple properties for ALSA cards, and unless I misunderstand how ALSA insteracts here, I'm pretty sure those formats don't apply (namely the top of the file for which table to insert rules into).

Freedesktop's WirePlumber page on the configuration files
Arch Wiki page on WirePlumber
Arch Forum thread on 0.5 changes to configuration in WirePlumber
This page on the new format

Any help to solve the error, or pointers for a new strategy to try would be awesome.

Last edited by Gozbyn (2025-06-04 08:51:40)

Offline

Board footer

Powered by FluxBB