Pulseaudio: auto switch sink when headphones connected

pulseaudio

I'm running XUbuntu 16.04. Previously I had speakers connected to analog line-out, and sound would automatically switch over to headphones when they were plugged in. This was all happening on one output device (motherboard audio).

I've now got a new monitor with built-in speakers, but no analog connection, so I'm getting audio over DisplayPort from my Radeon R9 270. I'd like pulseaudio to switch existing streams and new streams to the headphone port on the motherboard audio when I plug in the headphones, and back to the DP audio port on the GPU device when I unplug them again.

I've tried using pactl load-module module-switch-on-connect, but it doesn't seem to have any effect, presumably because plugging in the headphones doesn't create a new sink, only a new port.

I know from reading other questions that I can do this manually with pactl/pacmd invocation and I'll do that if I have to, but I'd much prefer to have this happen automatically. I don't mind if I have to do some scripting to do it, but is there a hook I can intercept to get a call when the headphones are connected or disconnected?

Best Answer

I figured out a solution thanks to this discussion and paswitch. In summary, acpid can be used to hook the headphone plug/unplug events.

I created the following files:

/etc/acpi/events/headphone-jack:

event=jack/headphone
action=/etc/acpi/headphone-jack.sh %e

/etc/acpi/headphone-jack.sh (remember to make it executable):

#!/bin/bash
set -e -u

if [ "$1" = "jack/headphone" -a "$2" = "HEADPHONE" ]; then
    case "$3" in
        plug)
            sink=alsa_output.pci-0000_00_1b.0.analog-stereo
            ;;
        *)
            sink=alsa_output.pci-0000_01_00.1.hdmi-stereo
            ;;
    esac
    for userdir in /run/user/*; do
        uid="$(basename $userdir)"
        user="$(id -un $uid)"
        if [ -f "$userdir/pulse/pid" ]; then
            PULSE_RUNTIME_PATH="$userdir/pulse" su "$user" -c "paswitch $sink"
        fi
    done
fi

The sinks naturally need to be updated depending on your system.

I'm not sure how robust the script is to an actual multi-user system, but it works for me.