#!/bin/bash HOST="$(uname -n)" ARG0="$(basename "$0")" TMPD="${TMPDIR:-/tmp}" PIPEDIR="$TMPD/$ARG0-$USER" CMDPIPE="$PIPEDIR/cmd-$HOST" OUTPIPE="$PIPEDIR/out-$HOST" AUXPIPE="$PIPEDIR/aux-$HOST" FILE="get_property path\nget_file_name\n" TIME="get_percent_pos\nget_time_pos\nget_time_length\n" AUDI="get_audio_bitrate\nget_audio_codec\nget_audio_samples\n" META="get_property metadata\n" TAGS=\ "album\narchival location\nartist\nauthor\ncomment\ncomments\n"\ "commissioned\ncopyright\ncreation date\ncropped\ndate\n"\ "digitization time\ndimensions\ndots per inch\nencoder\n"\ "encoder url\nengineer\ngenre\nkeywords\nlightness\nmedium\n"\ "name\npalette setting\nproduct\nsharpness\nsoftware\nsource\n"\ "source form\nsubject\ntechnician\ntime code\ntitle\ntrack\nyear\n" errmsg () { echo "$@" >&2 ; exit 1 ; } cmd_echo () { echo "$@" | dd of="$CMDPIPE" oflag=nonblock status=noxfer &>/dev/null ; } cmd_push () { cmd_echo "$@" || errmsg "not listening" ; } get_direct () { cmd_push -ne "$REQT" while [ -n "$1" ] ; do read -t 3 || errmsg "not responding" [[ "$REPLY" == ANS_* ]] || continue shift ; $PASS "$REPLY" && continue IFS='=' read tag val <<< "$REPLY" val="${val#\'}" ; val="${val%\'}" IFS='' read $tag <<< "$val" done } short_info () { PASS="false" REQT="${FILE}${TIME}" get_direct {a..e} <>"$OUTPIPE" } long_info () { PASS="false" REQT="${FILE}${TIME}${AUDI}${META}" get_direct {a..i} <>"$OUTPIPE" } pause () { PASS="echo" REQT="${FILE}${TIME}${AUDI}${META}pause\n" get_direct {a..i} <>"$OUTPIPE" >"$INPAUSE" # fuser -s -k -STOP "$CMDPIPE" } resume () { # [ -f "$INPAUSE" ] && # fuser -s -k -CONT "$CMDPIPE" rm -f "$INPAUSE" ; cmd_push "$@" tty -s || exit 0 ; short_info echo "$ANS_FILENAME: $(position)" } on_hold () { [ -f "$INPAUSE" ] && CMDPIPE=/dev/null && OUTPIPE="$INPAUSE" ; } from_sec () { IFS='.' read s ss <<< "$1" [ $s -lt 3600 ] && printf '%d:%02d\n' $(($s/60)) $(($s%60)) || \ printf '%d:%02d:%02d\n' $(($s/3600)) $((($s/60)%60)) $(($s%60)) } position () { unset HOLD [ -f "$INPAUSE" ] && HOLD="[PAUSE]" echo "$(from_sec $ANS_TIME_POSITION)" \ "($(from_sec $ANS_LENGTH)) $ANS_PERCENT_POSITION%" $HOLD } for NEWPIPE in "$CMDPIPE" "$CMDPIPE".{a..z} ; do [ -p $NEWPIPE ] || break CMDPIPE="$NEWPIPE" cmd_echo -n || break CMDPIPE="$NEWPIPE" done INPAUSE="$CMDPIPE.pause" unset APPEND DETACH [ -d "$PIPEDIR" ] && cmd=${1:-i} || cmd=${1:-h} case "$cmd" in h|-h|--help) echo "Usage: $ARG0 [command|playlist|path...]" echo " -- play in background" echo " d|-d|--direct ... -- play in foreground" echo echo "Background mode:" echo " a|-a|--append ... -- append to current playlist" echo " r|-r|--replace ... -- replace current playlist" echo " p|-p|--play|--pause -- toggle play/pause" echo " f|-f|--forward [N] -- skip N tracks forward" echo " b|-b|--back [N] -- skip N tracks backward" echo " u|-u|--up-step -- skip current playlist level" echo " s|-s|--seek -- seek to (% or seconds)" echo " i|-i|--info -- short 'now playing' info" echo " I|-I|--INFO -- info + full pathname" echo " l|-l|--long -- info + metadata" echo " q|-q|--quit -- stop and exit" ;; l|-l|--long) on_hold ; long_info echo "Playing : $ANS_FILENAME" echo " Stream : $ANS_AUDIO_CODEC, $ANS_AUDIO_BITRATE, $ANS_AUDIO_SAMPLES" echo " Played : $(position)" unset delim while [ -n "$ANS_metadata" ] ; do IFS=',' read head ANS_metadata <<< "$ANS_metadata" if echo -ne "$TAGS" | grep -ixq "$head" ; then IFS=' ' read ANS_metadata <<< "$ANS_metadata" if [[ "$ANS_metadata" == ,* ]] ; then unset delim else printf "\n%7s" "$head" ; delim=' : ' fi elif [ -n "$delim" ] ; then echo -n "$delim$head" ; delim=',' fi done ; echo ;; i|-i|--info) on_hold ; short_info echo "$ANS_FILENAME: $(position)" ;; I|-I|--INFO) on_hold ; short_info echo "$ANS_path: $(position)" ;; p|-p|--play|--pause) [ -f "$INPAUSE" ] && resume 'pause' || pause ;; f|-f|--forward) resume "pt_step ${2:-1} 1" ;; b|-b|--back) resume "pt_step -${2:-1} 1" ;; u|-u|--up-step) resume "pt_up_step 1 1" ;; s|-s|--seek) case "$2" in +*|-*) typ='0' ;; *%) typ='1' ;; *) typ='2' ;; esac resume "seek ${2:-0} $typ" ;; q|-q|--quit) resume 'quit' "$AUXPIPE" & ;; esac if [ -n "$APPEND" ] && cmd_echo -n ; then protected="$(sed 's/"/\\\\\\"/g' <<< $PLAYLIST)" resume "loadlist \"$protected\" $APPEND" exit 0 fi [ ! -f "$INPAUSE" ] && cmd_echo -n && pause if [[ "$DETACH" == 0 || "$CMDPIPE" == *.z ]] ; then exec mplayer -vo null -playlist "$PLAYLIST" fi CMDPIPE="$NEWPIPE" INPAUSE="$CMDPIPE.pause" rm -f "$INPAUSE" mplayer -vo null -playlist "$PLAYLIST" \ -slave -really-quiet -msglevel global=4 \ -input file="$CMDPIPE" >"$OUTPIPE" & dd if="$OUTPIPE" of="$CMDPIPE" count=0 &>/dev/null short_info ; echo "Playing $ANS_path"