Implementing “Bob’s Listening To”

I put up on my web page what I am listening to at the moment. This article tells how I do that.

I listen to music through the Squeezebox, a fabulous device made by SlimDevices that plays MP3s you have on your computer through your stereo system. “SlimServer” is the server that runs on whatever computer you have handy, that you talk to through a web interface, and feeds the music wirelessly to the Squeezebox. SlimServer can also report its current status, including the current song being played, in XML format, which turns out to be useful, via the URL:

http://slimserver:9000/xml/status.html

Using wget or lwp-request, I grab this data and then process it through XSLT to get a simple string of the form SONG by ARTIST from ALBUM:

<?xml version="1.0"?>
<!-- slim-putsong.xsl:
transform slimserver XML status output into SONG by ARTIST from ALBUM -->

<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:sl="http://www.slimdevices.com/slimserver/xml"
version="1.0"
>

<xsl:output method="html" omit-xml-declaration="yes"/>

<xsl:template match="/">
<xsl:for-each select="sl:status/sl:player_status/sl:current_song/sl:song">
<b><xsl:value-of select="sl:title"/></b> by
<b><xsl:value-of select="sl:artist"/></b> from
<b><xsl:value-of select="sl:album"/></b>
</xsl:for-each>
</xsl:template>

</xsl:transform>

With Slimserver 6.x, the XML format was changed. 🙁 The “sl:song” portion of the for-each statement above needs to be removed.

You can apply this XSLT through a tool such as xsltproc.

I wrote a little shell script which grabs the URL, transforms it, and FTPs it to my server:

#!/bin/sh

# shell script to create HTML of current song playing on Squeezebox,
# and ftp'ing a file containing that information to bob's blog.

wget --quiet --output-document=-  http://localhost:9000/xml/status.xml | \
xsltproc --novalid slim-putsong.xsl - > slim-putsong.html

ftp -i -n my.host.name <<EOF
user user password
cd /some/directory/
put slim-putsong.html
bye
EOF

To prevent FTP’ing an unchanged file, precede the ftp line with

diff slim-putsong.html prev-slim-putsong.html > /dev/null ||

Run this script from cron however often you want.

All that remains is to include the HTML file into the web page you want the info to appear on, with something like

<? include 'slim-putsong.html'; ?>

8 Responses to “Implementing “Bob’s Listening To””

  1. Johan Says:

    Hold it…. You r going to fast for me… 😉

    I am using an windows machine and am not a wizard in programming… I\’ll get there in the end… How can I achieve this on my machine… Will/can you help me?

    p.s. i have XSLT/XML PHP APACHE installed and working…

  2. Bob Myers Says:

    On Windows, I\’d recommend doing this under Cygwin. That will give you all the pieces you need, including wget (to retrieve the information from the SlimServer), xslt (to transform it), and cron (to run the script every so often).

  3. Johan Says:

    Well i have my server running at home and have the info available. So i don\’t need to use wget. XSLT i have got working. I can use scheduling in windows to run a batch programme ever so often. My problem now is to get the xsltproc to work with the XML programme you have written. Where do you put the data the XML proc needs? I can\’t find any location information of the input and export file.

  4. tamagen Says:

    A quick and dirty approach would be to read the XML from a php page on your web server, assuming you can get access to the slimserver http server from your normal web server – you may need to poke a hole through a firewall.

    Something like this would work in that case (change localhost to the name or ip address of your slimserver or external nat router interface etc., and since you can\’t use angle brackets here replace the strings LEFTBRACKET and RIGHTBRACKET with left and right angle brackets respectively):

    LEFTBRACKET?
    $xml = fread(fopen(\”http://localhost:9000/xml/status.xml\”,r),9999);
    if (eregi(\”LEFTBRACKETplaymodeRIGHTBRACKETplaying\”,$xml)) {
    if (preg_match(\”/LEFTBRACKETtitleRIGHTBRACKET([^LEFTBRACKET]*)LEFTBRACKET\\/titleRIGHTBRACKET.*?LEFTBRACKETartistRIGHTBRACKET(.*?)LEFTBRACKET\\/artistRIGHTBRACKET.*?LEFTBRACKETalbumRIGHTBRACKET(.*?)LEFTBRACKET\\/albumRIGHTBRACKET/s\”, $xml, $m)) {
    $track = $m[1] . \” by \” . $m[2] . \” (Album: \” . $m[3] . \”)\”;
    }
    echo \”I am listening to: $track\”;
    }
    ?RIGHTBRACKET

  5. Joel Aufrecht Says:

    Here\’s a modified version of the bash script, which uses ssh instead of ftp:
    #!/bin/sh

    # shell script to create HTML of current song playing on Squeezebox,
    # originally from http://bob.myers.name/blog/article/249
    # modified by Joel Aufrecht Oct 2004 to use scp

    # check for input
    if [[ -z \”$1\” || -z \”$2\” ]]
    then
    echo \”Usage: putsong.sh target-destination identity-file
    Example: To upload a song every 3 minutes, using a dedicated ssh
    account called \\\”upload\\\”, put this in your crontab:

    */3 * * * * sh /etc/slimserver/putsong.sh upload@foo.bar:/tmp/song.html /home/me/.ssh/upload\”
    exit
    fi

    STATUS=/tmp/status.xml
    STATUS_HTML=/tmp/song.html

    wget—quiet—output-document=$STATUS http://localhost:9000/xml/status.xml
    # if song is not playing, do nothing
    if [ \”`grep -c \’playing\’ $STATUS`\” -eq \”1\” ]
    then
    xsltproc -o $STATUS_HTML—novalid /etc/slimserver/slim-putsong.xsl $STATUS
    echo \”at `date`\” >> $STATUS_HTML
    scp -i $2 $STATUS_HTML $1
    fi

  6. Joel S Aufrecht Says:

    Here\’s a version of slim-putsong.xsl which does not output the \”by\” or \”from\” text if artist or album is missing:

    0\”>

    0\”>
    by

    0\”>
    from

  7. Hywel Mallett Says:

    Thanks Bob!
    I’ve implemented this myself, in about 10 minutes (including installing libxslt). My scenarios easier than yours, as the web server and slimserver are the same, so mine just creates the file in the correct location. Great instructions though!
    H

  8. Paul Henry Says:

    For multiple squeezeboxes, don’t forget to query the right one!

    Modify wget source as http://localhost:9000/xml/status.xml?player=name_of_player

Leave a Reply