0

I want to pause playback after headphones have been unplugged, then resume after they were plugged back in.

My current solution uses ACPI to detect plug / unplug, as shown here. To play / pause the playback, I use xdotool key XF86AudioPlay.

This solution works fine in the basic case:

  • music is playing, headphones are plugged in
  • headphones are unplugged -> music pauses
  • headphones are plugged back in -> music continues playing.

However, I do not want to resume playback if it wasn't active when the headphones were unplugged.

Imagine this scenario:

  • start up the PC with headphones in,
  • play music,
  • pause music,
  • unplug headphones,
  • plug headphones back in.

The last point is where the problem lies – the playback would resume after the headphones are plugged back in, although it was not active at the time they were unplugged.

Moreover, xdotool key XF86AudioPlay simply toggles the playback, whereas xdotool key XF86AudioPause does nothing. That makes things even worse:

  • start PC with headphones in,
  • play music,
  • pause music,
  • unplug headphones (MUSIC STARTS PLAYING!).

So what I need is to detect play / pause / stop events as well as plug / unplug events, to be able to correctly react in all possible scenarios.

This state machine describes the desired operation: Unplug-pause FSM


The one idea that came to my mind is to re-bind the keyboard shortcuts for play / pause / stop to add the state machine logic. This has the drawback that playback always has to be controlled using these keyboard shortcuts, instead of eg. Rhythmbox buttons, which is somewhat impractical.

Also, if I close Rhythmbox while playing, the state machine will stay in a playing state. Of course I could have a 'daemon' which will wait until Rhythmbox is closed, and then set the state to stopped. But what if it's not Rhythmbox that plays the music, what if it's for example VLC, etc.? This approach is ugly and unreliable, so I would like to avoid it.


My question: How to detect when media playback was paused / resumed / stopped?

  • If you are using Rythmbox (exclusively), you'll have to modify the source to make its internal state (playing/pausing/stopped) available to you, for example by writing the state to a file when it changes. You'll have to do the same for every other mediaplayer you use. – dirkt Sep 28 '17 at 5:24
  • @dirkt I have thought about that. Apart from Rhythmbox I only use VLC, with which it shouldn't be difficult to do detect if it's running / playing / etc. With Rhythmbox it's a little tricky. It would be fairly easy, using rhythmbox-client with parameters --check-running and --print-playing, if the latter didn't print the name of the song also when it's paused. Still, a relatively clean solution would be to add another option, eg. --is-paused or so. But then both rhythmbox and rhythmbox-client source would have to be modified. Also, I would prefer this to be portable across players. – kyrill Sep 28 '17 at 9:29
  • The easiest thing is really to modify the source(s). There is no generally accepted API to indicate what a media player is doing. Another thing you can do is to check the state of the Pulseaudio streams (e.g. with pacmd list-sink-inputs, look at state), but that requires the media player to pause the stream if it is paused (which some media players may do, and some may not, and I can't check for Rythmbox because I don't have it installed). – dirkt Sep 28 '17 at 9:53
  • Regarding modifying the sources: if I only wanted to support Rhythmbox, I could enable debug output from which I would know when the state changes to playing / paused / etc. But since Rhythmbox changes the sink state to CORKED after it's been paused, I will probably use the Pulseaudio approach – thanks for the suggestion! – kyrill Sep 28 '17 at 10:08
2

One option is to check the state of the Pulseaudio streams, e.g. with pacmd list-sink-inputs (look at state), or interacting directly with the Pulseaudio demon in a programming language of your choice.

That requires the media player to pause the stream (change state from RUNNING to CORKED) if the player itself is paused. Some media players may do that, and some may not.

  • 1
    You can also add that pactl subscribe can be used to listen for Pulseaudio events (eg. Event 'change' on sink-input #1). Then you use pacmd list-sink-inputs to find out whether the playback has been paused/stopped or started/resumed. – kyrill Sep 28 '17 at 19:53

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.