Down the drain: The elusive ‘default’ PulseAudio sink

There is no such thing as a default output device (or sink) in PulseAudio. It say so right there in the official documentation. There is something referred to as a fallback device which is used “if the stream has not been seen before”. Yet there is a configuration command called set-default-sink.

So where does that leave the user who wants a default device persistent across boots? The answer is: With a few challenges to climb, the greatest probably being insufficient documentation. Sadly, people seem to prefer griping about PulseAudio to tipping in and producing good docs.

In the name of documentation (and SCIENCE!) I have tried to test a few of the available and potentially default-relevant PulseAudio settings to see if I could get a surefire way for new streams to always play on the device I want them to. Here’s what I’ve come up with.

Let’s start by copying the file /etc/pulse/default.pa to ~/.config/pulse/default.pa if you don’t already have a local copy. Remember, PulseAudio runs per session. The local copy will make it so that the systemwide file is ignored so you don’t need to worry about aggregating or negating settings between configuration files and you will have the fallback option of deleting your local copy and starting over.

Let’s try the obvious and scroll to the bottom to uncomment the line:

#set-default-sink output

where you replace output with your preferred default sink. You either use indices or names but the former are not guaranteed to persist across sessions. You can get a list of both by issuing the command:

pactl list sinks short

Try rebooting a few times and check what is the fallback sink each time. This can be done using GUIs like pavucontrol or from the command line

pacmd list-sinks | grep -e 'name:' -e 'index'

will show you the same list as pactl list sinks short, only with an asterisk in front of the fallback device.

pacmd dump | grep default

will show you the configuration commands that result from your current setup (note that some commands are dynamically generated so it is not a static one-to-one representation of a file on disk), including what output and input devices are set with set-default-sink and set-default-source.

Now if all you have are an analog speakers out and a digital HDMI out, this might just be sufficient. However, I failed to consistently see this get the results I was hoping for. Mostly the fallback sink would be one of the two devices that my headset registers as.

Issue 1: The default device is not set consistently at boot

Suppose that I insert a wired USB headset or an external DAC in my PC while it’s running. Chances are I want to use it immediately so the default policy of switching to it s the new default makes sense. This is similar to how PulseAudio acts when you insert a headphone jack. I insert it, I probably want to use it.

My problem is that a permanently plugged in device will hijack your output in the exact same way simply because it connects via USB. You boot up with the device plugged in, the result is the same as if you waited for the boot to complete, then inserted the device. Aggravating this for wireless devices is that the associated antenna/dongle/plug tends to always be left in. However, whether or not it is plugged in is no indication as to whether the headset is turned on or not. By default therefore I more often than not do not have a working audio output or at least the one I want.

Can we change this behaviour? Let’s try. Two default.pa settings (or modules) seem to be particularly relevant here. First up is module-default-device-restore:

module-default-device-restore

Since 0.9.7. Automatically restore the default sink and 
source (configuration is saved in a file)

This does pretty much what it say on the tin. Change the fallback sink to device X, reboot and it will – all other things being equal – try to set the fallback device to device X. With an emphasis on try and all other things etc. Because there are may be other commands and modules trying to do the very same thing. I tried rebooting a number of times with an enabled module-default-device-restore listed before (in the line order of default.pa) the set-default-sink [output] where the module and the command were attempting to set different fallback devices and I ‘suceeded’ in getting different results on different boots despite the ‘setup’ (configuration and set fallback device on previous session) being the same. The simple answer is to not run these side by side. If you intend to have a persistent, constant fallback sink on boot, you should probably disable (comment out) module-default-device-restore.

The other module of interest is module-switch-on-connect:

module-switch-on-connect

Whenever a new sink or source appears, this module will 
switch the default sink/source to be the new sink/source, 
and will move all currently running streams to the new 
sink/source.

Do you know the feeling of swearing that you saw some behaviour earlier on and then when you try to replicate it doesn’t show? I suspect any computer user does. Well, I could have sworn that this module used to override my set-default-sink command in default.pa at boot but now it’s suspiciously respectful of it. Given that my desktop PC doesn’t make use of USB plug-in-plug-out headsets, USB DACs or bluetooth speakers, I still prefer disabling this (and it’s surrounding conditional lines) for good measure. If you do plug in digital sinks on a daily basis in order to use them upon plugin, you would probably want to keep it. Note that disabling this will not change behaviour when plugging in a headphone jack. That does not change the sink but the port of the sink. It’s still your onboard audio (in my desktop’s case: alsa_output.pci-0000_00_1f.3.analog-stereo) that acts as the destination for the stream it just pushes it out a different door/port. The module for the automatic port switching is module-switch-on-port-available and it is loaded by default.

Disable these two modules, set a permanent fallback sink with set-default-sink and you should consistently hit the same fallback device across boots regardless of what you have plugged in.

Issue 2: Some applications fall back on non-fallback devices

At the top of the post I quoted a line about how the fallback device would be used “if the stream has not been seen before”. So what happens if a stream “has been seen before”? And how does PulseAudio recognise a stream as a reincarnation of an old one, so to speak? Also, what is the desired behaviour? Do we want all new streams to always go to the fallback sink or are the exceptions?

Let’s try an example that should be easy to replicate: Open Firefox and start a YouTube video playing. In pavucontrol this should now reigster under the Applications tab as ‘AudioIPC Server’ (with a slightly more recognisable Firefox icon). If it isn’t playing on the fallback device, open GNOME sound settings and hit the fallback sink in the list of devices which should move all streams back there. Go back to pavucontrol and move this one particular stream to another sink. Then stop the playback and close Firefox. When you reopen Firefox and start some playback (same video, different video, internet radio, you name it) should the stream go to the fallback device or the one you moved the earlier? If you answered the latter, you’re in luck because this is the behaviour most people will see out of the box and I’ve found it to be persistent at least across a session.

I ran a few experiments to test more precisely how this works:

  • Does this behaviour apply when streams are auto-moved by GNOME sound settings? In other words: Change the fallback device in GNOME sound settings while the stream is playing and watch it move to the new fallback device. Close the stream (and the application for good measure). Now, reset the fallback device and restart the stream from the application. Will the stream play on the last sink it was moved to or the fallback device? It appears the ‘auto-move’ does not tie it to the new device. Only changing the stream’s sink in pavucontrol or using the command pacmd move-sink-input [stream index] [index / name of sink to move to] will have the ‘restore to sink’ effect.
  • Does it persists across boots? Yes, it does. My ÝouTube video continued on my headphones mono output after reboot despite the default sink being set to speakers.
  • Where is this connectilon saved? It seems to be saved in the memory of a running PulseAudio session and in the files in ~/.config/pulse. Clear out those files AND reboot (or just kill pulseaudio forcing it to restart) and the connection is severed and any streams from the application now play on the fallback sink when relauched.
  • How is it defined? It seems to go by the name of the application. The following line is an example of information on a stream which seems to tie an application identified by name to a sink:
module-stream-restore.id = "sink-input-by-application-name:AudioIPC Server"

Supporting this hypothesis is the following observation: I run multiple Firefox profiles and I can say that once a stream from the first profile has been moved to a specific sink, any new streams from the second profile will also start playing on the chosen sink (despite it not being the fallback sink).

It is a legitimate question of preference, though. Did you move the stream because this application should always default to this particular device or did you move it because you just needed it this one time on the headset, usb dac or whatever? To my mind the latter is the more obvious and useful behaviour. The few applications that warrant a close link to one sink in particular (e.g. a video conferencing application and a headset or webcam) usually have settings that allow you to define that in-application without relying on PA magic.

I have not definitively found a way to disable this. load-module module-stream-restore is interesting though. The accompanying comment seems to imply that it enables a memory of a stream, including mute state, volume and sink. In other words the behaviour we’ve been loking into. Comment it out, however, and the most immediate result is that it disables GNOME’s sound settings ability to automatically move all playing streams to the new fallback sink. The fallback device is changed but streams keep playing to the same device they did before the change. The module does have a specific boolean restore_device parameter with a comment that says: “Restore the selected sink/source (default to true)” However, setting this to false leads to auto-move no longer working and it does not seem to stop PulseAudio remembering the last sink an application played to.

The simple way to deal with it if it the behaviour is unwanted, would be to avoid singling out specific streams for moving to specific devices. Using the GNOME sounds settings to switch-and-move all streams would not give PulseAudio the idea that you wanted any particular stream permanently associated with a particular device.

3 Comments

Helpful, bookmarked.
PulseAudio is one of the key reasons I use Linux over Windows or Mac.
So sick of the dumbing down of everything tech.

Very helpful, thanks!
it was so annoying that all audio switched to a newly plugged in audio/Midi controller.
Fixed by commenting out “module-switch-on-connect”

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.