How to Configure Audio Device Priorities in Pipewire / Wireplumber
I have several audio devices connected to my Linux desktop machine, including a USB audio interface (a MOTU M4), and a Jabra wireless headset that uses a USB dongle, and appears as its own audio device. I also like to use Bluetooth headphones on a daily basis.
After switching to Pipewire as my audio backend, I found that my default audio device wasn’t switching automatically to what I wanted – I’d always have to set it manually. I’d need to do this when my BT headphones would connect (select the a2dp headphone profile), and then again when I disconnected them (because I wanted to hear sound from my MOTU audio interface, but it would automatically fallback to the Jabra headset device). This is a two-part recipe to fix these issues.
Step 1: Make pipewire automatically select my Bluetooth headphones sink when they connected. This didn’t require any configuration changes. Instead, I have a script which runs on startup of my desktop environment which runs pactl load-module module-switch-on-connect
. This is actually a pulseaudio command, but desktop apps still use the pulseaudio interface, which pipewire implements as part of the pipewire-pulse package.
Step 2: Make my default audio device my MOTU M4 audio interface, and stop selecting the Jabra headset device when I disconnect my BT headphones. This turned out to be caused by the fact that the Jabra audio device had a higher priority than my audio interface. Run the command wpctl status
to show a list of your audio devices, and make a note of the device number. In this case, I was looking for the M4 device in my list of Audio Sinks. Then you can run wpctl inspect <device-number>
to show the details of this audio device. What you’re looking for are the fields priority.driver
and priority.session
. Larger numbers correspond to a higher priority, but for sinks, they should be kept no larger than 1500 (otherwise a sink’s monitor could end up being selected as a default source – this is called out in the Wireplumber documentation). In my case, the Jabra sink had a priority of 1008, so I chose to set my audio interface to a priority of 1050.
Update May 2024: Wireplumber as of v0.5 no longer uses lua scripts for configuration. Check which version of wireplumber you’re using, and if you’re on 0.5, please refer to this guide to update the lua script below to the new format (and file location). I’ll update this blog post further when I have the time.
To change this configuration, you’d do so in Pipewire’s session manager. The preferred session manager for Pipewire is Wireplumber, which uses lua scripts to apply these kinds of custom configurations. So in my case, I created the file ~/.config/wireplumber/main.lua.d/60-raise-motu-m4-priority.lua
with the following code:
rule = {
matches = {
{
{ "node.name", "equals", "alsa_output.usb-MOTU_M4_M4MC0570FU-00.Direct__hw_M4__sink" },
},
},
apply_properties = {
["priority.driver"] = 1050,
["priority.session"] = 1050,
},
}
table.insert(alsa_monitor.rules,rule)
Then, restart the wireplumber service with systemctl --user restart wireplumber
and compare the new output from wpctl inspect
. You should now see that the driver and session priorities are what you set them to. And when pipewire automatically switches to a new audio device, the highest priority device should be chosen.
I’ve found Pipewire and Wireplumber’s documentation to be confusing, and there are lots of dead-ends you can go down when researching how to do this. I hope this recipe-style blog post is easier to understand if this is the problem you’re trying to solve.
Many thanks to PleasantlyFlailing on the r/linuxaudio subreddit for suggesting some improvements to this blog post!