Tuesday, August 19, 2014

Infra-red remote controlling LMS on RPi

Acronym soup follows - but as a quick summary ... this is about controlling, via an infra-red remote control, the sounds from a Logitech Media Server.

I wanted to get a Creative Labs Soundblaster X-Fi Surround 5.1 Pro USB Sound Card (part number SB-1095 with remote RM-820) working with one Raspberry Pi that is set-up as a Squeezebox music server (LMS) and player (Squeezelite) and a different RPi working with the IQaudIO DAC and a generic Philips remote control.

Getting the sound working was pretty straight-forward but I also wanted to make use of the infra-red remote controls to at least control the volume and ideally do much more.

Why not simply use the web interface or a smartphone or tablet or a real Squeezebox to control it?
Well, they can be used of course and are needed to select what to play but leaving the simple remote near the player makes it very easy for someone to pause the music when the phone rings, skip a track or pump up the volume.

Getting it to work required pulling a few things together and then doing some custom scripting.

Most of this is not Raspberry Pi specific - it should work on nearly any Linux system. The exception is the installation of the IR receiver for the Philips (and in theory any other regular remote).
Note: there is no need to install an IR receiver for the Soundblaster because there is one built-in to the device and for this particular device this also works with the rotary control that is on top of the device (twist for volume and push for mute/pause).

Here is what it looks like. This is the RPI with the IQaudIO DAC installed and the lid removed from the IQaudIO case. The DAC is attached to the RPi in the top right.
Attached to that is the infra-red receiver - with the "eye" attached (using blue sticky stuff) so that a signal can get through the holes along the top edge of the IQaudIO case (you cannot see them),



So here is how I did it.

I decided to use the "expect" application to drive LMS because it has can send data in "telnet" style, as made available through the LMS CLI, and then take actions using a simple built-in scripting language based on the reply.

Text below that is in monospaced font and/or red shows what appears on the console or needs to be typed.

The full "expect" script is below. Some key points from it are:

  • This assumes that you have already installed Squeezelite and it has access to LMS either locally on same system or somewhere remote that can be accessed through the network (for example by installing SqueezePlug on RPi)
  • "expect" and possibly "telnet" might not be installed on your system. In which case you will have to install them yourself. On Debian-based systems (like Raspbian for Raspberry Pi) you can do this with
    sudo apt-get install expect telnet
  • If you are going to force actions via infra-red (IR) remote control then you will also need to install "lirc"
    sudo apt-get install lirc
  • You might not have the ALSA sound utilities installed. They are used to control some of the sound settings ... to install them you would do
    sudo apt-get install alsa-utils
  • Settings (such as where is the LMS server relative to this controlling client) are included in the file but they can also come from the settings file for Squeezelite ... in which case you probably would not have to edit this file at all.
  • Lines that start with "# " are comments. Some of them have some tracing statements to help if things are not working as expected. Simply remove the "#" from the front
    e.g.
    # puts "settings: host:\"$params(SBSHOST)\" and player MAC:\"$params(SLMAC)\""
    becomes
    puts "settings: host:\"$params(SBSHOST)\" and player MAC:\"$params(SLMAC)\""
    In this case this will output (puts = put string on console) the settings that were found
  • There are some special functions in there - such as treating the OK button as a special case (to restore things to a default configuration with middle volume, mute off, power on, shuffle off, repeat off) but they should be easy to understand simply by reading the script
  • Take care with line wrapping when copying the file below. It is up to you to work out where the blogging software has wrapped lines that should not have been wrapped. If you cannot do that then contact me directly and ask for a copy of the file to be sent by email to you
  • I stored this file as lmscli.exp in /home/pi/lmscli and performed a chmod on it
    i.e. I logged in as "pi" then
    mkdir lmsclicd lmscli(then copy the file and save as lmscli.exp)
    chmod +x lmscli.expYou can test this by hand like this:
    ./lmscli.exp pauseYou should see something like this if it worked (and any music that was playing via your local Squeezelite should have then paused or resumed)
    spawn telnet 127.0.0.1 9090Trying 127.0.0.1...Connected to 127.0.0.1.Escape character is '^]'.login user passb8:27:eb:aa:bb:cc pauseexitlogin user ******Connection closed by foreign host.Note: the output above is slightly out of sequence but do not worry about it if it worked


Here is the lmscli.exp script (between but not including the separator lines):
------------------------------------------------------------------------------
#!/usr/bin/expect -f

# lmscli "Expect" script
# Author:       Paul Webster
# Version:      0.1
# Date: 29-Mar-2014
##
# Simple script (with no error checking) to send Logitech Media Server (SqueezeCenter) CLI commands to control a player
# Attempts to read parameters from Squeezelite defaults file - where syntax is
# keyword="value"
#
# "Expect" and telnet are required
# sudo apt-get install expect telnet
# Also - if this is to be driven via infrared remote (expected use) then also install lirc
# sudo apt-get install lirc
#

set settingsfile /etc/default/squeezelite

# Defaults
# Values here are overridden by values found in /etc/default/squeezelite (if present)
# SBSHOST = ip address of the LMS/Squeezebox Server
# SBSPORT = port number on LMS that cli runs on (rarely changed)
# SLMAC = the MAC address claimed by the player to be controlled - not always the real MAC address and is specified to Squeezelite
# SBSUSER / SBSPASS = username and password to access LMS. Usually not configured - in which case leave as is
# - if used then make sure that the user/pass fields are URL-encoded (e.g. %20 for space)
array set params {
    SBSHOST     127.0.0.1
    SBSPORT     9090
    SLMAC       00:11:22:33:44:55:66
    SBSUSER     user
    SBSPASS     pass
}

# Override the defaults that are in this script with the ones from the Squeezelite settings
if {[file exists "$settingsfile"]} {
    set fp [open "$settingsfile" r]
    set file_data [read $fp]
    close $fp

    # get lines
    set data [split $file_data "\n"]
    foreach line $data {
        #parse lines for config data
        if {[regexp {^(\w+)\s*=\s*[\"|](.*)[\"|]} $line -> name value]} {
            # puts "found name of \"$name\" with value \"$value\""
            set params($name) $value
        }
    }
}

# puts "settings: host:\"$params(SBSHOST)\" and player MAC:\"$params(SLMAC)\""
# The settings are now in place

set arg1 [lindex $argv 0]
set arg2 [lindex $argv 1]

# puts "recieved arguments of \"$arg1\" and \"$arg2\""
spawn telnet $params(SBSHOST) $params(SBSPORT)
expect "Escape character is *"
send "login $params(SBSUSER) $params(SBSPASS)\n"
expect "login user"


switch $arg1 {

pause   {
                send "$params(SLMAC) pause\n"
                expect "* pause"
        }

bb      {
                send "$params(SLMAC) time -10\n"
                expect "* time"
        }

ff      {
                send "$params(SLMAC) time +10\n"
                expect "* time"
        }

muteoff {
                send "$params(SLMAC) mixer muting 0\n"
                expect "* mixer muting"
        }

muteon  {
                send "$params(SLMAC) mixer muting 1\n"
                expect "* mixer muting"
        }

next    {
                send "$params(SLMAC) playlist index +1\n"
                expect "* playlist index"
        }

prev    {
                send "$params(SLMAC) playlist index -1\n"
                expect "* playlist index"
        }

power   {
                send "$params(SLMAC) power\n"
                expect "* power"
        }

voldown {
                send "$params(SLMAC) mixer volume -2.5\n"
                expect "* mixer volume"
        }

volup   {
                send "$params(SLMAC) mixer volume +2.5\n"
                expect "* mixer volume"
        }

shuffle {
                send "$params(SLMAC) playlist shuffle\n"
                expect "* playlist shuffle"
        }

repeat  {
                send "$params(SLMAC) playlist repeat\n"
                expect "* playlist repeat"
        }

stop    {
                send "$params(SLMAC) stop\n"
                expect "* stop"
        }

ok      {       #Restore to base values
                send "$params(SLMAC) playlist repeat 0 1\n"
                expect "* playlist repeat"
                send "$params(SLMAC) playlist shuffle 0\n"
                expect "* playlist shuffle"
                send "$params(SLMAC) mixer volume 50\n"
                expect "* mixer volume"
                send "$params(SLMAC) mixer muting 0\n"
                expect "* mixer muting"
                send "$params(SLMAC) power 1\n"
                expect "* power"
}

default {puts "Unknown command issued to lmscli"}

}
# End of switch (do not put on same line as the closing brace)

send "exit\n"
expect eof
------------------------------------------------------------------------------

Next step is to get the commands that are sent by infra-red to get sent to lmscli.
I have not covered all of the steps required to get lirc working (there are plenty of posts and FAQs about that elsewhere) - so all I am showing here are the configuration files to link lirc to the "expect" script.

This first file should be saved as "root" in /etc/lirc as lircrc
To be safe, make a copy of the file that is already there (if there is one).
This particular file is set-up to handle 2 different remote controls, "RM-820" and "philipsdvd".
Therefore you will see that many of the functions are repeated. By doing it this way it meant that I could have the same config file on two different RPi systems, making life easier for me.
The full file is below - some key points from it are:

  • the "remote =" line define which remote control this is referring to. It has to match the name used in other lirc config files (see more about that much further below)
  • the text after the "button =" has to exactly match what you have mapped the button presses to for the particular remote control - via the lirc config files (see more about that much further below)
  • I was still getting occasional lock-ups resulting in no sound coming out or sometimes a few digital burps and in worst case the Ethernet connection stops responding. So while trying to work out why that was happening (and I had tried what was the most recent official firmware and the work-in-progress FIQ handler at the time) I mapped one of the keys to a "reboot" command. I chose the long-back command on the RM-820 or the "scan" button on the Philips remote rather than Power for that as it very unlikely to be used accidentally and the Power key is mapped to the player power function on LMS because sometimes toggling the soft power button is enough to get things working again since Squeezelite releases something when it is told to power down. However, if you face similar problems and you do not have a button/function that you can readily map then you could edit the "#Power" section below to comment out the current "config =" line (by putting a "#" in front of it) and then put in "config = reboot". Applications/scripts that are invoked by lirc are run as "root" so you do not need to put "sudo" in front. This makes it very powerful and dangerous so take care
  • the volume is controlled through ALSA (sound libraries) directly. Therefore I set the command to change the volume via ALSA and also repeat the command to LMS so that it shows the volume change. However, these are not really matched up so it would be easy to have LMS show a very different volume to what is really set in ALSA. To help get around that potential issue I configured things to use the "OK" button to try to return this setting (and some others) to defaults. There is similar trickery in place for the "mute" function for the same reason. The ALSA settings are stored so that they can be restored when needed. The hint for some of this came from http://alsa.opensrc.org/Usb-audio and possibly other places that I found while hunting for a solution but have since forgotten.


------------------------------------------------------------------------------
# Power
begin
    prog = irexec
    remote = RM-820
    button = power
    config = /home/pi/lmscli/lmscli.exp power
    # config = reboot
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_POWER
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp power
end

# Hold the menu button down for a long time ... to try to force a reboot
begin
    prog = irexec
    remote = RM-820
    button = menu/back-long
    config = reboot
end

# On philipsdvd remote - there does not seem to be a long-hold ... so use the "scan" button - saved as SYSRQ
begin
    prog = irexec
    remote = philipsdvd
    button = KEY_SYSRQ
    repeat = 0
    config = reboot
end

# S51 Volume Knob
begin
    prog = irexec
    remote = RM-820
    button = knobvoldn
    repeat = 1
    config = amixer sset Master 1- ; /home/pi/lmscli/lmscli.exp voldown
end

begin
    prog = irexec
    remote = RM-820
    button = voldn
    repeat = 1
    config = amixer sset Master 1- ; /home/pi/lmscli/lmscli.exp voldown
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_DOWN
    repeat = 1
    config = amixer sset Master 1- ; /home/pi/lmscli/lmscli.exp voldown
end

begin
    prog = irexec
    remote = RM-820
    button = knobMute
    repeat = 1
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0; amixer sset 'Power LED' off; /home/pi/lmscli/lmscli.exp muteon; else alsactl restore -f ~/.asound.state; amixer sset 'Power LED' on ; /home/pi/lmscli/lmscli.exp muteoff; fi
end

begin
    prog = irexec
    remote = RM-820
    button = mute
    repeat = 1
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0; amixer sset 'Power LED' off; /home/pi/lmscli/lmscli.exp muteon; else alsactl restore -f ~/.asound.state; amixer sset 'Power LED' on ; /home/pi/lmscli/lmscli.exp muteoff; fi
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_AUDIO
    repeat = 1
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0;  /home/pi/lmscli/lmscli.exp muteon; else alsactl restore -f ~/.asound.state; /home/pi/lmscli/lmscli.exp muteoff; fi
end

begin
    prog = irexec
    remote = RM-820
    button = play-pause
    repeat = 1
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0; amixer sset 'Power LED' off; /home/pi/lmscli/lmscli.exp pause; else alsactl restore -f ~/.asound.state; amixer sset 'Power LED' on ; /home/pi/lmscli/lmscli.exp pause; fi
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_PAUSE
    repeat = 0
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0; /home/pi/lmscli/lmscli.exp pause; else alsactl restore -f ~/.asound.state; /home/pi/lmscli/lmscli.exp pause; fi
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_PLAY
    repeat = 0
    config = if [ `amixer sget Master|grep "Front Left:"|awk '{print $3}'` -gt 0 ]; then alsactl store -f ~/.asound.state; amixer sset Master 0; /home/pi/lmscli/lmscli.exp pause; else alsactl restore -f ~/.asound.state; /home/pi/lmscli/lmscli.exp pause; fi
end

begin
    prog = irexec
    remote = RM-820
    button = knobvolup
    repeat = 1
    config = amixer sset Master 1+ ; /home/pi/lmscli/lmscli.exp volup
end

begin
    prog = irexec
    remote = RM-820
    button = volup
    repeat = 1
    config = amixer sset Master 1+ ; /home/pi/lmscli/lmscli.exp volup
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_UP
    repeat = 1
    config = amixer sset Master 1+ ; /home/pi/lmscli/lmscli.exp volup
end

begin
    prog = irexec
    remote = RM-820
    button = bb
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp prev
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_REWIND
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp prev
end

begin
    prog = irexec
    remote = RM-820
    button = ff
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp next
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_FASTFORWARD
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp next
end

begin
    prog = irexec
    remote = RM-820
    button = shuffle
    config = /home/pi/lmscli/lmscli.exp shuffle
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_SHUFFLE
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp shuffle
end

begin
    prog = irexec
    remote = RM-820
    button = repeat
    config = /home/pi/lmscli/lmscli.exp repeat
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_MEDIA_REPEAT
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp repeat
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_MEDIA
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp repeat
end

begin
    prog = irexec
    remote = RM-820
    button = right
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp ff
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_RIGHT
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp ff
end

begin
    prog = irexec
    remote = RM-820
    button = left
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp bb
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_LEFT
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp bb
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_STOP
    repeat = 1
    config = /home/pi/lmscli/lmscli.exp stop
end

begin
    prog = irexec
    remote = RM-820
    button = ok
    config = /home/pi/lmscli/lmscli.exp ok
end

begin
    prog = irexec
    remote = philipsdvd
    button = KEY_OK
    repeat = 0
    config = /home/pi/lmscli/lmscli.exp ok
end

------------------------------------------------------------------------------

Next is the set-up of lirc to know what hardware is being used.
The file shown below is my config file from the RPi that has the Philips Remote control - which is getting the data via a simple IR receiver attached to GPIO pins on the RPi.
However, I have left the RM-820 set-up in there as well - but commented out. So if you are trying to get the Creative device to work then uncomment those lines and comment out the Philips ones.
This file is stored as "root" as /etc/lirc/hardware.conf
------------------------------------------------------------------------------
# /etc/lirc/hardware.conf
#
# Arguments which will be used when launching lircd
#LIRCD_ARGS=""
LIRCD_ARGS=""

#Don't start lircmd even if there seems to be a good config file
#START_LIRCMD=false

#Don't start irexec, even if a good config file seems to exist.
#START_IREXEC=false

#Try to load appropriate kernel modules
LOAD_MODULES=true

# Run "lircd --driver=help" for a list of supported drivers.
# Uncomment the line below (and comment out the one following it) for Creative Labs Soundblaster X-Fi USB DAC
#DRIVER="alsa_usb"
DRIVER="default"
# usually /dev/lirc0 is the correct setting for systems using udev
# Uncomment the line below (and comment out the one following it) for Creative Labs Soundblaster X-Fi USB DAC
#DEVICE="hw:Pro"
DEVICE="/dev/lirc0"
# Uncomment the line below (and comment out the one following it) for Creative Labs Soundblaster X-Fi USB DAC
#MODULES=""
MODULES="lirc_rpi"

# Default configuration files for your hardware if any
# Uncomment the line below (and comment out the one following it) for Creative Labs Soundblaster X-Fi USB DAC
#LIRCD_CONF="creative/lircd.conf.alsa_usb"
LIRCD_CONF="/home/pi/lircd-philipsdvd.conf"
LIRCMD_CONF=""

------------------------------------------------------------------------------

In this case you can see that I put the configuration file for the Philips remote into the /home/pi directory.
Here is the contents of that file.

------------------------------------------------------------------------------
# Please make this file available to others
# by sending it to
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(default) on Wed Apr 16 18:37:15 2014
#
# contributed by
#
# brand:                       lircd-philipsdvd.conf
# model no. of remote control:
# devices being controlled by this remote:
#

begin remote

  name  philipsdvd
  bits            8
  flags RC6|CONST_LENGTH
  eps            30
  aeps          100

  header       2690   871
  one           462   422
  zero          462   422
  pre_data_bits   13
  pre_data       0xEFB
  gap          106190
  toggle_bit_mask 0x10000
  rc6_mask    0x10000

      begin codes
          KEY_POWER                0xF3
          KEY_1                    0xFE
          KEY_2                    0xFD
          KEY_3                    0xFC
          KEY_4                    0xFB
          KEY_5                    0xFA
          KEY_6                    0xF9
          KEY_7                    0xF8
          KEY_8                    0xF7
          KEY_9                    0xF6
          KEY_0                    0xFF
          KEY_BACK                 0x7C
          KEY_DISPLAYTOGGLE        0x10
          KEY_MENU                 0xAB
          KEY_CONTEXT_MENU         0x7D
          KEY_UP                   0xA7
          KEY_DOWN                 0xA6
          KEY_LEFT                 0xA5
          KEY_RIGHT                0xA4
          KEY_OK                   0xA3
          KEY_REWIND               0xDE
          KEY_FASTFORWARD          0xDF
          KEY_STOP                 0xCE
          KEY_PLAY                 0xD3
          KEY_PAUSE                0xCF
          KEY_SUBTITLE             0xB4
          KEY_ANGLE                0x7A
          KEY_ZOOM                 0x08
          KEY_AUDIO                0xB1
          KEY_MEDIA_REPEAT         0xE2
          KEY_MEDIA                0xC4
          KEY_SHUFFLE              0xE3
          KEY_SYSRQ                0xD5
      end codes

end remote
------------------------------------------------------------------------------


For the Creative device I used the default that came with lirc (as you can see from the commented out set-up in the hardware.conf).

For the particular IR module that I used I connected it to GPIO pin 23 - which is one of the pins that the IQaudIO device exports to its connectors on top of the card. I forced this pin to be used by adding the following lines to /etc/modules
lirc_dev
lirc_rpi gpio_in_pin=23
This might not be right for you - so you will need to check the documentation for the IR module that you are using to see how to do it for your particular device. Note - this is not needed for the Creative device because it has a built-in IR receiver and it passes the commands in through the USB connection not GPIO.


As always, if you have questions then ask it in the comments section below and I'll try to answer it.

Monday, January 07, 2013

BBC DQF Local Radio - Part 2

- BBC Local Radio weekday evenings now consolidated

In a post in late 2011 I wrote about the plans to save money in BBC local radio by having a single show across all of the networks. At that time the idea was to have the show in the afternoon - do you remember the ensuing protests to save Danny Baker's show (BBC London).
Well things changed a bit since then. Danny (along with some other afternoon presenters kept their job - although Danny subsequently found his position axed in late 2012) and the consolidation has happened in the evening slot.
Today it went live. The new show takes the name of the presenter "Mark Forrest".
All of the BBC local radio stations in England and Channel Islands now carry it - but they have opt-outs for local sport or other locally significant news - and for the launch show tonight all but Gloucester and Mersyside were broadcasting it.

Compare this schedule view to the ones that I posted in 2011.

If you listened, what did you think of it?


Saturday, May 26, 2012

Running SqueezeSlave on Raspberry Pi

- Running SqueezeSlave on Raspberry Pi

Getting Squeezeslave to run on the RPi is very easy - here is a revised version of the instructions that I posted on the Raspberry PI forum.
NOTE: This has been tested on Debian Squeeze (and I think it also works on Wheezy) - but will almost certainly need some updated to work on hard-float builds such as Raspbian and has been updated since first published to include instructions for Raspbian Wheezy (the hardfloat version of Debian that is endorsed by Raspberry Pi Foundation).
Version numbers shown here were correct when this blog was written but it is possible that newer versions have been released since then ... and they might work better (or worse) so check on Sourceforge (for official release) and GoogleCode (for latest test versions).


Most of what is shown below could be copied to a script and run - but there is no error checking so it is best to run as individual commands - e.g. copy / paste into SSH session

NOTE: Some of the lines below are very long and get wrapped when presented in the blog.
I have left a blank line after those long lines to make it clearer. If you are using copy/paste to replay the commands then make sure that you take the full line and unwrap it if needed.

Start an interactive login to the Raspberry Pi then ...

mkdir squeezeslavesrc
cd squeezeslavesrc
# If on Debian (not Raspbian) then perform the next 2 commands
wget http://sourceforge.net/projects/softsqueeze/files/squeezeslave/squeezeslave-1.2.311/squeezeslave-1.2-311-armel-lnx26.tar.gz

tar -xvf squeezeslave-1.2-311-armel-lnx26.tar.gz


# If on Raspbian (a hardfloat version of Debian) then perform the next 3 commands
wget http://squeezeslave.googlecode.com/files/squeezeslave-1.2-367-armhf-lnx31.tar.gz

tar -xvf squeezeslave-1.2-367-armhf-lnx31.tar.gz

mv squeezeslave-1.2-367 squeezeslave




# at this point you have the various binaries for ARM/Linux so no need to build from source
# and you now have enough to run squeezeslave
# however, by downloading some more files you can make it easier to start/stop squeezeslave

# to test what you already have - assuming you are already running LMS somewhere on the same LAN
# type
./squeezeslave -L
# if this lists audio device(s) then things will probably work for you
# if there are none then try (note - this should not be necessary on Raspbian)
sudo modprobe snd-bcm2835
# and then
./squeezeslave -L

# to run it as a player ...
./squeezeslave -D -F
# to quit from that display mode hit the "q" key
# remember - if you are doing this via SSH from a different room then
# you will only hear something if you are at the device (e.g. the speakers on your TV!)

# If it acts like it is playing something but you cannot hear it then it might be that the sound on the Raspberry PI is set too low (in ALSA).
# In that case - quit (q) Squeezeslave and run
sudo alsamixer
then boost the sound by pressing the up arrow key (and the "esc" key to exit and then try running Squeezeslave again

# assuming all was OK from above - then you can do more to automate the startup


wget http://sourceforge.net/projects/softsqueeze/files/squeezeslave/squeezeslave-1.2.311/squeezeslave-1.2-311-src.tar.bz2

# If you do not have bzip2 on your system you might need
sudo apt-get install bzip2

tar -xjvf squeezeslave-1.2-311-src.tar.bz2

sudo cp squeezeslave /usr/bin

sudo cp squeezeslave-1.2-311/config/squeezeslave.init.debian /etc/init.d/squeezeslave

sudo chmod 755 /etc/init.d/squeezeslave

sudo update-rc.d squeezeslave defaults

echo "SBSHOST=\"-F\"" > defaultsqueezeslave

# the backslashes above are needed to make the quotation marks go into the file
# if you look at the file afterwards it should look like this
# SBSHOST="-F"

# if you needed to run the modprobe to get sound working then also do this
echo "modprobe snd-bcm2835" >> defaultsqueezeslave

# then copy the file over to become the default configuration for SqueezeSlave
# Done this way because trying to use sudo to echo direct to /etc/default does not work on some builds

sudo cp defaultsqueezeslave /etc/default/squeezeslave

# then to start it ...
sudo /etc/init.d/squeezeslave start
# and to stop it (for example if something else is trying to use the audio port and sharing not working)
sudo /etc/init.d/squeezeslave stop

# it should start automatically on the next reboot of your Raspberry Pi

Here is a short video showing the result ... to be honest there is not much to see because it SqueezeSlave is running in the background. However, it does show how quickly the Raspberry Pi reboots.



I also had this synchronising with a couple of real Squeezeboxes. It needed some tweaks to the timing offsets in LMS to get it to be closely in sync.

If you plan to add more SqueezeSlave devices to your set-up then you will need to change the fake MAC address that SqueezeSlave uses. It defaults to 00:00:00:00:00:01
I will probably update the default to set the SqueezeSlave MAC address to be the real MAC address of the Raspberry Pi (which in turn is usually derived from the serial number of the device).

If you did download and unpack the source - then it is also possible to build your own copy of SqueezeSlave. I did this as well and it worked - but you have to build the "contribs" as well to get the ARM version. I might update this blog entry with how to do it if there is some interest.
Remember, though, if you are on Raspbian then start from a software release that is known to work on hard-float (armhf).

September 2012 - updated with some extra information for Raspbian users