3 # Collection of shell functions for manipulating MPD. Functions prefixed with
4 # __ are intended for use in these scripts, whereas functions prefixed with
5 # "mpd" are intended to be called by users.
7 # This file may be sourced by your shell startup scripts in order to load all
8 # the functions into the environment, or it may be invoked as an executable.
9 # The first argument to the script designates the function, with or without
10 # the leading "mpd". Subsequent arguments are passed to the called function.
12 # For example, you might run:
13 # `source mpdscripts.sh' followed by `mpdlist mycoolsong'
15 # `./mpdscripts.sh list mycoolsong'.
16 # The latter form is useful when not invoking the scripts from a shell.
18 # This version specifies the functions:
19 # mpdnext, mpdbetter, mpdlist, mpdalbum, and mpdshow.
21 # See the comments above each function for more details.
23 # Requires mpc, GNU grep and GNU sed.
24 # Works with zsh or bash.
26 # Send questions or comments to nbowler@draconx.ca, or find me on IRC as
27 # Draconx on irc.freenode.net.
29 # Licensed under the terms of the Do What The Fuck You Want To Public License.
31 ##############################################################################
35 mpc --format='%position%) %artist% - %title%' playlist
38 # __mpd_trackid [regexp]
39 # With a regular expression as an argument, search the MPD playlist for the
40 # track matching the expression and print the index of that track. Otherwise,
41 # print the index of the currently playing track.
47 id=`mpc | sed -n "2{s/.*#//;s/\/.*//p}"`
49 id=`__mpd_playlist | sed -n \
50 "/${1//\//\\\/}/I{s/^[^[:digit:]]//;s/).*//p;q}"`
53 [ -z "$id" ] && return 1
59 # __mpd_trackname [id]
60 # With a track ID as an argument, print the title of that track. Otherwise,
61 # print the title of the currently playing track.
67 title=`mpc | sed -n "1h;2{g;p;q}"`
69 title=`__mpd_playlist | sed -n \
70 "/^[^[:digit:]]*$1)/s/^.[0-9]*) //p"`
73 [ -z "$title" ] && return 1
79 # mpdnext <regexp> [advance]
80 # Searches the playlist for a track matching <regexp>, then moves it to the
81 # position following the currently playing track. If [advance] is a non-empty
82 # string, also run `mpc next' to play the moved track immediately.
85 local index target name
88 echo "usage: mpdnext <regexp>"
92 if ! index=`__mpd_trackid`; then
93 echo "mpdnext: MPD is currently stopped."
97 if ! target=`__mpd_trackid "$1"`; then
98 echo "mpdnext: target not found."
102 name=`__mpd_trackname $((target))`
104 if [ $target -lt $index ]; then
105 mpc move $target $index
106 elif [ $target -gt $index ]; then
107 mpc move $target $((index+1))
109 echo "mpdnext: selected the playing track"
113 echo "mpdnext: $name moved."
115 # Play track if desired
116 [ -n "$2" ] && mpc next
121 # mpdbetter [sedscript]
122 # Processes the title of the currently playing song through the sed program
123 # specified by [sedscript] (or ~/.mpdbetter if not specified). If the
124 # resulting title is different, attempt to find it in the playlist and use
125 # mpdnext to play it immediately.
128 local title better script="$HOME/.mpdbetter"
129 [ -n "$1" ] && script="$1"
131 if ! title=`__mpd_trackname`; then
132 echo "mpdbetter: MPD is currently stopped."
136 if ! better=`echo "$title" | sed -f "$script"`; then
137 echo "mpdbetter: error in script: \`$script'"
141 if [ "$better" = "$title" ]; then
142 echo "mpdbetter: nothing to be done."
146 mpdnext ") $better\$" next
150 # Simply search the playlist for tracks matching [regexp], or print the entire
151 # playlist if [regexp] is not specified.
157 __mpd_playlist | grep --color=auto -i -- "$1"
162 # Display the currently playing track as well as the part of the playlist
163 # surrounding that track.
168 if ! index=`__mpd_trackid`; then
169 echo "mpdshow: MPD is currently stopped."
175 __mpd_playlist | grep -C 5 --color=auto "^$index)"
179 # Search the playlist for tracks belonging to an album matching <regexp>.
180 # Print those tracks grouped by album and sorted by track number.
186 echo "usage: mpdalbum <regexp>"
190 # This horrible hack grabs the relevant playlist entries and separates
191 # desired fields with @!@ and !@!.
192 list="`mpc --format $'\n%album%\n%track%\n%artist% - %title%' playlist \
206 # list="`mpc --format '%album%@!@%track%!@!%artist% - %title%' playlist |\
207 # sed -n 'h;s/@!@.*//;'"/${1//\//\\\/}/I{g;p}" | sort -k 2`"
209 if [ -z "$list" ]; then
210 echo "mpdalbum: no matches for \`$1'"
214 echo "$list" | while read i; do
215 local album="`echo $i | sed 's/.[0-9]*) \(.*\)@!@.*/\1/'`"
216 local index="`echo $i | sed 's/[# >]\?\([0-9]*\)).*/\1/'`"
217 local title="`echo $i | sed 's/.*!@!//'`"
219 if [ "$album" != "$current" ]; then
220 [ -n "$current" ] && echo
225 echo -e " $index)\t$title"
229 # For executable-like invocation...
231 # It would be nice if we could detect whether we are invoked as an executable
232 # and print a usage message if not given any arguments. I have yet to find
233 # a clean way to do this, however.
235 if [ $# -gt 0 ]; then