#!/bin/bash # THE FINAL SOLUTION # DEPENDENCIES: mpd, mpc, ncmpcpp # ANOTHER OPTION WOULD BE TO DMENU ALL THE OPTIONS, SO IT CAN BE RUN WITH ONLY ONE KEYBOARD SHORTCUT # AND I CAN'T HELP BUT THINK THAT THERE'S SOME WAY TO UNIFY THE PLAYLIST TYPES AND THE SINGLE-SONG BRANCH AND USE ONLY FLAGS INSTEAD OF IF # OH WELL # xargs -r is a thing # cdprev INSTEAD OF prev IF YOU'RE BINDING F10 SHORTCUTS=( 'FUNCTION | TERMINAL EQUIVALENT | RECOMMENDED KEYBIND' '---------------------------------------------------------------------------------------' 'Play Song | wide_play.sh | F8' 'Queue Song | wide_play.sh -q | F9' 'Notify-send Queue | wide_play.sh -n | F10' 'Play/Pause Song | wide_play_helper.sh -t | Shift+F8' 'Skip to Next Song | wide_play_helper.sh -n | Shift+F9' 'Go Back to Previous Song | wide_play_helper.sh -p | Shift+F10' 'Spawn ncmpcpp | CUSTOM | Ctrl+F8' 'Toggle Autoplay | wide_play_helper.sh -a | Ctrl+F9' 'Toggle Consume | wide_play_helper.sh -c | Ctrl+F10' 'Play Playlist | wide_play.sh -l | Ctrl+Shift+F8' 'Queue Playlist | wide_play.sh -lq | Ctrl+Shift+F9' 'Clear Playlist | wide_play.sh -c | Ctrl+Shift+F10' 'Increase Volume | wide_play_helper.sh -V | Shift+Upper side mouse button' 'Decrease Volume | wide_play_helper.sh -v | Shift+Lower side mouse button' ) playlist_flag=false queue_flag=false clear_flag=false current_song=$(mpc current -f "%position%" | head -n 1) MUSIC="$HOME/music" SONG="" ROFI_THEME="BernBlue" AUDIO_EXTENSIONS="(\.mp3|\.flac|\.wav|\.m4a|\.mp4|\.wma|\.aac)$" #E0E04B #AAAA00 function play_playlist() { $queue_flag || mpc clear # IF QUEUE FLAG IS FALSE, THEN CLEAR THE QUEUE mpc ls "$1" | grep -E "$AUDIO_EXTENSIONS" | $2 | sed -r "s|'|\\\'|g" | xargs -I{} mpc add "{}" # SHUFFLE/SORT AND PIPE EVERY SONG IN THE DIRECTORY (IGNORING ANY NESTED DIRECTORIES) INTO MPC $queue_flag || mpc play # IF QUEUE FLAG IS FALSE, PLAY THE FIRST SONG mpc single off # ENABLE AUTOPLAY } function play_song() { if ! $queue_flag; then mpc insert "$1" CURR_INDEX="$( mpc current -f "%position%" | head -n1 )" NEXT_INDEX="$( mpc queued -f "%position%" | head -n1 )" [[ -n "$NEXT_INDEX" ]] && mpc move "$NEXT_INDEX" "$CURR_INDEX" && mpc play "$CURR_INDEX" || mpc play else mpc add "$1" fi $queue_flag && mpc single off || mpc single on # TOGGLE AUTOPLAY BASED ON CIRCUMSTANCES } while getopts "hsnlqc" opt; do case $opt in h) echo -e "usage: $0 [-h help] [-n notify-send queue] [-l list] [-q queue] [-c clear]\n\nSuggested Keyboard Shortcuts:\n"; printf '%s\n' "${SHORTCUTS[@]}"; exit ;; # PRINT HELP IN TERMINAL s) [[ ! $(pgrep -x ncmpcpp) ]] && /usr/bin/urxvt -e sh -c "/usr/bin/ncmpcpp" ; exit ;; n) "$HOME/stuf/scripts/notification_wrapper.sh" "\n$( mpc playlist -f "%file%" | sed -r "${current_song}s|^|> |g" )" "WIDEPLAY" ; exit ;; # NOTIFY-SEND QUEUE VIA OWN WRAPPER l) playlist_flag=true; ROFI_THEME="BernViolet" ;; # SET PLAYLIST FLAG, CHANGE DMENU COLOR q) queue_flag=true; ROFI_THEME="${ROFI_THEME}Queue" ;; # SET QUEUE FLAG, CHANGE DMENU TEXT c) clear_flag=true; ROFI_THEME="BernRed" ;; # SET CLEAR FLAG, CHANGE DMENU COLOR/TEXT ?) echo "error: option -$OPTARG is not implemented"; exit ;; esac done if $clear_flag ; then CHOICE=$(echo -e "1. Keep only the currently playing song\n2. Clear everything\n3. Abort" \ | rofi -dmenu -i -no-custom -p "" -theme "$ROFI_THEME" -async-pre-read 3 -no-click-to-exit ) echo "$CHOICE" | grep "1" &> /dev/null && mpc crop echo "$CHOICE" | grep "2" &> /dev/null && mpc clear && mpc single on exit fi # FOR THE FOLLOWING TO WORK YOU NEED TO HAVE THE FOLLOWING KEYS UNBOUND IN YOUR ROFI CONFIG: # kb-accept-custom: ""; # kb-accept-custom-alt: ""; # kb-accept-alt: ""; KEYBINDS="-kb-custom-1 Shift+Return -kb-custom-2 Ctrl+Return -kb-custom-3 Alt+Return" if $playlist_flag ; then # FIND EVERY DIRECTORY WITH AN AUDIO FILE IN IT AND PIPE IT INTO ROFI PL_DIR=$( mpc listall | sed -r "s|\/[^\/]+?$|\/|g" | sort -V | uniq \ | rofi -dmenu -i -no-custom -p "" -theme "$ROFI_THEME" -async-pre-read 15 -no-click-to-exit $KEYBINDS ) KEYCODE="$?" if [[ -n $PL_DIR ]]; then case $KEYCODE in 10) SONG=$( mpc ls "$PL_DIR" | grep -E "$AUDIO_EXTENSIONS" | shuf | head -n1 | sed -r "s|'|\\\'|g" ) if [[ -n $SONG ]]; then play_song "$SONG" fi ;; 11) PL_PARENT="${PL_DIR%\/*\/}/" while IFS= read -r PL_SUBDIR; do play_playlist "$PL_SUBDIR" "sort -V" queue_flag=true done < <( mpc lsdirs "$PL_PARENT" | sort -V ) ;; 12) play_playlist "$PL_DIR" "shuf" ;; *) play_playlist "$PL_DIR" "sort -V" ;; esac fi else # FIND EVERY AUDIO FILE AND PIPE IT INTO ROFI, IN TWO LINES SONG=$( mpc listall | sort --version-sort | sed -r "s|(^([^\/]+\/)+)(([^\/])+$)|\1\n\3\x0f|g; $ s|.{1}$||" | paste -sd '\n\0' \ | rofi -dmenu -sep '\x0f' -eh 2 -i -no-custom -p "" -theme "$ROFI_THEME" -async-pre-read 15 -no-click-to-exit $KEYBINDS ) KEYCODE="$?" SONG=$( echo -e "$SONG" | paste -sd '' ) if [[ -n $SONG ]]; then case $KEYCODE in 10) mpc insert "$SONG" # $queue_flag && mpc single off || mpc single on # TOGGLE AUTOPLAY BASED ON CIRCUMSTANCES ;; 11) # THIS ONLY WORKS WITH LETTER-NUMBER SONG PREFIXES (e.g. MahoAko01, MP02, MiAx03), IF YOU CHANGE YOUR PREFIXING SCHEME ONE DAY YOU'LL NEED TO CHANGE THIS TOO PREFIX=$( echo "$SONG" | sed -r "s|^(.*/)([a-zA-Z]+)([0-9]+) .*$|\2|g" ) PREFIX_DIR=$( echo "$SONG" | sed -r "s|^(.*/)([a-zA-Z]+)([0-9]+) .*$|\1|g" ) $queue_flag || mpc clear # IF QUEUE FLAG IS FALSE, THEN CLEAR THE QUEUE mpc ls "$PREFIX_DIR" | grep -E "/${PREFIX}[0-9]+ .*${AUDIO_EXTENSIONS}" | sort -V | sed -r "s|'|\\\'|g" | xargs -r -I{} mpc add "{}" $queue_flag || mpc play # IF QUEUE FLAG IS FALSE, PLAY THE FIRST SONG mpc single off # ENABLE AUTOPLAY ;; *) play_song "$SONG" ;; esac fi fi