[download]

local/bin/music

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