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