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.
2 Answers
Ok, so you will need to do a few things for this:
- Detect when the headphones are unplugged;
- After the event in (1), send a "pause" command to VLC;
- Detect when the headphones are pluggd back in;
- 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.
-
1Thanks 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_uaJun 25, 2015 at 7:27
-
1
-
3You 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 Jun 29, 2015 at 0:31 -
2ACPI handles headphones unplug, will you add this to your answer? askubuntu.com/a/642404/20275– int_uaJun 30, 2015 at 11:36
-
Ok, so based on what I have learned from here, I am trying a new approach, using ACPI.
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
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
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.
-
1to 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. Jun 30, 2015 at 21:22
-
1Well spotted. Here is the cleanest way I could think of to do that. No need for autostart scripts and whatnot.– StuntsJun 30, 2015 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.dzJul 1, 2015 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.– StuntsJul 1, 2015 at 8:39
-
1You could still improve the answer by using %e, and using only a single script file. See this. Jul 1, 2015 at 8:39