mpvc (6701B)
1 #!/bin/sh 2 3 mpvdsock="/tmp/mpvd.sock" 4 cmd_socat="$(command -v socat) - '$mpvdsock'" 5 cmd_jq="$(command -v jq)" 6 cmd_exif="$(command -v exiftool)" 7 8 print_help() { 9 echo "Usage: mpvc ACTION [ARGS]\n" 10 echo "ACTIONS:" 11 echo " append PATH append file to playlist." 12 echo " goto INDEX goto track index of playlist." 13 echo " help print this help message." 14 echo " list print playlist." 15 echo " load PATH load file or directory, and override playlist." 16 echo " lower lower volume 10 units" 17 echo " mute toggle mute" 18 echo " next go to next track." 19 echo " plmenu MODE launch playlist menu." 20 echo " prev go to previous track." 21 echo " raise raise volume 10 units" 22 echo " seek (-)N seek (-)n seconds" 23 echo " stop stop playback" 24 echo " toggle toogle play and pause." 25 echo " " 26 echo "EXTRA:" 27 echo " ytdl-format FMT set ytdl-format" 28 echo " " 29 echo "ALSA:" 30 echo " alower alsa lower 5%" 31 echo " amute alsa mute" 32 echo " araise alsa raise 5%" 33 } 34 35 send_command() { 36 local input="" 37 for var in "$@"; do 38 [ "$input" != "" ] && input="$input, " 39 input="$input\"$var\"" 40 done 41 printf '{ "command": [%s] }\n' "$input" | $cmd_socat 42 } 43 44 get_path() { 45 local path="$(readlink -f "$@")" 46 if [ -f "$path" ] || [ -d "$path" ]; then 47 echo "$path" 48 else 49 echo "$@" 50 fi 51 } 52 53 notify_vol() { 54 case $1 in 55 master) 56 local level="$(amixer sget Master | awk -F"[][]" '/dB/ { print ($2+0) }')" 57 local muted="$(amixer sget Master | awk -F"[][]" '/dB/ { print ($6) }' | sed 's/off/true/')" 58 ;; 59 mpv) 60 local level="$(send_command "get_property" "volume" | $cmd_jq -rM '.data')" 61 local muted="$(send_command "get_property" "mute" | $cmd_jq -rM '.data')" 62 ;; 63 *) return;; 64 esac 65 66 echo $muted > /tmp/tttt 67 68 local marks="$((($level + 5) / 10))" 69 [ "$marks" -gt 10 ] && marks=10 70 71 local output="$1" 72 if [ "$muted" = "true" ]; then 73 local output="$output (muted)" 74 fi 75 local output="$output: [$([ "$marks" -gt 0 ] && printf "%-$((marks))s" "+" | sed 's/\ /+/g')" 76 local output="$output$([ "$marks" -lt 10 ] && printf "%-$((10-marks))s" " ")]" 77 local output="$output$(printf " %3d" "$level")%" 78 ztatus-notify "$output" 79 } 80 81 die() { 82 printf "Error: %s\n" "$@" 83 exit 1 84 } 85 86 # check if prerequisites exist 87 [ -z "$cmd_socat" ] && die "could not find 'socat'" 88 [ -z "$cmd_jq" ] && die "could not find 'jq'" 89 [ -z "$cmd_exif" ] && die "could not find 'exiftool'" 90 91 # check if daemonization should apply 92 if [ "${0##*/}" = "mpvd" ]; then 93 if pidof -x "$(basename -- "$0")" -o $$ >/dev/null; then 94 die "Another instance of mpvd is already runnig..." 95 fi 96 [ -S "$mpvdsock" ] && rm "$mpvdsock" 97 while true; do 98 mpv --idle=yes \ 99 --input-ipc-server="$mpvdsock" \ 100 --ytdl-format=best \ 101 --load-scripts=yes \ 102 2>&1 >/tmp/mpvd.log 103 done 104 exit 0 105 fi 106 107 # check if socket exists 108 [ ! -S "$mpvdsock" ] && die "socket: '$mpvdsock' is missing" 109 110 # print help if no argument was passed 111 if [ $# -lt 1 ]; then 112 print_help 113 exit 0 114 fi 115 116 show_playlist() { 117 cmd="fzf" 118 [ "$1" = "x" ] && cmd="dmenu_vtc -l 20 -p playlist:" 119 script="$(realpath -s $0)" 120 list="$($script list)" 121 [ "$list" = "" ] && exit 1 122 entry="$( 123 echo "$list" \ 124 | sed -e 's/^[ \t]*/ /' -e 's/^[^\w]*current[^\t]*\t/> /' \ 125 | awk '{printf "%-5s %s\n", (NR ": "), $0}' \ 126 | $cmd \ 127 )" 128 [ "$entry" != "" ] && $script goto "$((${entry%%:*}-1))" || exit 1 129 } 130 131 exif_extract() { 132 echo "$1" | grep ^"$2" | cut -d':' -f 2- | sed 's/^[ \t]*//' 133 } 134 135 exif_wrapper() { 136 exif_data="$($cmd_exif -directory -filename -artist -title -duration "$@")" 137 exif_directory="$(exif_extract "$exif_data" "Directory")" 138 exif_filename="$(exif_extract "$exif_data" "File Name")" 139 exif_artist="$(exif_extract "$exif_data" "Artist")" 140 exif_title="$(exif_extract "$exif_data" "Title")" 141 exif_duration="$(exif_extract "$exif_data" "Duration")" 142 exif_artisttitle="$exif_filename" 143 144 if [ "$exif_artist" != "" ] && [ "$exif_title" != "" ]; then 145 exif_artisttitle="$exif_artist - $exif_title" 146 fi 147 148 exif_directory="$(get_path "$exif_directory")" 149 150 # make sure duration is in the format of 'hh:mm:ss' then to seconds (awk) 151 exif_duration="$(echo "$exif_duration" | cut -d' ' -f 1)" 152 exif_duration="$( \ 153 printf '0:0:%s' "$exif_duration" \ 154 | rev | cut -d':' -f -3 | rev \ 155 | awk -F':' '{ print ($1 * 3600) + ($2 * 60) + $3 }' \ 156 )" 157 158 echo "$(printf '#EXTINF:%s,%s\n%s/%s\n' \ 159 "$exif_duration" \ 160 "$exif_artisttitle" \ 161 "$exif_directory" \ 162 "$exif_filename" \ 163 )" 164 } 165 166 case "$1" in 167 # actions 168 load) 169 shift; 170 playlist="$(get_path "$@")" 171 if [ -d "$playlist" ]; then 172 playlist_tmp="$(mktemp /tmp/pls.mpvc.XXXXXXXXXX)" 173 echo '#EXTM3U' > "$playlist_tmp" 174 find "$playlist" -maxdepth 2 -type f | sort -n | while read -r f; do 175 case "$f" in 176 *.flac | *.mp3 | *.ogg) 177 exif_wrapper "$f" >> "$playlist_tmp" ;; 178 *) continue ;; 179 esac 180 done 181 playlist="$playlist_tmp" 182 fi 183 send_command "loadfile" "$playlist" 184 [ "$playlist_tmp" != "" ] && (sleep 10 && rm "$playlist_tmp") & 185 ;; 186 append) 187 shift; send_command "loadfile" "$(get_path "$@")" "append" ;; 188 stop) 189 send_command "stop" ;; 190 toggle) 191 send_command "cycle" "pause" ;; 192 prev) 193 send_command "playlist-prev" ;; 194 next) 195 send_command "playlist-next" ;; 196 goto) 197 shift; send_command "set_property" "playlist-pos" "$@" ;; 198 list) 199 send_command "get_property" "playlist" \ 200 | $cmd_jq -rM '.data[]|( 201 if .current then 202 "\\e[1;37mcurrent\\e[0m\\t" 203 else 204 "\\t" end 205 )+(.title//.filename)' \ 206 | sed -e "s/\\\\t/\\t/g" -e "s/\\\\e/`printf "\033"`/g";; 207 plmenu) shift; show_playlist "$@" ;; 208 seek) 209 shift; send_command "seek" "$@" ;; 210 mute) 211 send_command "cycle" "mute"; notify_vol mpv;; 212 raise) 213 send_command "add" "volume" "10"; notify_vol mpv;; 214 lower) 215 send_command "add" "volume" "-10"; notify_vol mpv;; 216 217 # extra 218 ytdl-format) 219 shift; send_command "set" "ytdl-format" "$@" ;; 220 221 # alsa 222 amute) 223 amixer set Master toggle; notify_vol master;; 224 araise) 225 amixer -q sset Master 5%+; notify_vol master;; 226 alower) 227 amixer -q sset Master 5%-; notify_vol master;; 228 229 # default behaviour 230 help) 231 print_help ;; 232 *) 233 echo "Unknown option: $*"; print_help ;; 234 esac