12

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.

5
+150

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.

  • 1
    to run any command that needs DBUS, you have to export the environment variable of the running dbus session. See Germar's comment on Sneetsher's answer. – daltonfury42 Jun 30 '15 at 21:22
  • 1
    Well spotted. Here is the cleanest way I could think of to do that. No need for autostart scripts and whatnot. – Stunts Jun 30 '15 at 22:53
  • @Stunts, that's the best approach I have seen to get target ENV. It is possible to get user same way grep -z USER /proc/$_pid/environ so it will work for all users in the machine (with single running session/vlc). I was looking for such option. – user.dz Jul 1 '15 at 0:40
  • @Sneetsher: Sweet! Looks much better now. It crossed my mind last night, but I was too tired last night to think about it clearly. Thanks for the push in that direction. – Stunts Jul 1 '15 at 8:39
  • 1
    You could still improve the answer by using %e, and using only a single script file. See this. – daltonfury42 Jul 1 '15 at 8:39
9

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.

  • 1
    Thanks a lot, that's really helpful. I'll reward the points in case no better answer is posted. The only thing I don't like is the constant polling, I've created a separate question for that: askubuntu.com/questions/640741/… – int_ua Jun 25 '15 at 7:27
  • 1
    I'll follow that question! I could use that knowledge. – Stunts Jun 25 '15 at 9:45
  • 3
    You could add a sleep 0.25 at the end, which is a quarter of a second delay. That eases up on CPU and still works fast enough. I use this sometimes in my own scripts,too – Sergiy Kolodyazhnyy Jun 29 '15 at 0:31
  • 2
    ACPI handles headphones unplug, will you add this to your answer? askubuntu.com/a/642404/20275 – int_ua Jun 30 '15 at 11:36
  • Awesome! I will work something with it tonight. – Stunts Jun 30 '15 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.