Elmord's Magic Valley

Computers, languages, and computer languages. Às vezes em Português, sometimes in English.

Fixing audio device priorities in PulseAudio

2023-10-31 16:45 +0000. Tags: comp, unix, audio, in-english

Ever since I started using my current laptop (a ThinkPad E14 Gen 4, currently running Debian 12), I have had the following issue: when I connect headphones to the laptop, the audio goes to the headphones as expected, but when I disconnect the headphones, the audio goes to the HDMI output instead of going back to the laptop speakers. As it happens, my external monitor (an Eizo FlexScan EV2360) has audio output, but it’s pretty low-quality and I don’t use it. But PulseAudio (or is it ALSA?) assigns higher priority to the HDMI outputs, so as soon as the headphones are disconnected, it looks for the available device with the highest priority and picks the HDMI one. You can see the priority of each audio sink (output) by using pactl:

$ pactl list sinks | grep priority:
        [Out] HDMI3: HDMI / DisplayPort 3 Output (type: HDMI, priority: 700, not available)
        [Out] HDMI2: HDMI / DisplayPort 2 Output (type: HDMI, priority: 600, not available)
        [Out] HDMI1: HDMI / DisplayPort 1 Output (type: HDMI, priority: 500, available)
        [Out] Speaker: Speaker (type: Speaker, priority: 100, availability unknown)
        [Out] Headphones: Headphones (type: Headphones, priority: 200, not available)

In this case, the HDMI1 output is available and has priority 500, whereas the speakers have priority 100.

The solution is to change the HDMI priorities. The problem is where to set this. In my particular case, this was set in /usr/share/alsa/ucm2/Intel/sof-hda-dsp/Hdmi.conf (included from /usr/share/alsa/ucm2/Intel/sof-hda-dsp/Hdmi.conf), which looks like this:

# Use case Configuration for sof-hda-dsp

Include.hdmi.File "/codecs/hda/hdmi.conf"

If.hdmi1 {
    Condition { Type AlwaysTrue }
    True.Macro.hdmi1.HDMI {
        Number 1
        Device 3
        Priority 500

If.hdmi2 {
    Condition { Type AlwaysTrue }
    True.Macro.hdmi1.HDMI {
        Number 2
        Device 4
        Priority 600

If.hdmi3 {
    Condition { Type AlwaysTrue }
    True.Macro.hdmi1.HDMI {
        Number 3
        Device 5
        Priority 700

I just changed the values 500, 600, 700 manually to 50, 60, 70 in this file. This is not a very good solution because this file belongs to the alsa-ucm-conf package and will get overridden whenever I upgrade it, but since this is Debian stable, I don’t have to worry about this any time soon. There is probably a better way to override these values, but I don’t know enough about either ALSA or PulseAudio (and I’m not particularly keen on learning more, unless my fellow readers know and want to leave a helpful comment), so this will have to do for now.

* * *

Another recurring issue is getting Bluetooth headphones to become the selected default device when they are connected. It seems that Bluetooth devices get created dynamically with a bunch of hardcoded priorities (and worse, sometimes I get a device with priority 40 and sometimes 0, I don’t know why). But it also seems that the priorities just don’t have any effect on the selection of the Bluetooth device. I was having a curious issue where some programs would pick the headphones and some wouldn’t, and the default device would remain unchanged (which among other things meant that my multimedia keys set the volume of the wrong device). What seems to be going on is that PulseAudio remembered the associations of certain programs (e.g., VLC) with the headphones, but only for those programs where I had at some point manually changed the output sink manually via pavucontrol. The solution here was two-step:

  1. In /etc/pulse/default.pa, replace the line that says:

    load-module module-stream-restore


    load-module module-stream-restore restore_device=false

    This will make PulseAudio not try to remember associations between specific programs and devices. From now on, all programs get the default sources/sinks when they connect to PulseAudio.

  2. Set the default sink manually to the Bluetooth headphones. Use pactl list sinks to figure out the sink name:

    $ pactl list sinks  | grep Name:
            Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_5__sink
            Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_4__sink
            Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_3__sink
            Name: alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp__sink
            Name: bluez_sink.C8_7B_23_9F_B3_21.a2dp_sink

    Then set it (replacing with the appropriate device name):

    pactl set-default-sink bluez_sink.C8_7B_23_9F_B3_21.a2dp_sink

The result of this is that PulseAudio will remember the headphones as the default sink device when they are present, but will revert to the built-in sound card when not.

I still don’t know why this works even though the Bluetooth device’s priority is lower than the built-in sound card. (There is a PulseAudio module called module-switch-on-connect that provides behavior like this, but it is not enabled on my system, and it does not show up as loaded in the pactl list output.) But It Works For Me™.

Comentários / Comments (0)

Deixe um comentário / Leave a comment

Main menu

Recent posts

Recent comments


em-portugues (213) comp (147) prog (70) in-english (61) life (48) unix (38) pldesign (36) lang (32) random (28) about (28) mind (26) lisp (24) mundane (22) fenius (21) web (20) ramble (18) img (13) rant (12) hel (12) privacy (10) scheme (10) freedom (8) esperanto (7) music (7) lash (7) bash (7) academia (7) copyright (7) home (6) mestrado (6) shell (6) android (5) conlang (5) misc (5) emacs (5) latex (4) editor (4) etymology (4) php (4) worldly (4) book (4) politics (4) network (3) c (3) tour-de-scheme (3) security (3) kbd (3) film (3) wrong (3) cook (2) treta (2) poem (2) physics (2) x11 (2) audio (2) comic (2) lows (2) llvm (2) wm (2) philosophy (2) perl (1) wayland (1) ai (1) german (1) en-esperanto (1) golang (1) translation (1) kindle (1) pointless (1) old-chinese (1)


Quod vide

Copyright © 2010-2023 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.

Powered by Blognir.