Some pianod Uses
The X10 daemon I use (a customized version of Anya Turnquist’s exTENd) can be set up to invoke an arbitrary command in response to an X10 event. I imagine most home automation systems have similar facilities.
I use invokable shell script (using the #!/bin/ksh syntax; see
exec(2) if you’re unfamilar with UNIX’s
#!) that issues
piano commands in to control
pianod in response to clicks X10 controllers through
the house. Shell scripts make great “impedance
matching” tools to get different utilities to work together.
If you’re not acquainted, I recommend taking some time to
familiarize yourself with (in order of preference)
sh(1). Don’t waste time
csh(1) and variants; they don’t have
csh programming is considered
Shared Music Server with Autotuning
pianod implements an algorithm to select stations
best compatible with the current listeners. It can determine who is
listening in 2 ways:
Proximity based—Using a list provided by an external helper program such as Proximity. If each listener has an identifying mobile device (detectable via 802.11 ping or BlueTooth equivalent), use this method.
Based on users currently connected/authenticated with
pianod. If everyone can have a client connected, use this method.
You can also combine the two methods, allowing some of both.
Each user indicates whether they like, hate, or are neutral
about each station. Whenever the listener list changes,
pianod adjusts the stations to the current listeners,
- Stations everybody likes
- Stations somebody likes and nobody hates
- Stations nobody hates (i.e., everyone will tolerate).
If no agreeable stations are found, or there are no listeners,
pianod provides silence.
A nice feature of Pandora is the wide selection of music it offers. It makes it easy to define collections of different genres and styles, then blend them based on your mood with the shufffle (formerly the QuickMix). However, there are times it would be nice to preprogram the mood—for example, “setting a mood”.
You might want the evening to start with some nice classical piano for dinner, change to something a little more romantic later in the evening, and finally switch over to your love goove as the night heats up. A mixplan is a declarative program that describes how you want the music to mix:
# My Romantic Evening mixplan now piano concerti 18:00 start // start playing 20:00 jazz fusion 21:00 barry white radio // Justify My Love Radio refers to the song on Madonna's // "Erotica" song 22:00 justify my love radio + yes radio 00:00 stop
The format is simply a time (or “now”) followed by a list of patterns that will match station names. Comments are allowed in shell (#) and C++ (//) form.
runmix script included in the
contrib directory is used to run mixplans. The format
runmix [-n] <mixfile>
The -n option causes the mixplan to be validated without scheduling/execution.
A mixplan is valid if every station pattern (not line) matches 1 or more station. Patterns matching 2 or more stations are reported, but considered valid.
If a mixplan is valid,
at(1) is used to change the
mix at the requested times. Note on OS X,
at must be
manually enabled. See
atrun(8) for instructions.
The automix sample above is a start, but the transitions may be a bit harsh. After sketeching out what I want to achieve, I find it pleasing to add steps in between to make the transition more gradual:
# My Romantic Evening mixplan now piano concerti 18:00 start // start playing 19:00 piano concerti + light jazz 19:20 light jazz 19:40 light jazz + jazz fusion 20:00 jazz fusion 21:00 jazz fusion + funk radio // Trying the transition via funk 21:20 funk radio + yes radio 21:40 yes radio // Justify My Love Radio refers to the song on Madonna's // "Erotica" song 22:00 justify my love radio + yes radio 00:00 stop
Now that the music is planned, there’s just getting some candles, preparing a nice meal, and finding a date!
kshbecause when dealing with pipelines, the current process performs the tail of the pipe, which is usually What You Want (i.e., collecting some output for further manipulation). However, this diverges from the original
sh(1) behavior in which the current process performs the front of the pipe (which requires redirecting output into a temporary file, then extracting it without using a pipe before further processing). ↩︎