MPD Utility to Add Gap Between Songs

In the documentation for music players, you almost always see the claim of support for “gap-less playback”. Never a mention of adding a gap between songs.

But I have often wished for a way to add a gap of a few seconds between songs. You would think any software which can remove gaps would also be able to add gaps. They can’t. There is a plugin available for MediaMonkey which does add gaps between songs (which confirms my use case isn’t totally nutty, right?), but I don’t use MediaMonkey any more.

I now play my music at home using a dedicated music server, a Raspberry Pi 3 computer, running Linux and the MPD music player software. I have search for an add-gap-between-songs utility for MPD, but to no avail. So I ended up writing one.

It consists two files, (a) a simple shell script of about a dozen lines (not counting comments), and (b) a systemd service unit file.

The unit file is saved to /usr/local/bin/gap.sh.


#!/bin/sh

#Script name = gap.sh

#Location: /user/local/bin/

#Adds a gap between songs.For use with the MPD music player.

#Tested OK with bash and dash - but mostly with dash (Debian's default shell).

#Parameters:

  #1 - Gap delay time, in seconds. Default: 5

  #2 - Server name where MPD is running. Default: tynmanpi01

#MPD does not expose an end-of-song event. But for the purposes of adding the gap

#between songs, it can be faked. When MPD is running in "single" mode, it "pauses"

#at the end of each song. We can detect that.

#

#The "end-of-song" pseudo-event is detected as follows:

#- Use the MPC idle command to wait for a "player" event.

#- Get the MPD status using the MPC command without any options. When a song is either

#   playing or paused, the MPC command returns three lines of output.

#- Use grep to parse the results for both strings: '[paused]' AND '(0%)', on the same line.

#- The '(0%)' indicates the pause occurred as a result of an end-of-song event, as opposed to

#   the user having intentionally paused the playback. We don't want to run the

#   wait-and-resume-play code if the user has intentionally paused the playback.

#If an end-of-song pseudo-event is detected, wait for GAP_DELAY seconds and issue an MPC PLAY

#command to resume playing.

#Note 1 - While this script is running, the gap-between-songs can be effectively turned off

#and back on by the user by toggling MPD's "single" mode using an MPD client software.

#E.g., in Cantata, single mode may be toggled with the "1" icon in the bottom

#right corner of the window. In NCMPCPP, it can be toggled with the "y" key.

#Note 2 - If the user issues a pause at exactly the wrong time (between songs), there is a slight

#(maybe zero) chance the script will highjack their intent and start playing the next song after

#the delay. I haven't seen this happen and it may not even be possible.

GAP_DELAY=${1:-5}

MPD_SERVER=${2:-tynmanpi01}

printf "\n%s\n" "$0 $(date +"%Y%m%d-%H%M%S") - Starting."

printf "%s\n" "$0 $(date +"%Y%m%d-%H%M%S") - Gap delay set to ${GAP_DELAY} seconds."

#Ensure MPD is running in "single mode"

mpc -h ${MPD_SERVER} single on

mpc -h ${MPD_SERVER}

while true

do

  #Wait for an MPD "player" event. (A "player" event occurs on play, stop, pause, or seek..)

  mpc -h ${MPD_SERVER} idle player

  #Is MPD paused between songs?

  if mpc -h ${MPD_SERVER} | grep '\[paused\]' | grep '(0%)'; then

    printf "\n%s\n" "$0 $(date +"%Y%m%d-%H%M%S") –Paused between songs. To sleep for ${GAP_DELAY} seconds..."

    sleep ${GAP_DELAY}s

    printf "\n%s\n" "$0 $(date +"%Y%m%d-%H%M%S") - Awake."

    mpc-h ${MPD_SERVER} play

  fi

done

Code: gap.sh

A systemd service unit file, mpd-gap.service, is deployed to run the script as soon as MPD starts on the music server.
The unit file is saved to /etc/systemd/system/.

[Unit]

Description=Add gap between songs

After=mpd.service

[Service]

Type=idle

ExecStart=/usr/local/bin/gap.sh 10 tynmanpi01

[Install]

WantedBy=multi-user.target

Code: mpd-gap.service

Enable the service with,

$ sudo systemctl enable mpd-gap

Return to Tyndall Park