Skip to content

Instantly share code, notes, and snippets.

@Markus00000
Last active February 24, 2023 06:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Markus00000/ad8c0ff46290f9dc2887 to your computer and use it in GitHub Desktop.
Save Markus00000/ad8c0ff46290f9dc2887 to your computer and use it in GitHub Desktop.
Song ratings with playlists in cmus
#!/bin/bash
# Usage: cmus-rate [1-5]
#
# Rate tracks playing in cmus and add them to corresponding playlists.
#
# The track currently playing in cmus is added to an M3U playlist corresponding
# to the given rating ("[1-5].m3u") and removed from any other rating playlist.
# If no argument is given, the track is removed from all rating playlists.
#
# The playlists are kept sorted.
# Path to playlists
playlists="$HOME/music"
# Prefix and suffix strings for playlist filenames
pl_prefix=''
pl_suffix='.m3u'
# Get currently playing track from cmus
track=$(cmus-remote -Q | grep file)
# Errors
# + Inaccessible playlist directory
if [ ! -d "$playlists" ]; then
mkdir -p "$playlists"
if [ ! -d "$playlists" ]; then
notify-send 'cmus-rate' 'Rating failed: Failed to create playlist directory.'
exit 1
fi
fi
# + No track playing
if [ -z "$track" ]; then
notify-send 'cmus-rate' 'Rating failed: No track is currently playing.'
exit 1
fi
# + Incorrect argument given
if [ -n "$1" ] && { [ "$1" -lt 1 ] || [ "$1" -gt 5 ]; }; then
notify-send 'cmus-rate' "Rating failed: Incorrect argument given ($1)."
exit 1
else
rating="$1"
fi
# Path to lock file
lock='/tmp/cmus-rate.lock'
# Lock the file (other atomic alternatives would be "ln" or "mkdir")
exec 9>"$lock"
if ! flock -n 9; then
notify-send 'cmus-rate' 'Rating failed: Another instance is running.'
exit 1
fi
# Strip "file " from cmus output
track=${track/file \///}
# Temporary file for grepping and sorting
tmp="$playlists/tmp.m3u"
# Remove track from all rating playlists
for n in {1..5}; do
f="$playlists/${pl_prefix}$n${pl_suffix}"
if [ -f "$f" ] && [[ $(grep -q "$track" "$f") -eq 0 ]]; then
grep -vF "$track" "$f" > "$tmp"
mv -f "$tmp" "$f"
fi
done
# Append track to new rating playlist
if [ -n "$rating" ]; then
f="$playlists/${pl_prefix}$rating${pl_suffix}"
printf '#EXTM3U\n%s' "$track" >> "$f"
sort -u "$f" -o "$tmp"
mv -f "$tmp" "$f"
fi
# The lock file will be unlocked when the script ends
@sebw
Copy link

sebw commented Mar 26, 2021

Does the script actually work? See cmus/cmus#1066 (comment)

@Markus00000
Copy link
Author

@sebw The script has been working for years. (I have made some minor changes in a new revision.)

@kostabekre
Copy link

kostabekre commented Feb 24, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment