A Universal Network Music Player

Posted February 21, 2015 by whistlinginthedark
Categories: electronics, music, tech

Ever more of my music collection is in the form of MP3s, but the only way to listen to it was by sitting at the PC or carrying my phone around the house and wearing headphones. So I was looking for a way to do Hi-Fi playback without buying into one of the various network audio systems.

  • avoid buying more electronics
  • make my old boom box network capable
  • find something useful to do for that Raspberry Pi I had lying around
  • web-based control
  • stream sound from multiple sources: PC, mobile, music server

The embedded Linux distro Volumio seemed to fit the bill, so I installed it and had it running in a few minutes. (Note: Version 1.55 hangs during boot, but Version 1.51 works well). Great, my pre-internet stereo is now capable of playing back music via AirPlay and DLNA. But I also wanted it to be Squeezebox player, so I set up squeezelite, which involved some non-trivial bits:

  • use the armv6hf build
  • to avoid clicking and popping in the audio, add the -a :8 option

Download the binary:

wget -O /opt/squeezelite http://squeezelite-downloads.googlecode.com/git/squeezelite-armv6hf
chmod +x /opt/squeezelite

Install and activate the service script:

# copy the script at the end of the post into /etc/init.d/squeezelite
chmod +x /etc/init.d/squeezelite
chkconfig squeezelite on

# test the service script
service squeezelite start
service squeezelite stop

Open issues:

  • play back music directly via Bluetooth
  • squeezelite causes a noticeable hiss on the output

Here’s the startup script:

#!/bin/bash
### BEGIN INIT INFO
# Provides:          squeezelite
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: SqueezeLite Software Player
# Description:       SqueezeLite Software Player.
### END INIT INFO

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="SqueezeLite Software Player"
NAME=squeezelite
DAEMON=/opt/$NAME
PIDFILE=/var/run/$NAME.pid
DAEMON_ARGS="-n Volumio -s 192.168.30.128 -P $PIDFILE -a :8 -z"
SCRIPTNAME=/etc/init.d/$NAME

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
[ -r /etc/default/$NAME ] && . /etc/default/$NAME

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --exec $DAEMON -- \
                $DAEMON_ARGS \
                || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
        # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
        #
        # If the daemon can reload its configuration without
        # restarting (for example, when it is sent a SIGHUP),
        # then implement that here.
        #
        start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
        return 0
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  status)
        status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $?
        ;;
  #reload|force-reload)
        #
        # If do_reload() is not implemented then leave this commented out
        # and leave 'force-reload' as an alias for 'restart'.
        #
        #log_daemon_msg "Reloading $DESC" "$NAME"
        #do_reload
        #log_end_msg $?
        #;;
  restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
        echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2
        exit 3
        ;;
esac

:

Some Irish songs to keep ya going

Posted October 29, 2011 by whistlinginthedark
Categories: music

Tags: ,

I know it’s been a while. Here are some of my favorite song performances.

8tracks mix

Favorite Flute Recordings

Posted June 9, 2011 by whistlinginthedark
Categories: music

Tags: , ,

I’ve put together a mix on 8tracks. Enjoy, and don’t forget to “like” it.

Eleanor Plunkett (O’Carolan)

Posted October 27, 2010 by whistlinginthedark
Categories: music

Tags: , , , ,

A gorgeous O’Carolan tune in 3/4 time, played and accompanied both by yours truly. I’m playing the Eb-body of my Grinter, and I love how both the warmth and the edge of this amazing flute come through.

Eleanor Plunkett

A neat site for ABC users

Posted May 31, 2010 by whistlinginthedark
Categories: music

Tags: , , ,

For those of us using and reading ABC, there is an awesome new site. Drawthedots.com renders ABC interactively and lets the user collect and share an online tune book.

Three Jigs

Posted March 13, 2010 by whistlinginthedark
Categories: music

Tags: , , ,

I have an Eb body for my keyed flute, and it may sound strange, but that half-step up completely changes how the flute feels – much brighter and more responsive. So I talked my son into tuning up his fiddle, and here’s the result. Three jigs – Tobin’s, The Sunnyside and the one that comes after whose name I’m too lazy to look up.

Chicken Coop

Posted February 27, 2010 by whistlinginthedark
Categories: tech

Tags:

This is one of those rare non-ITM related projects – we’re trying to keep a few chicken in the city, as a balance for our kids and the occasional eggs. Being the geek that I am, I decided to model the thing in Blender first. This is how it looks so far:

Those cones are my abstraction of the hens. I had to make sure somehow that they’ll fit.