MPDDP 2 Signals
Greetings, legion of MPDDP users, there is another update! With it, MPDDP has been bumped to version 2.0.1, as the configuration file format is the same, so things will keep working, but the “update” keyword no longer does anything.
But why? I used that feature, how dare you deprive me of it!?
Well, allow me to explain…
The “update” keyword was, really, not very good. It worked by telling MPDDP to enable a silly behaviour whereby it reloaded the configuration and rules every so many minutes. This produces unnecessary disk accessing (albeit not much of that), and CPU load when querying MPD for tracks and figuring out which ones we can use (which can be a lot, MPDDP 2 isn't terribly efficient yet). All in all, it was a Bad Thing. But it was the only way to notice changes in configuration without restarting MPDDP 2, which is very slow depending on how many rules you have enabled.
Depending on how many rules you have enabled? I thought it depended on how many rules you had!
Well, yes, it did. That's the second thing I have changed. MPDDP 2 will now only figure out what tracks are allowed for the allowed rules, not all of them. This speeds up starting MPDDP 2 massively. Anyway, back to signals…
…fast forward to today, when I'm skimming through wikipedia and end up on the article for POSIX signals. I then learn that dd prints progress information when sent SIGUSR1 (yes, I too was amazed) and a thought hit me: why can't I do the same with MPDDP 2? So, off to the Python documentation for signals I went and now MPDDP 2 has some nice new behaviour:
- SIGUSR1 tells MPDDP 2 to reload the configuration but not the rules.
- SIGUSR2 tells MPDDP 2 to reload the rules but not the configuration.
Individually, you can use them for things like changing the length of the playlist, with SIGUSR1, and editing the conditions of a rule, with SIGUSR2. Together, you can change which rules are active.
I think this is a very elegant solution. We've gone from checking continuously to see if something has happened, to waiting to be notified that something has happened. After editing the config file, it's only a little extra effort to send MPDDP 2 the appropriate signal(s), and you're not getting unrequired disk/CPU usage every few minutes just in case you changed something.
MPDDP 2: Functionally complete
That's right, MPDDP 2 is now functionally complete, it can do everything that regular MPDDP can, and more. The downside is that, currently, it's incredibly slow to start up, but I'm thinking of a solution for that.The whole routine for checking if a track is allowed by the rule is fairly inefficient currently, so that'll likely be rewritten completely soon and, for ease of parsing, I might change the rule syntax to S-expressions. Perhaps a MPDDP 2.1 already?
Barrucadu's Guide to MPDDP Version Numbers
Which number has changed?
- X.y.z: everything has changed completely. Your configuration file definitely won't work.
- x.Y.z: something big has changed more-or-less completely. Your configuration file probably won't work
- x.y.Z: something has changed, but not really that much; probably just a bugfix. Your configuration file should be fine.
Configuration
MPDDP 2 has a completely different configuration syntax to MPDDP, here's an example:
MPDDP
server = localhost
path:fred/
Connect to the MPD server at localhost and use all tracks in the path fred/.
MPDDP 2
rule fred {
path ~= "fred/"
}
host localhost
active fred
Connect to the MPD server at localhost, and use the rule fred, which matches all tracks with a path containing fred/.
While these two examples are functionally equivalent, the MPDDP 2 example is longer. In fact, my MPDDP 2 config file is a lot longer than my MPDDP config file, but that's because currently it's a direct translation of my MPDDP config file to MPDDP 2 syntax, and I'm not using many MPDDP 2 specific features yet. However, MPDDP 2 can do things that regular MPDDP can't, or can only do using the MPDSPL integration (which has been removed from MPDDP 2). Consider the following, for example:
rule firstfred {
artist = "fred"
album = "first"
}
A rule which matches all tracks by "fred" in the album "first", or the following:
rule fg {
artist = "fred" or \
artist = "george"
}
A rule which matches all tracks by "fred" or "george". Also, note that I split the line into two by putting a backslash before the newline. You can escape newlines like that anywhere in the config file. I suppose that's enough examples for now, now I shall go into more detail about how the rules work.
Rules
Each rule is more correctly known as a ruleset. Each ruleset is broken up into several rules (one line = one rule), and each rule is broken up into several conditions (eg: 'artist = "fred"'). A track matches the ruleset if it matches all of the rules.
Conditions have two forms, the first takes three parameters, the second only one.
'Normal' Conditions
These conditions are in the form "keyword comparison value" (or "value comparison keyword" (or even "keyword comparison keyword", or "value comparison value")), where the keyword is one of the following:
- artist
- album
- title
- path
- file
- genre
- time
Comparison is one of the following:
- = (A equals B)
- != (A does not equal B)
- ~= (A contains B)
- !~= (A does not contain B)
And the value is a string contained in quotes. The following are all valid conditions:
- album ~= artist
- artist ~= "Fred"
- path !~= "boring-music/"
'Rule' conditions
These conditions take only one parameter, the name of a rule. These conditions evaluate to true if the track matches the given rule. These are best explained through an example:
rule fred {
artist = "fred"
}
rule fredfoo {
rule "fred"
album = "foo"
}
The rule fredfoo would then match all tracks which have artist "fred" and album "foo".
Chaining conditions together
As I said, each rule can contain several conditions. These conditions are chained together with the boolean operations "and", "or", and "xor", for example:
- artist = "fred" or artist = "george"
- album = "foo" xor path ~= "bar/"
Putting it all together
So, now you can have rules like this, which would be impossible in MPDDP, even with the MPDSPL integration:
rule dark {
artist = "Nox Arcana" or \
artist = "Mortiis"
album != "Grimm Tales"
title !~= "Child"
}
A rule to return all tracks by Nox Arcana and Mortiis which do not contain "Child" in the title and are not in the album Grimm Tales.
Configuration Continued
So, what other than the rules and a bit of syntax is different for configuration? Well, MPDDP 2 can't save the playlist, or clear the playlist when it starts, any more. I never used those features, so I removed them, and MPDDP 2 now supports password-protected MPD servers! Also, as I'm sure you noticed, the "=" is gone. I might add that back…
So, here are all the configuration options for MPDDP 2:
- host
- port
- password
- changeafter
- playlistlen
- update
- active
The "active" option is a little special, it's a comma-delimited list of rules which should be used. This lets you specify many rules and, without commenting hundreds of lines out, indicate that only one or two of them should be used.
MPDDP 2 does have command-line parameters, which take priotity over the values in the config file, but I'm sure you can figure those out for yourself from the help text.
Half Term Week, and, one month of Spork Bomb
Well, one month tomorrow, but near enough.
School has ended for half term week—a whole 5 week days off, and what shall I do with this vast amount of free time on my hands? I have a couple of plans. Firstly, Erasmus. I'd like to hit version 0.1 and make a dent in 0.2 this week, as I have free time I can't really hit a snag and put off solving it indefinitely due to “schoolwork”.
Remaining 0.1 features:
- Working memory manager
- IDE driver
- ATA driver
The IDE and ATA drivers have sort of merged, which is ok, for now; I can separate them when I start on ATAPI. The memory manager is there, but doesn't work: I'm going to write one from scratch rather than just borrowing/editing code, as then I'll definitely know what's going on.
After Erasmus, fractalgen. I want to figure out how to create arbitrarily large images with gd; if I try to make one too big it complains about the size exceeding INT_MAX, or something like that. I refuse to believe gd has such a limitation that has no work-arounds when it comes to large images. I also want to start on my fviewer program, a GUI to display / zoom fractals. Smooth colour shading would be nice, but it's not really a high-priority feature currently.
Of course, there are always books. I've still got a heap of books from Christmas to read, and with 9 days before school again, I should be able to get through at least one, perhaps two. I make it sound like I try to read books as quickly as possible, which isn't entirely true: I just dislike having unread books lying around, when I re-read books, I do take my time and generally notice things I didn't the first time through.
Leading on to other forms of entertainment: anime. I have borrowed the first two seasons of Claymore which, hopefully, I'll enjoy. Claymore is about a world in which humans coexist with yoma, demons, where there exists a group of half-human half-yoma warriors, the Claymores, who protect the humans (for a fee).
Finally, after mpdspl was rewritten to be much better by sdelafond, I have been spurred into action to improve mpddp. A complete rewrite; a second version. It will be object-orientated and have much better code organisation (the current program is a mess: why I change it so very rarely), and I have a vague notion of wanting a “more powerful” config syntax. Currently each line of a config file acts as a boolean OR: including everything which matches this line, OR that line, OR another… I want to include more boolean operations, AND at the very least, perhaps NOT (that's currently worked-around by the “never” keyword) or XOR, too.
Of my plans, mpddp 2 is the one I'm most excited about implementing. I can barely remember how the current code works, so I'll most likely read through it to figure out which functions do what, and then just write version 2 from scratch.







