How to pause VLC playback when the headphones are disconnected?

How is it possible to pause the playback of VLC when my headphones are plugged out? I can mute the speakers via ALSA, but I want to use the plug trigger to stop the playback, as it is usual in smartphones.


Solution 1:

Ok, so you will need to do a few things for this:

  1. Detect when the headphones are unplugged;
  2. After the event in (1), send a "pause" command to VLC;
  3. Detect when the headphones are pluggd back in;
  4. After the event in (3), send a "play" command to VLC;

For (1) and (3): You can use what is shown here. This answer contains a small procedure to find the difference between a plugged and unplugged jack, and a script that you can modify to conform to your case.

For (2) and (4): You should use VLC's Dbus interface. The relevant code should be this:

dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Pause

dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Play

For pause and play respectively.

Now, about the script. In your case, it should look something like this:

#!/bin/bash
# This scripts detecs unplugging headphones.

oldstatus="unrelated string"
while [ 1 ]; do
    # The following line has to be changed depending on the difference (use diff) in '/proc/asound/card0/code#0'
    status=$(grep -A 4 'Node 0x16' '/proc/asound/card0/codec#0' |  grep 'Amp-Out vals:  \[0x80 0x80\]')
    if [ "$status" != "$oldstatus" ]; then
        if [ -n "$status" ]; then
            echo "Plugged in"
             dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Play
            oldstatus="$status"
        else
            echo "Unplugged"
            dbus-send --print-reply --session --dest=org.mpris.vlc /Player org.freedesktop.MediaPlayer.Pause
            oldstatus="$status"
        fi
    fi
    # Now sleep for 250 milli-seconds as per @Serg's request (who learnt if from @Fabby)
    # sleep is timer-based so doesn't use *any* processor cycles while sleeping.
    sleep 0.25
done

Add this modified script to your startup applications, and you're set. I think it should do what you wanted to.

PS - Note that there are more efficient ways to do this, such as using inotify to detect event changes (and maybe even other approaches), but this one should get you started (and the others are above my skill level and experience). I suppose you can start with this "hackish" approach, and build up from here.

Solution 2:

Ok, so based on what I have learned from here, I am trying a new approach, using ACPI.

  1. Create a script, for pausing and unpausing VLC:

    sudo touch /etc/acpi/headphone_jack.sh
    sudo chmod +x /etc/acpi/headphone_jack.sh
    

    and place the following on this file:

    _pid=`pgrep vlc`
    _pid="${_pid% *}"
    DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$_pid/environ | sed -e 's/DBUS_SESSION_BUS_ADDRESS=//'`
    _username=`grep -z USER= /proc/$_pid/environ |sed 's/.*=//'`
    
    if [ "$3" = unplug ]; then
        su $_username -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Pause"
    else
        su $_username -c "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS dbus-send --print-reply --session --dest=org.mpris.MediaPlayer2.vlc /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Play"
    fi
    
  2. Now let's create an event trigger (replace vim with your favourite text editor):

    sudo vim /etc/acpi/events/headphones
    

    and add the following:

    event=jack/headphone
    action=/etc/acpi/headphone_jack.sh %e
    
  3. Finally, restart the ACPI daemon:

    sudo service acpid restart
    

I think the should be exactly what you require, with no polling involved. The only drawback I can find with this implementation is in case you have multiple users running VLC at the same time. I suppose in that case, what can happen is that this approach will randomly pause and resume one of them (or it might simply not work).

Big Kudos to @int_ua and @Sneetsher for providing me with important knowledge regarding ACPI event handling. Also thumbs up to @user3073656 for helping simplify the procedure.