Sunday, November 28, 2010

LPD Music Hack - How it's done

People have been asking how to achieve the lpd music hack, which was used at Friday night geekery #1.

First of all I would like to explain that the idea is not my own. OpenBSD developers have been using this technique at their hackathons for years now. I was first exposed to this hack at p2k9 when I was enrolled as an OpenBSD dev, then i asked for the configs at p2k10. So basically the message is "this was not my idea, but it's awesome".

Requirements



A single music server which maintains a playlist, playing tracks one at a time. Users should be able to queue their own music from their own machines without having to put anything into a database up-front (which is why mpd sucks for this). Users should be able to view the playlist.

Seems simple huh? Well no software I know does this.

Configure Server




  • Find a machine capable of playing audio and install OpenBSD on it. Do not enable aucat, or if you do, make sure the daemon user can use the aucat socket.

  • Set up a print spool that will use a shell script as it's filter. An /etc/printcap like this:

    mp3|lp:\
    :lp=/dev/null:mx#0:if=/opt/bin/mp3spool:sd=/var/spool/output


  • Permit remote printing

  • Set up an /etc/hosts.lpd and list hosts that should be able to play music. If you are in a trusted network, you can just stick in a '+', meaning "everyone with a reverse lookup name". If your hosts do not have reverse DNS records, then list them in /etc/hosts instead. Make sure that /etc/resolv.conf is configured correctly to do so.

  • Make the spooling script

  • Make the script that 'if' refers to in the print spooler, so in our case /opt/bin/mp3spool.


    /usr/local/bin/mplayer -vo null -af resample=48000 - || true > /dev/null 2>&1


    Make sure the script is executable.

  • Start lpd


  • Just type `lpd` as root. If you want lpd t start at boot, `echo 'lpd_flags=""' >> /etc/rc.conf.local`

  • Test the server

  • `lpq` should display 'no entries' and you should be able to queue songs using `lpr /some/song.mp3`, for example.


Configure Clients




  • Set up spooler

  • In /etc/printcap:

    lp:\
    :lp=:rm=servers_ip_here:rp=lp:sd=/var/spool/output:lf=/var/log/lpd-errs:


  • Start spooler in the same way as the server, `lpd`


  • Test clients

  • `lpq` and `lpr` should work in the same way as on the server.


That's it!

A few extra notes:


  • When you are using `lpq`, song names may be too long and truncated to '...', in which case, you would use `lpq -l`.


  • User's may de-queue their own tracks using `lprm jobnumber`, as long as the song is not already playing. The job number is found in the short `lpq` output.


  • Assign a "queue admin" who has root access on the server. If a crap song comes on and 3 people vote it off, the queue admin can kill the job using lprm as root.

  • If others don't use lpd or can't be arsed to set up cups (i don't blame you), then you can distribute a script to queue songs locally from the server. This is what we used:



    #!/bin/sh

    host="username@servername"
    path="/tmp/"

    if [ "$1" = "" ]; then
    echo " q.sh "
    echo " q.sh -l"
    exit 1
    elif [ "$1" = "-l" ]; then
    ssh ${host} lpq -l
    exit 0
    fi

    file="`basename \"$1\"`"
    scp "$1" "${host}:${path}\"${file}\""
    ssh ${host} "lpr ${path}\"${file}\""
    ssh ${host} "rm ${path}\"${file}\""


    If you do this you will either have to set up a user account for each user (if you want to see who queued what in the playlist), or if you are lazy, use a single user account on the server.


So, it's quite a hack and it amazes me that there is no better solution yet. Please someone write one.

Please leave know-it-all comments underneath, if you must.

3 comments:

Alpha said...

http://sqweek.dnsdojo.org/code/m9u/ is similar in functionality to what you accomplished, though yours doesn't require some weird environment. :-)

vext01 said...

I recently wrote this, which replaces lpd hack:

https://github.com/vext01/hgd/

sqweek said...

9p is not a "weird environment" :P

sqweek.dnsdojo.org is going down though, the new link is:

http://sqweek.net/code/m9u/