[download]

local/bin/player

   1 #!/bin/bash
   2 
   3 debug= format=
   4 
   5 while getopts df: OPT; do
   6     case $OPT in
   7         d) debug=1;;
   8         f) format="$OPTARG";;
   9     esac
  10 done
  11 shift $(( OPTIND - 1 ))
  12 
  13 mocp_control(){ # {{{
  14     case $1 in
  15         play) mocp --play; sleep 0.2;;
  16         stop) mocp --stop;;
  17        pause) mocp --toggle-pause;;
  18         prev) mocp --previous; sleep 0.1;;
  19         next) mocp --next; sleep 0.1;;
  20         seek) mocp --seek $2; sleep 0.1;;
  21     esac 2>&-
  22 } # }}}
  23 mocp_status(){ # {{{
  24     mapfile -t array < <(mocp -Q '
  25 %state
  26 %ts
  27 %cs
  28 %file
  29 %artist
  30 %album
  31 %song
  32 ' 2>&-)
  33 
  34     [[ ${array[1]} == STOP ]] && return 1
  35     [[ ${array[1]} == PLAY ]] && status=playing || status=paused
  36 
  37     tts=${array[2]}
  38     cts=${array[3]}
  39 
  40     file=${array[4]}
  41     artist=${array[5]}
  42     album=${array[6]}
  43     title=${array[7]}
  44 } # }}}
  45 
  46 audacious_control(){ # {{{
  47     case $1 in
  48         play) audtool playback-play;;
  49         stop) audtool playback-stop;;
  50        pause) audtool playback-playpause;;
  51         prev) audtool playlist-reverse;;
  52         next) audtool playlist-advance;;
  53         seek) audtool playback-seek-relative $2;;
  54     esac
  55 } # }}}
  56 audacious_status(){ # {{{
  57     mapfile -t array < <(audtool \
  58         playback-status \
  59         current-song-length-seconds \
  60         current-song-output-length-seconds \
  61         current-song-filename \
  62         current-song-tuple-data artist \
  63         current-song-tuple-data album \
  64         current-song-tuple-data title
  65     )
  66 
  67     [[ ${array[0]} == stopped ]] && return 1
  68     [[ ${array[0]} == playing ]] && status=playing || status=paused
  69 
  70     tts=${array[1]}
  71     cts=${array[2]}
  72 
  73     file=${array[3]}
  74     artist=${array[4]}
  75     album=${array[5]}
  76     title=${array[6]}
  77 } # }}}
  78 
  79 cmus_control(){ # {{{
  80     case $1 in
  81         play) cmus-remote --play; sleep 0.2;;
  82         stop) cmus-remote --stop;;
  83        pause) cmus-remote --pause;;
  84         prev) cmus-remote --prev;;
  85         next) cmus-remote --next;;
  86         seek) cmus-remote --seek $2;;
  87     esac
  88 } # }}}
  89 cmus_status(){ # {{{
  90     declare -A array
  91     while read k1 k2 v; do
  92         [[ $k1 == set || $k1 == tag ]] &&
  93         array[$k2]="$v" || array[$k1]="$k2 $v"
  94     done <<< "$(cmus-remote --query)"
  95 
  96     [[ ${array[status]} == stopped* ]] && return 1
  97     [[ ${array[status]} == playing* ]] && status=playing || status=paused
  98 
  99     tts=${array[duration]}
 100     cts=${array[position]}
 101 
 102     file=${array[file]}
 103     artist=${array[artist]}
 104     album=${array[album]}
 105     title=${array[title]}
 106 } # }}}
 107 
 108 mpd_control(){ # {{{
 109     case $1 in
 110         play) mpc play;;
 111         stop) mpc stop;;
 112        pause) mpc toggle;;
 113         prev) mpc prev;;
 114         next) mpc next;;
 115         seek) mpc seek $2;;
 116     esac >&-
 117 } # }}}
 118 mpd_status(){ # {{{
 119     mapfile -t array < <(mpc -f '
 120 %file%
 121 %artist%
 122 %album%
 123 %title%
 124 ')
 125 
 126     [[ ${array[6]} ]] || return 1
 127     [[ ${array[6]} == \[playing\]* ]] && status=playing || status=paused
 128 
 129     read _ _ time _ <<< "${array[6]}"
 130     tts=$(date -ud 00:${time#*/} +%s 2>&-)
 131     cts=$(date -ud 00:${time%/*} +%s 2>&-)
 132 
 133     file=${array[1]}
 134     artist=${array[2]}
 135     album=${array[3]}
 136     title=${array[4]}
 137 } # }}}
 138 
 139 dbus(){ # {{{
 140     qdbus org.mpris.MediaPlayer2.$1 \
 141     /org/mpris/MediaPlayer2 \
 142     org.mpris.MediaPlayer2.Player.$2 $3
 143 } # }}}
 144 dbus_control(){ # {{{
 145     case $2 in
 146         play) dbus $1 Play; sleep 0.2;;
 147         stop) dbus $1 Stop;;
 148        pause) dbus $1 PlayPause;;
 149         prev) dbus $1 Previous;;
 150         next) dbus $1 Next;;
 151         seek) dbus $1 Seek $(( $3 * 1000000 ));;
 152     esac
 153 } # }}}
 154 dbus_status(){ # {{{
 155     status=$(dbus $1 PlaybackStatus) || return 1
 156 
 157     [[ $status == Stopped ]] && return 1
 158     [[ $status == Playing ]] && status=playing || status=paused
 159 
 160     declare -A array
 161     while read k v; do
 162         array[$k]=$v
 163     done < <(dbus $1 Metadata)
 164 
 165     tts=$(( ${array[mpris:length:]} / 1000000 ))
 166     cts=$(( $(dbus $1 Position) / 1000000 ))
 167 
 168     file=${array[xesam:url:]#file://}
 169     file=$(echo -e "${file//%/\\x}")
 170 
 171     artist=${array[xesam:artist:]}
 172     album=${array[xesam:album:]}
 173     title=${array[xesam:title:]}
 174 } # }}}
 175 
 176 player_control(){ # {{{
 177     seek=$3
 178     case $3 in
 179         +*) seek=${3:1}+;;
 180         -*) seek=${3:1}-;;
 181          *) seek=$3;;
 182     esac
 183 
 184     case $2 in
 185         play) playerctl -p $1 play; sleep 0.2;;
 186         stop) playerctl -p $1 stop;;
 187        pause) playerctl -p $1 play-pause;;
 188         prev) playerctl -p $1 previous;;
 189         next) playerctl -p $1 next;;
 190         seek) playerctl -p $1 position $seek;;
 191     esac
 192 } # }}}
 193 player_status(){ # {{{
 194     mapfile -t array < <(playerctl -p $1 metadata -f '
 195 {{status}}
 196 {{mpris:length}}
 197 {{position}}
 198 {{xesam:url}}
 199 {{artist}}
 200 {{album}}
 201 {{title}}
 202 ')
 203 
 204     [[ ${array[1]} == Stopped ]] && return 1
 205     [[ ${array[1]} == Playing ]] && status=playing || status=paused
 206 
 207     tts=$(( ${array[2]} / 1000000 ))
 208     cts=$(( ${array[3]} / 1000000 ))
 209 
 210     file=${array[4]#file://}
 211     file=$(echo -e "${file//%/\\x}")
 212 
 213     artist=${array[5]}
 214     album=${array[6]}
 215     title=${array[7]}
 216 } # }}}
 217 
 218 rhythmbox_control(){ # {{{
 219     command -v playerctl > /dev/null &&
 220     player_control rhythmbox "$@" ||
 221     dbus_control   rhythmbox "$@"
 222 } # }}}
 223 rhythmbox_status(){ # {{{
 224     command -v playerctl > /dev/null &&
 225     player_status rhythmbox ||
 226     dbus_status   rhythmbox
 227 } # }}}
 228 
 229 mpv_control(){ # {{{
 230     command -v playerctl > /dev/null &&
 231     player_control mpv "$@" ||
 232     dbus_control   mpv "$@"
 233 } # }}}
 234 mpv_status(){ # {{{
 235     command -v playerctl > /dev/null &&
 236     player_status mpv ||
 237     dbus_status   mpv
 238 } # }}}
 239 
 240 vlc_control(){ # {{{
 241     command -v playerctl > /dev/null &&
 242     player_control vlc "$@" ||
 243     dbus_control   vlc "$@"
 244 } # }}}
 245 vlc_status(){ # {{{
 246     command -v playerctl > /dev/null &&
 247     player_status vlc ||
 248     dbus_status   vlc
 249 } # }}}
 250 
 251 export player status icon file artist album title tt ct tl
 252 
 253 for i in mocp cmus mpd audacious rhythmbox mpv vlc; do
 254     [[ $(pidof $i) ]] || continue
 255     ${i}_control "$@" && ${i}_status || continue
 256 
 257     player=$i
 258 
 259     tt=$(date -ud @$tts +%H:%M:%S)
 260     ct=$(date -ud @$cts +%H:%M:%S)
 261     tl=$(date -ud @$(( tts - cts )) +%H:%M:%S)
 262 
 263     tt=${tt#00:}
 264     ct=${ct#00:}
 265     tl=${tl#00:}
 266 
 267     [[ $title ]] || title=${file##*/}
 268     [[ $status == playing ]] && icon='>'
 269     [[ $status == paused  ]] && icon='||'
 270 
 271     [[ $debug  ]] && printf '[%9s] ' $player
 272     [[ $format ]] && printf "$format\n" | envsubst
 273     [[ $format ]] || echo "$icon $artist${artist:+ - }$title (-$tl)"
 274 done
 275 
 276 [[ $format ]] ||
 277 for i in player status file artist album title tt ct tl; do
 278     printf '%s\t%s\n' "$i" "${!i}"
 279 done > ~/.cache/player
 280 
 281 [[ $status ]]