WirePlumber

From ArchWiki

WirePlumber is a powerful session and policy manager for PipeWire. Based on a modular design, with Lua plugins that implement the actual management functionality, it is highly configurable and extendable.

Installation

Install the wireplumber package. It will conflict with other PipeWire Session Managers and make sure they are uninstalled.

WirePlumber uses systemd/User for management of the server.

Optionally, install wireplumber-docs to review the documentation.

Configuration

WirePlumber's modular design confers lots of flexibility when it comes to swapping the implementation of a specific functionality without having to re-implement the rest of it. Detailed information can be found at the official documentation.

Below we add examples of simple configurations.

Obtain interface name for rules matching

In WirePlumber's Lua scripts, you need to specify matches rules with PipeWire objects of the target interface you want to configure.

Use the commands pw-cli list-objects and pw-cli dump to show all available objects in the system.

Object Node are sinks or sources in the PipeWire graph. They correspond to the ALSA Device.

To filter what type to show, add the list-objects option with one of [Device|Node]. For example:

$ pw-cli list-objects Device
...
id 37, type PipeWire:Interface:Device/3
 	object.serial = "264"
 	factory.id = "14"
 	client.id = "49"
 	device.api = "alsa"
 	device.description = "Starship/Matisse HD Audio Controller"
 	device.name = "alsa_card.pci-0000_08_00.4"
 	device.nick = "HD-Audio Generic"
 	media.class = "Audio/Device"
...

Object type filtering also applies to the pw-cli dump command.

If you are looking for specific class of the endpoint (ex. “Audio/Sink”), see the media.class property.

In most cases, when configuring ALSA the property you need is either device.name or node.name.

Tip: The command pw-top show a list of Node currently in use.

Changing a device/node property

To change a device or node property, such as its description or nick, you must create a Lua script and add it into ~/.config/wireplumber under the proper path and name.

For instance, to change the description of an ALSA node, you would create a file such as ~/.config/wireplumber/main.lua.d/51-alsa-rename.lua with the following content:

51-alsa-rename.lua
rule = {
  matches = {
    {
      { "node.name", "equals", "alsa_output.pci-0000_00_1f.3.output_analog-stereo" },
    },
  },
  apply_properties = {
    ["node.description"] = "Laptop",
  },
}

table.insert(alsa_monitor.rules,rule)

If instead you wish to change something on a Bluetooth node or device, you could create ~/.config/wireplumber/bluetooth.lua.d/51-rename.lua with a content such as:

51-rename.lua
rule = {
  matches = {
    {
      { "node.name", "equals", "bluez_output.02_11_45_A0_B3_27.a2dp-sink" },
    },
  },
  apply_properties = {
    ["node.nick"] = "Headphones",
  },
}

table.insert(bluez_monitor.rules,rule)

The Lua scripts' filenames and locations are thus devised in a way that allows WirePlumber's Multi-path merging to run them just after the default configuration files (e.g. /usr/share/wireplumber/main.lua.d/50-alsa-config.lua) but before the file that loads and enables the devices (e.g. /usr/share/wireplumber/main.lua.d/90-enable-all.lua).

The properties that you can change as well as the matching rules to select devices or nodes are documented at ALSA configuration and Bluetooth configuration.

Disable a device/node

Since WirePlumber v0.4.7, users could now disable any devices or nodes by property device.disabled or node.disabled

~/.config/wireplumber/main.lua.d/51-alsa-disable.lua
rule = {
  matches = {
    {
      { "device.name", "equals", "alsa_card.pci-0000_08_00.4" },
    },
  },
  apply_properties = {
    ["device.disabled"] = true,
  },
}

table.insert(alsa_monitor.rules,rule)

For the name of alsa_card.* in your system, see #Obtain interface name for rules matching

Note: Common use-case, for example, is to disable NVIDIA's HDMI audio output.

Simultaneous output to multiple sinks on the same sound card

Create a copy of /usr/share/alsa-card-profile/mixer/profile-sets/default.conf so that changes persist across updates. Here we define a profile joining the two default mappings for Analog and HDMI.

/usr/share/alsa-card-profile/mixer/profile-sets/multiple.conf
[General]
auto-profiles = no

[Mapping analog-stereo]
device-strings = front:%f
channel-map = left,right
paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
priority = 15

[Mapping hdmi-stereo]
description = Digital Stereo (HDMI)
device-strings = hdmi:%f
paths-output = hdmi-output-0
channel-map = left,right
priority = 9
direction = output

[Profile multiple]
description = Analog Stereo Duplex + Digital Stereo (HDMI) Output
output-mappings = analog-stereo hdmi-stereo
input-mappings = analog-stereo

Now we configure Wireplumber to use the new card-profile for matching devices. For identifying information see #Obtain interface name for rules matching. We apply the configuration systemwide by creating a Lua script in the new directory # mkdir -p /etc/wireplumber/main.lua.d with a number prefixed filename starting after 50-alsa-config.lua:

/etc/wireplumber/main.lua.d/51-alsa-custom.lua
rule = {
  matches = {
    {
      { "device.nick", "matches", "HDA Intel PCH" },
    },
  },
  apply_properties = {
    ["api.alsa.use-acp"] = true,
    ["api.acp.auto-profile"] = false,
    ["api.acp.auto-port"] = false,
    ["device.profile-set"] = "multiple.conf",
    ["device.profile"] = "multiple",
  },
}
table.insert(alsa_monitor.rules,rule)

See also