Maintain ratings & playcounts for your mpd server.
This manual corresponds to mpdpopm version 0.3.4.
mpdpopm provides a companion daemon to MPD that will maintain play counts, ratings, & last-played timestamps for your music library, along with an associated CLI for talking to the companion daemon. Similar to mpdfav, but written in Rust (which I prefer to Go), it will maintain this information in your sticker database. Along the lines of mpdcron, it will also allow you to keep that information up-to-date in your tags or other data stores by invoking external (user-provided & -configured) commands.
NB. The project README
contains the reference instructions for mpdpopm installation.
mpdpopm is distributed in a number of formats. The
prerequisites depend on the distribution format, but in any event you
need to have MPD installed & running in order to use
mpdpopm. See also Setting-up mpd.
The pre-built binary distribution, the Debian package, and the Arch User Repository packages require no other pre-requisites.
Downloading mpdpopm from crates.io requires the Rust toolchain.
Building from source via the Autotools distribution further requires the Gnu Autools.
mpdpopm may be installed in a number of ways. Refer to the
project README for the most
up-to-date instructions.
mpdpopm can be installed from
crates.io.
mpdpopm provides two programs:
mppopmd is the companion daemon process to MPD
mppopm is the command-line interface to mppopmd
Both programs make use of the MPD
protocol, a
simple text-based protocol by which clients can communicate with the
MPD daemon and with one another. From the perspective of
MPD, mppopm & mppopmd are just new clients. Via
this protocol mppopmd will monitor MPD for song playback
& note when songs complete; this is how it knows to increment the
playcount & update the last played timestamp for each song to which
you listen.
Also via the protocol, MPD clients can communicate with one
another by registering "channels" and subscribing to them; one client
can send a message to a given channel, and all other clients
subscribed to that channel will receive that message. In particular,
if an MPD client sends the "rating" command to the
mppopmd commands channel (the channel name is configurable, but
defaults to "unwoundstack.com:commands"), mppopmd will set the
rating for the given track.
The mechanism by which mppopmd records this information (i.e
play counts, last played and ratings) is MPD
stickers. A sticker is a little bit of textual information which
clients can attach to songs in the form of a name-value
pair. mpdpopm defines a new sticker name (again configurable)
for each of these items & updates the values for each song when & as
requested.
Of course, other MPD clients will not, in general, be aware of
mppopmd, its command channel, or the stickers it sets: you the
user will have to bridge that gap. You could of course just fire-up
netcat & start sending commands, but that’s not particularly
convenient. That’s where mppopm comes in. It is a small
command-line tool for controlling the mppopmd daemon; you could
for instance say mppopm set-rating '*****' to rate the
current track at five stars. Under the hood, it connects to the MPD
daemon, sends a "rating" message to the mppopmd commands
channel, and mppopmd, in turn, tells MPD to set the rating
sticker for the curren track to 255 (more on the rating system below).
Configuring & setting up MPD is beyond the scope of this manual; see the MPD manual here.
One note, however: in order for mpdpopm to function, MPD
must be configured to enable the sticker database. This is done via
the sticker_file configuration item. The user as whom
mppopmd is run will need access to the file named therein and
its parent directories. See
here for details.
mppopmd is the companion daemon to MPD. Once installed, most
configuration items have sensible defaults, but there are a few that
will need to be customized to the user’s particular taste (mostly
having to do with their MPD configuration).
It is recommended that it be run in the foreground initially (using the -F flag) for purposes of trouble-shooting, but after that the user will likely want to run it as a daemon.
The configuration file’s location is specified on the mppopmd
command-line (using the -c flag). It takes the form of a LISP
S-expression in which each top-level configuration item is a cons
cell. LISP comments will be ignored.
General-purpose items:
host The network address on which the MPD daemon is
listening. It should match bind_to_address in your MPD
configuration file. The default value is "localhost".
port The TCP port on which the MPD daemon is listening. This
should match the port setting in your MPD configuration
file. The default value is 6600.
local_music_dir The root of your MPD music directory, as seen
from this host. This will be used to evaluate the %full-file
and %current-file replacement parameters when executing
commands (see below).
log The file to which the daemon will log when running in the
background (if you specify the -F flag, to run it in the
foreground, it will log to stdout); no log rotation is
provided, so setup logrotate, run it under systemd
(see see below) or keep an eye on it so it
doesn’t grow too large.
commands_chan The name of the MPD channel on which
mppopmd shall listen for commands ("unwoundstack.com:commands"
by default).
Configuration items related to maintaining play counts & last-played timestamps:
playcount_sticker The sticker name mpdpopm will use to
store play counts (defaults to "unwoundstack.com:playcount").
lastplayed_sticker The sticker name mpdpopm will use to store
the last played timestamp (defaults to "unwoundstack.com:lastplayed")
played_thresh The percentage of a song’s duration that must be
played back in order for it to be considered as "played", expressed as
number between 0 & 1 (defaults to 0.6).
poll_interval_ms The amount of time, in milliseconds, between
polls of MPD by mppopmd to check on playback progress. This is
the error bound on detection of song having been “played” in that if
a poll is performed the instant before the current song’s playback
reaches played_thresh, it may be up to this many milliseconds
before mppopmd tries again and belatedly determines that the
current track has been “played” (and hence updates the playcount,
last played time &c). Since this is not, in general, a time-sensitive
operation, the default setting is 5000 (i.e. five seconds) to keep
network traffic down.
playcount_command An optional name of a program to run when the
play count is incremented; this should be an absolute path. Use
playcount_command_args to specify arguments to this
command. The intent behind this feature is to enable the user to keep
other data stores (such as ID3 tags) up-to-date with play count
information (see below)
playcount_command_args An array of arguments to specify to the
playcount command; arguments may contain replacement parameters that
will be filled in at the time of execution.
Configuration items related to ratings:
rating_sticker The sticker name mppopmd will use to
store the rating (defaults to "unwoundstack.com:rating").
ratings_command An optional name of a program to run when the
rating is set; this should be an absolute path. Use
ratings_command_args to specify arguments to this command. The
intent behind this feature is to enable the user to keep other data
stores (such as ID3 tags) up-to-date with play count information (on
which more see below).
ratings_command_args An array of arguments to specify to the
ratings command; arguments may contain replacement parameters that
will be filled in at the time of execution.
Finally, the configuration for generalized commands is not described here, but rather under Generalized Commands.
mpdpopm ships with a minimal sample configuration file. A more
expansive sample appears at the end of this manual (see Sample Configuration File).
Once you’ve got your configuration file prepared, you should probably start the daemon in the foreground for ease of trouble-shooting. I suggest starting it with the -v flag ("verbose") the first time, as well (there’s also a -d flag which will produce more copious debug output). You should expect to see something like this:
mppopmd -v -F -c <path to configuration file>
[2020-12-12T15:26:19.620806454-08:00][mppopmd] mppopmd 0.2.2 logging at level Debug.
[2020-12-12T15:26:19.621395828-08:00][mpdpopm] mpdpopm 0.2.2 beginning.
[2020-12-12T15:26:19.621998677-08:00][mpdpopm::clients] Connected 0.22.0.
[2020-12-12T15:26:19.623398521-08:00][mpdpopm::clients] Connected 0.22.0.
[2020-12-12T15:26:19.623874861-08:00][mpdpopm::clients] Sent subscribe message for unwoundstack.com:commands; got `OK
'.
[2020-12-12T15:26:19.623888424-08:00][mpdpopm::clients] Subscribed to unwoundstack.com:commands.
[2020-12-12T15:26:19.624985027-08:00][mpdpopm] selecting...
[2020-12-12T15:26:19.628412738-08:00][mpdpopm] output status is Ok(
Output {
status: ExitStatus(
ExitStatus(
0,
),
),
stdout: "/home/sp1ff\n",
stderr: "",
},
)
[2020-12-12T15:26:19.628778521-08:00][mpdpopm] No database update needed
[2020-12-12T15:26:19.628817190-08:00][mpdpopm] No more commands to process.
At this point mppopmd is just sitting around, waiting for
something to happen. Bring up your favorite MPD client & start playing
a track. That should induce some activity:
[2020-12-12T15:26:29.522581696-08:00][mpdpopm::clients] Sent idle message; got `changed: player OK '. [2020-12-12T15:26:29.522756287-08:00][mpdpopm] subsystem Player changed [2020-12-12T15:26:29.527064915-08:00][mpdpopm::playcounts] Updating status: 0.000% complete. ... [2020-12-12T15:28:19.653519123-08:00][mpdpopm::playcounts] Updating status: 60.698% complete. [2020-12-12T15:28:19.653569350-08:00][mpdpopm::playcounts] Increment play count for 'M/Miles Davis - Boplicity.mp3' (songid: 262) at 0.6069790770994554 played. [2020-12-12T15:28:19.661696678-08:00][mpdpopm::clients] Sent message `sticker get song "M/Miles Davis - Boplicity.mp3" "unwoundstack.com:playcount"'; got `sticker: unwoundstack.com:playcount=3 OK ' [2020-12-12T15:28:19.661743547-08:00][mpdpopm::playcounts] Current PC is 3. [2020-12-12T15:28:19.770956673-08:00][mpdpopm::clients] Sent `sticker set song "M/Miles Davis - Boplicity.mp3" "unwoundstack.com:lastplayed" "1607815699"'; got `OK ' [2020-12-12T15:28:19.868244915-08:00][mpdpopm::clients] Sent `sticker set song "M/Miles Davis - Boplicity.mp3" "unwoundstack.com:playcount" "4"'; got `OK ' ...
In this example, mppopmd noticed that "Boplicity" by Miles
Davis started playing; when it was played 60% of the way through, the
daemon updated the play count from 3 to 4 & set the last played
timestamp.
Once things seem to be working, you might consider removing the
-F flag & running mppopmd as a proper
daemon. mpdpopm ships with a sample systemd unit if you’d like to
run it that way.
On it’s own, mppopmd will happily sit in the background,
monitoring playback & keeping play counts & last-played timestamps
up-to-date. In order to rate a song, or indeed to do anything
with the information that’s being accumulated, the user will need to
induce their favorite MPD client to send the relevant commands
(see mppopmd Commands) to the mppopmd commands channel
(see mppopmd Configuration), or fire-up something like
netcat and start entering the commands manually.
Since neither of those options are likely to be convenient,
mpdpopm ships with a small, purpose-built MPD client:
mppopm (see mppopm Commands).
The mppopm CLI needs to know where to find the MPD daemon, as
well as the names of the mpdpopm commands channel & sticker
names. These configuration items all have default values. They may
also be specified on the command line, a configuration file, or an
environment variable. The order of presendence is:
The configuration file defaults to ~/.mppopm, but may be
specified on the command line. Like that of mppopmd, it is a
LISP S-expression, where each item is a cons cell.
The mppopm configuration items:
MPD_HOST
MPD_PORT
mppopmd daemon is subscribed (i.e. should match the
commands_chan setting in your daemon’s configuration);
defaults to “unwoundstack.com:commands”. No command-line option or
environment variable.
mppopmd daemon to store playcounts (i.e. should match the
daemon’s configuration item of the same name); defaults to
“unwoundstack.com:playcount”. No command-line option or environment
variable.
mppopmd daemon to store last-played timestamps (i.e. should
match the daemon’s configuration item of the same name); defaults to
“unwoundstack.com:lastplayed”. No command-line option or environment
variable.
mppopmd daemon to store ratings (i.e. should match the daemon’s
configuration item of the same name); defaults to
“unwoundstack.com:rating. No command-line option or environment
variable.
mppopm supports a number of sub-commands for carrying out
various operations related to mpdpopm. You can always see the
complete list of sub-commands your particular build of mppopm
supports by saying mppopm --help, and get detailed help on a
particular sub-command by saying mppopm SUB-COMMAND --help.
mppopm Rating Commandsmppopm Play Count Commandsmppopm Last Played Commandsmppopm Filter Commandsmppopm Rating Commands ¶mppopm can be used to set & retrieve ratings for your music
library. It can also be used to filter on the basis of rating
mppopm Filter Commands.
mppopm get-rating will retrieve the current song’s rating &
print it on stdout. mppopm get-rating URI will
interpret “URI” as an MPD song URI & display it’s rating on
stdout. mppopm get-rating URI... will do the same for
multiple songs. Ratings are expressed as an integer between 0 & 255
inclusive, with the convention that a rating of zero denotes
“un-rated”.
mppopm set-rating ARG will set the current song’s rating to
“ARG”. “ARG” may be an integer between 0 & 255, or it may be
expressed as one to five “stars”: “*” deontes one star, “**” two
stars and so forth. “Stars” are mapped to numeric ratings as per
Winamp:
1
64
128
196
255
Finally, mppopm set-rating ARG SONG will interpret “SONG”
as a song URI & set that song’s rating to “ARG”.
mppopm Play Count Commands ¶mppopm get-pc will print the play count of the current song
on stdout. mppopm get-pc ARG will interpret “ARG”
as a song URI & print that song’s play count to stdout.
mppopm get-pc ARG... will print the play count for each
argument on stdout.
mppopm set-pc ARG will set the play count for the current
song to “ARG”, where “ARG” is an unsigned integer. mppopm
set-pc ARG SONG will set the play count for “SONG” to “ARG”.
mppopm Last Played Commands ¶mppopm get-lp will print the last played time of the current
song in seconds since Unix epoch on stdout. mppopm
get-lp ARG will interpret “ARG” as a song URI & print that song’s
last played timestamp to stdout. mppopm get-lp
ARG... will print the last played timestamp for each argument on
stdout.
mppopm set-lp ARG will set the last played timestamp for the
current song to “ARG”, where “ARG” is an unsigned integer
interpreted as seconds since Unix epoch. mppopm set-lp ARG
SONG will set the last played timestamp for “SONG” to “ARG”.
mppopm Filter Commands ¶Having accumulated play counts, ratings &c in one’s sticker database one can now begin acting on that information. For instance, here is a bash shell script to add all un-rated songs to the play queue:
exec 3<>/dev/tcp/localhost/6600;
head -1 <&3
declare -A rated
last_file=""
echo "sticker find song \"\" unwoundstack.com:rating" >&3
while true; do
read -r -u 3 line
case $line in
OK*)
break;;
ACK*)
echo "$line" >&2;
exit 1;;
file:*)
last_file="${line:6}";;
sticker:*)
rated["$last_file"]="${line:33}";
last_file="";;
*)
echo "error: $line" >&2;
exit 1;;
esac
done
exec 4<>/dev/tcp/localhost/6600;
head -1 <&4
echo "command_list_begin" >&4
echo "listall" >&3
while true; do
read -r -u 3 line
case $line in
OK*)
break;;
ACK*)
echo "$line" >&2;
exit 1;;
file:*)
if test -z "${rated[${line:6}]}" -o "${rated[${line:6}]}" == "0"; then
echo "adding ${line:6}"
echo "add \"${line:6}\"" >&4
fi;;
esac
done
exec 3<&-
echo "command_list_end" >&4
head -1 <&4
exec 4<&-
In search of a more ergonomic way to make use of this information,
mpdpopm now has support for
filters. Filters are an MPD feature for searching one’s song database; one can
select songs for various operations by filters such as “(artist =~
’pogues’)”, for instance. mpdpopm’s contribution is to extend
the MPD filter syntax to add ratings, play counts & last-played
timestamps (“rating”, “playcount” & “lastplayed” resp.) to the
filter syntax.
The first two filter-related commands added to mppopm are
searchadd and findadd. Each accepts a filter as an
argument and adds the selected songs to the the play queue. The only
difference is that searchadd works case-insensitively &
findadd respects case.
Consequently, the shell script above can now be replaced by
the command mppopm findadd ``(rating == 0)''. NB. filter
syntax requires textual values to be quoted, so you’ll need to escape
them for the shell. For instance, to select songs with an artist like
“pogues”, the filter syntax would be (artist =~ “pogues”), so
to specify this on the command line, you would have to escape the double
quotes: mppopm searchadd ``(artist =~ \"pogues\")''.
See below for a detailed description of filter syntax & quoting issues.
mppopm Filter Syntax ¶The mpdpopm filter syntax is a (small) superset of the MPD
syntax. The following is a grammar for filter expressions in
modified BNF:
<expr> ::= <term> | <negation> | <conjunction> | <disjunction>
<term> ::= "(" <comparison> ")"
<negation> ::= "(" "!" <expr> ")"
<conjunction> ::= "(" <conj-list> ")"
<conj-list> ::= <expr> "AND" <expr> |
<expr> "AND" <conj-list>
<disjunction> ::= "(" <disj-list> ")"
<disj-list> ::= <expr> "OR" <expr> |
<expr> "OR" <disj-list>
<comparison> ::= <tag> <op> <qtext> |
"file" "==" <qtext> |
"base" <qtext> |
"modified-since" <qtext> |
"AudioFormat" <audio-format-op> <audio-format> |
<mpdpopm-numeric-tag> <numeric-op> <number> |
"lastplayed" <numeric-op> <date-or-epoch>
<tag> ::= "artist" | "artistsort" | "album" | "albumsort" |
"albumartist" | "albumartistsort" | "title" | "track" |
"name" | "genre" | "date" | "originaldate" | "composer" |
"performer" | "conductor" | "work | "grouping" | "comment" |
"disc" | "label" | "musicbrainz_artistid" |
"musicbrainz_albumid" | "musicbrainz_albumartistid" |
"musicbrainz_trackid" | "musicbrainz_releasetrackid" |
"musicbrainz_workid"
<op> ::= "==" | "!=" | "contains" | "=~" | "!~"
<audio-format-op> ::= "==" | "=~"
<audio-format> ::= "'" <samplerate>:<bits>:<channels> "'"
<mpdpopm-numeric-tag> ::= "rating" | "playcount"
<numeric-op> ::= "==" | "!=" | "<" | "<=" | ">" | ">="
<number> ::= [0-9]+
<qtext> ::= text enclosed in either single- or double-quotes; if the text
contains single- or double-quotes, or backslashes, they shall
be backslash-escaped
<date-or-epoch> ::= either <number> or a single- or double-quoted ISO
8601 timestamp
In the above grammar, the non-terminals <samplerate>,
<bits>, and <channels> are undefined; please see the MPD
manual for details on how to specify them.
Note that tags are matched without regard to case; for consistency’s
sake, mpdpopm-defined attributes are also matched
case-insensitively.
For a detailed description of how tags are matched, also please see
the MPD manual, since mpdpopm delegates the evaluation of all terms
already supported by MPD to thereto.
mppopm Filter Quoting ¶The non-terminal qtext appears frequently in the mpdpopm
filter grammar (see mppopm Filter Syntax). These textual tokens
are required to be enclosed in quotation marks, either by single-quote
or a double-quote characters (ASCII characters 39 or 34, respectively;
cf.
ExpectQuoted in the MPD codebase) This brings up the question of how
to represent single- or double-quotes inside the quoted text. MPD
employs the time-honored tradition of “escaping” them with a
backslash character (ASCII character 92). This then implies that
backslashes in the quoted text must themselves be
backslash-escaped.
For example, to test against the text
foo\bar''
using double-quotes, we would enclose the text in " characters,
and backslash-escape any ", ', and \ characters
therein, to obtain
"foo\\bar\""
We could also choose to quote the text using single-quotes in the same manner:
'foo\\bar\"'
Tragically, to use this text in a filter in the shell with
mppopm, we will need to again quote the text in order to
protect special characters therein from the shell.
Let us suppose we had songs by the pathologically named artist foo\bar”. A properly quoted filter expression would be:
(artist == "foo\\bar\"")
To invoke this on the command line, however, we would need to quote
the filter itself (to make it into a single argument for
mppopm), which would require quoting the entire filter:
mppopm findadd "(artist =~ \"foo\\\\bar\\\"\")"
In this particular case, quoting the filter using single-quotes might be simpler
mppopm findadd '(artist == "foo\\bar\"")'
If the artist name contained a single-quote, e.g.
foo'bar
We could quote it using "s
(artist =~ "foo\'bar")
but to express this in the shell we would need to protect the single-quote from bash:
mppopm findadd '(artist =~ "foo\'"'"'bar")'
Quoting the artist name using 's, and protecting that
from the shell is left as an exercise for the reader.
This section discusses mppopmd command syntax & will be of
interest only to authors of MPD clients that want to communicate
with mppopmd.
Clients can invoke mppopmd commands via the
sendmessage MPD command to the mppopmd commands channel, e.g.
$>: nc localhost 6600 OK MPD 0.22.0 sendmessage unwoundstack.com:commands "rate 255" OK
The sendmessage command takes two string arguments: the channel & the message. Both must be quoted according to the rules of the MPD protocol. Per the MPD manual, “If arguments contain spaces, they should be surrounded by double quotation marks”.
More generally, in the MPD protocol:
' & "
'-s or "-s, the token must be
enclosed in "-s, and any "-s or \-s therein must
be backslash escaped. NB. 's need not be escaped, if
they occur within a quoted string (although doing so is harmless)
Since mppopmd commands generally take arguments, they will
contain spaces, and hence need to be quoted. For instance, the
“rate” command above takes at least one argument (the rating)
and so the text “rate 255” had to be enclosed in double-quotes.
Commands that take filters as arguments will not only contain spaces,
but also "s and/or 's and possible backslashes, so
quoting will be more
involved. Cf. libmpdclient for a reference implemenation of the quoting algorithm.
As a worked example, suppose we wanted to send the findadd command with the (filter) argument of:
(artist =~ 'foo\'bar')
The filter itself needs to be quoted to make it a single parameter:
"(artist =~ \'foo\\\'bar\')"
Giving us a command of
findadd "(artist =~ \'foo\\\'bar\')"
This contains spaces, so we wrap it in double-quotes and escape all special characters therein, giving us the final message as it would appear on the wire:
sendmessage unwoundstack.com:commands "findadd \"(artist =~ \\\'foo\\\\\\\'bar\\\')\""
See also here for the MPD parsing logic.
mppopmd supports the following commands:
rate: “rate RATING( TRACK)?” set the rating to RATING for TRACK if it
is given, or the current track if it is not. If TRACK is given, it will be
interpreted as a song URI.
setpc: “setpc PC( TRACK)?” set the play count to PC for TRACK if it
is given, or the current track if it is not. If TRACK is given, it will be
interpreted as a song URI.
setlp: “setlp LP( TRACK)?” set the last-played timestamp to
LP for TRACK if it is given, or the current track if it is not. If
TRACK is given, it will be interpreted as a song URI.
findadd: “findadd FILTER” apply FILTER in a case-sensitive manner
and add all matching songs to the play queue
searchadd: “searchadd FILTER” apply FILTER in a
case-insensitive manner and add all matching songs to the play queue
It may be that the information managed by mpdpopm is replicated
in other locations. For instance, the author has play counts
also recorded in the PCNT & POPM frames of the
ID3 tags attached to his music files, and ratings in the POPM
frame, as well. For that reason, mppopmd has the ability to run
arbitrary commands after updating stickers. This feature was developed
for the purpose of keeping ID3 tags up-to-date, but one could do
anything (pop up a notification, update a database &c).
The operations of rating a song and of updating its play count (and
associated last played timestamp) may be configured to run an
arbitrary program whenever they are carried out. The two salient
options are rating_command and playcount_command,
respectively. If present in the mppopmd configuration, they
should be the absolute path to the program to be executed.
Each has a partner option specifying the parameters that will be
supplied to the program when it is run (rating_command_args
and playcount_command_args, respectively). These options
shall be lists of command-line arguments to be provided, specified as
strings. Each may specify an argument of “%full-file” which will, on
command execution, be expanded by mppopmd to the absolute path
of the song being operated upon.
rating_command_args may also make use of the “%rating” replacement parameter which will be expanded to the rating being applied (expressed as an integer between 0 & 255 inclusive expressed in base 10).
playcount_command_args may also employ the “%playcount” replacement parameter which will be the new play count (again expressed as an integer in base 10).
For example, the author has written an ID3 tagging utility called
scribbu which he uses
to keep his ID3 tags up-to-date. The following two lines, placed
in the mppopmd configuration file, will cause it to invoke
the command /home/sp1ff/bin/scribbu popm -a -A -b -o sp1ff@pobox.com -C %playcount %full-file every time it updates the play count sticker:
(playcount_command . "/home/sp1ff/bin/scribbu")
(playcount_command_args . ("popm" "-a" "-A" "-b" "-o" "sp1ff@pobox.com" "-C" "%playcount" "%full-file"))
The tokens %playcount & %full-file will be replaced with
the new play count and the absolute path to the file backing the
current song, respectively.
The idea of executing arbitrary commands proved useful enough that
mpdpopm generalized it: the user can configure arbitrary server-side
commands in response to messages received on the mppopmd
commands channel. As an example, an entry in the configuration file
like this:
(gen_cmds .
(((name . "set-genre")
(formal_parameters . (Literal Track))
(default_after . 1)
(cmd . "/home/sp1ff/bin/scribbu")
(args . ("genre" "-a" "-C" "-g" "%1" "%full-file"))
(update . TrackOnly)))
will define a new command “set-genre”, with two parameters, the second
of which can be omitted (it will default to the current track). When
mppopmd receives this command; i.e. when a client says something
like:
sendmessage unwoundstack.com:commands "set-genre Rock"
mppopmd will invoke scribbu like so:
/home/sp1ff/scribbu genre -a -C -g Rock "${music-dir}/${song URI}"
where the "psuedo-variables" music-dir and song URI
above will be replaced with the configured music directory and the
current song’s URI.
The configuration is perforce more complex because we have to, at
configuration-time, define a mapping between the actual parameters
supplied by a client in the message to “unwoundstack.com:commands”
and the replacement parameters used in the command arguments. The
command’s replacement parameters are defined by a simple list, given
in formal_parameters, of parameter types. At this time, there
are only two formal parameter types:
Actual parameters after index default_after (counting from one) are optional; if not specified the replacement parameter will take the default value for its type (the empty string for literals, the currently playing song’s URI for tracks).
Two additional parameters are available:
music_dir prepended to the actual argument), as will
%full-file
Finally, some commands (such as set-genre, above) may change
your music collection in such a way as to necessitate an MPD database
update after they complete. The update configuration item
governs that: it may be set to "NoUpdate", "TrackOnly", or
"FullDatabase" to indicate that this command will require no update,
an update to the song named by the Track parameter only, or the full
database, respectively.
((log . "/home/mgh/var/log/mppopmd.log")
(host . "192.168.1.6")
(port . 6600)
(local_music_dir . "/mnt/Took-Hall/mp3")
(playcount_sticker . "unwoundstack.com:playcount")
(lastplayed_sticker . "unwoundstack.com:lastplayed")
(played_thresh . 0.6)
(poll_interval_ms . 5000)
(playcount_command . "/usr/local/bin/scribbu")
(playcount_command_args . ("popm" "-v" "-a" "-A" "-b" "-o" "sp1ff@pobox.com" "-C" "%playcount" "%full-file"))
(commands_chan . "unwoundstack.com:commands")
(rating_sticker . "unwoundstack.com:rating")
(ratings_command . "/usr/local/bin/scribbu")
(ratings_command_args . ("popm" "-v" "-a" "-A" "-b" "-o" "sp1ff@pobox.com" "-r" "%rating" "%full-file"))
(gen_cmds .
(((name . "set-genre")
(formal_parameters . (Literal Track))
(default_after . 1)
(cmd . "/usr/local/bin/scribbu")
(args . ("genre" "-a" "-C" "-g" "%1" "%full-file"))
(update . TrackOnly))
((name . "set-xtag")
(formal_parameters . (Literal Track))
(default_after . 1)
(cmd . "/usr/local/bin/scribbu")
(args . ("xtag" "-a" "-o" "sp1ff@pobox.com" "-T" "%1" "%full-file"))
(update . TrackOnly))
((name . "merge-xtag")
(formal_parameters . (Literal Track))
(default_after . 1)
(cmd . "/usr/local/bin/scribbu")
(args . ("xtag" "-m" "-o" "sp1ff@pobox.com" "-T" "%1" "%full-file"))
(update . TrackOnly)))))
| Jump to: | C F I P T |
|---|
| Jump to: | C F I P T |
|---|