Some pianod Uses
Home Automation
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)
ksh
(1)1,
bash
(1), or sh
(1). Don’t waste time
on csh
(1) and variants; they don’t have
functions and csh
programming is considered
hazardous.
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,
prefering:
- 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.
Automixing
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.
The runmix
script included in the
contrib
directory is used to run mixplans. The format
is:
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.
Blending Automixes
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!
-
I prefer
ksh
because 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 originalsh
(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). ↩︎