/ Tech

Squeezebox Dashing widget

Displaying Squeezebox "Now Playing" information on a Dashing dashboard is now very easy with my widget, which can be found on gist.github.com.

Just type dashing install 9714028 in your dashing root directory, the widget will be installed automatically. Include the following snipped in your dashboard to display the widget:

<li data-row="1" data-col="1" data-sizex="2" data-sizey="2">
   <div data-id="now-playing" data-view="Squeezebox" data-title="Squeezebox"></div>
</li>

Don't forget to update squeezebox.rb with the URL to your server and the player ID.

Some background information and how the widget was born:

First version: Telnet interface

The Squeezebox server (aka Logitech Media Server) has a so called CLI interface which listens on port 9090. It's reachable using telnet and sending a command. The server then replies with the sent command and it's result. The output is just text, not really structured. My first (let's call it prototype) version of the widget was using this interface. But because using it was not easy, error-prone and not every information I wanted was returned (f.e. the album art), I searched for another way to access the server API and found one, the JSON interface. But before describing the JSON interface, here's how I got the information with the telnet CLI:

require 'net/telnet'
require 'open-uri'

connection = Net::Telnet.new('Host' => 'localhost',
                             'Port' => '9090',
                             'Telnetmode' => false,
                             'Prompt' => /\n/)

data_hash = {}
status = connection.cmd("status tags:Ju").split(' ')
status.each do |data|
  decoded_data = URI::decode(data)
  next if decoded_data.count(':') != 1
  key = decoded_data.split(':')[0]
  value = decoded_data.split(':')[1]
  data_hash[key] = value
end

The data fields are separated by a blank and the data itself by a colon. F.e.: field1:data field2:data. Therefore the fields are separated using split. As the data returns URI encoded, it needs the be decoded first.
The first field returned is the MAC address of the player, this field needs to be detected because it has more than one colon, which gives as trouble while separating the field description from the data. After applying this operation, the returned data is saved in data_hash.

For more information about the CLI, have a look at the wiki under Logitech Media Server CLI

Second version: JSON interface

A much nicer way to access the Squeezebox server API is the JSON API, reachable under http://yoursbserver:9000/jsonrpc.js.

It uses the same commands as the telnet CLI, so it's easy to convert from the telnet CLI API to the JSON API.

Here is some sample ruby code:

require 'json'
require 'net/http'
require 'uri'

LMS_URL = 'http://my-sbserver:9000'
SB_PLAYER_ID = 'my-player-mac-or-ip'

def slim_request(params)

  form_data = { 'id'     => 1,
                'method' => 'slim.request',
                'params' => params,
  }

  uri = URI.parse(LMS_URL + '/jsonrpc.js')
  http = Net::HTTP.new(uri.host, uri.port)

  request = Net::HTTP::Post.new(uri.request_uri)
  request.body = form_data.to_json
  response = JSON.parse(http.request(request).body)

  return response['result']

end

player_status = [ SB_PLAYER_ID, [ 'status', '-', 1, 'tags:cgABbehldiqtyrSuoKLNJ' ] ]
data = slim_request(player_status)

This example sends the status command to the API and stores the returned data in data. One way to find out which commands and parameters need to be sent to the API is using Firebug and see what commands the webinterface sends to the API (Yes, the webinterface is also using this API). Everything what can be done using the webinterface is also possible with the JSON API.

Happy Squeezebox API consuming!