Squeezebox

From MiOS
Revision as of 19:56, 4 May 2013 by Ap15e (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


Using the SqueezeBox Plugin

Contents

Displaying cover art for the current song

1. Create new camera device(s) for the room(s) equipped with Squeezebox(es)

2. Configure the new camera device(s):

  • IP address: IP address and port of your Squeezebox Server (<ip address>:<port number>)
  • Path: music/current/cover.jpg?player=<MAC address> (replace <MAC address> with the MAC address of the player; IP address should work too)

Example

Using the SBS CLI

Luup/Lua skeleton

socket=require('socket')
local client = socket.connect('<IP address of SBS>', 9090)
client:send("<CLI command>\n")
local result=client:receive()
...

For a list of valid <CLI command> navigate to: SBS's Home / Technical Information / Help / Command Line Interface

Some examples for <CLI command>

<duration> does not work for Squeezebox Radio due to Slimdevices bug #15749.

Displaying text

Syntax:

<MAC address of player> display <line1> <line2> <duration>

Example:

client:send("00:04:20:XX:XX:XX display Hello%20World%201 Hello%20World%202 10\n")

'Pressing' a button on the Squeezebox remote

Syntax:

<MAC address of player> button <buttoncode>

Example:

client:send("00:04:20:XX:XX:XX button brightness_toggle\n")
client:send("00:04:20:XX:XX:XX button volume_up\n")
client:send("00:04:20:XX:XX:XX button volume_down\n")

<buttoncode> as defined in Default.map; telnet to your SBS port 9090, type 'subscribe button' (without quotes), press <RETURN>, press the buttons of the remote to get the buttoncodes.

Skipping to the previous/next track

Syntax:

<MAC address of player> playlist index <index|+index|-index|?> <fadeInSecs>

Example:

client:send("00:04:20:XX:XX:XX playlist index -1\n")
client:send("00:04:20:XX:XX:XX playlist index +1\n")

Pause/Unpause playing

Syntax:

<MAC address of player> pause <0|1|>  <fadeInSecs>  <suppressShowBriefly>  

Example:

client:send("00:04:20:XX:XX:XX pause\n")

Changing the volume level

Syntax:

<MAC address of player> mixer volume <0 .. 100|-100 .. +100|?>

Example:

client:send("00:04:20:XX:XX:XX mixer volume +10\n")
client:send("00:04:20:XX:XX:XX mixer volume -10\n")

Switching players (undocumented and untested)

Syntax:

switchplayer from:<MAC address of player1> to:<MAC address of player2>

Example:

client:send("switchplayer from:00:00:00:00:00:01 to:00:00:00:00:00:02\n")

[Reference: http://www.mail-archive.com/plugins@lists.slimdevices.com/msg46077.html]

Playing a file

Syntax:

<MAC address of player> playlist play file:///<filename>

Example:

Windows:
77:d3:XX:XX:XX:XX playlist play file:///I:/NewMusic/Schwanensee%20(aus%20Kinderbuch)/Content/01%20-%20Track%201.flac
Synology NAS:
77:d3:XX:XX:XX:XX playlist play file:///disk1/music/file.mp3

Sending IR codes (SB2/3 and Transporter)

Theory of operation

1. Plug an IR emitter into the phones jack of your Squeezebox/Transporter.

2. Install IRBlaster.

3. Restart your SBS.

4. Install the IR remote files for the IR devices you are going to control or use the IR-Learning Wizard (part of IRBlaster) to record the codes of your remote(s).

Now you are ready to send IR codes via Lua (adjust SBS_IP_address, SBS_CLI_port, playerid, remote_name, and command_name accordingly):

socket=require('socket')
 
local SBS_IP_address = '192.168.178.22'
local SBS_CLI_port   = 9090
local playerid 	     = '00:04:20:XX:XX:XX'
local remote_name    = 'Onkyo_RC-738M' -- as defined in the LIRC configuration file for this remote
local command_name   = 'PWR'           -- as defined in the LIRC configuration file for this remote
 
local client = socket.connect( SBS_IP_address, SBS_CLI_port ) 
 
function sendIR( device_MAC, remote, command )
 
 client:send( device_MAC .. ' irblaster send ' .. remote .. ' ' .. command .. '\n' )
 client:receive()
 
end
 
sendIR( playerid, remote_name, command_name )

Successfully tested with: SBS 7.3.2, IRBlaster/IR-Learning wizard 5.4, Skymaster DVR 7400.

Squeezebox Control beta plugin (by MCV/radarengineer)

http://forum.micasaverde.com/index.php/topic,10108.0.html

http://forum.micasaverde.com/index.php?topic=5097.msg28878#msg28878

LOUIS4Vera

http://forum.micasaverde.com/index.php?topic=5232.0

LIRC2LuupDevice4SBS

http://forum.micasaverde.com/index.php?topic=5709.0

SAD - Squeezebox Server Announcement Device

Old implementation: http://forum.micasaverde.com/index.php?topic=6952.0

New implementation (LIFO queue per player, luup.sleep replaced with luup.call_delay; copy into the 'Startup Lua' window; should be rewritten with coroutines ...):

---------------------------------------------------------------------------------------------------
 
-- V1.2
 
LMS_players = {}
 
---------------------------------------------------------------------------------------------------
 
function LMS_CLI( server_ip, server_port, player_id, cmd )
 
 local socket = require( 'socket' )
 
 local client = socket.connect( server_ip, server_port )
 
 client:send( player_id .. ' ' .. cmd .. '\n' )
 
 local res = client:receive()
 
 client:close()
 
 return res
 
end -- LMS_CLI
 
---------------------------------------------------------------------------------------------------
 
function LMS_Say( LMS_ip          ,   -- IP address of LMS 
                  LMS_port        ,   -- CLI Port of LMS (default: 9090)
                  player_id       ,   -- MAC address of player
                  message1        ,   -- line 1
                  message2        ,   -- line 2
                  message_duration,   -- in seconds
                  file            ,   -- audio announcement
                  file_duration   ,   -- duration of announcement in seconds
                  repeats           ) -- number of announcements
 
-- V1.4 catch empty announcement (would result in a stuck queue ...)
 
if ( file ~= '' ) and ( file ~= nil ) 
  then
 
 if LMS_players[ player_id ] == nil
  then 
   LMS_players[ player_id ] = {}
  end
 
 if LMS_players[ player_id ].is_saying -- nil is false
  then
 
   local queue_index = LMS_players[ player_id ].waiting_in_queue or 0
 
   queue_index = queue_index + 1
 
   LMS_players[ player_id ].waiting_in_queue = queue_index
 
   if LMS_players[ player_id ].queue == nil 
    then
     LMS_players[ player_id ].queue = {}
    end
 
   if LMS_players[ player_id ].queue[ queue_index ] == nil
    then
     LMS_players[ player_id ].queue[ queue_index ] = {}
    end
 
   LMS_players[ player_id ].queue[ queue_index ].LMS_ip           = LMS_ip
   LMS_players[ player_id ].queue[ queue_index ].LMS_port         = LMS_port
   LMS_players[ player_id ].queue[ queue_index ].message1         = message1
   LMS_players[ player_id ].queue[ queue_index ].message2         = message2
   LMS_players[ player_id ].queue[ queue_index ].message_duration = message_duration
   LMS_players[ player_id ].queue[ queue_index ].file             = file
   LMS_players[ player_id ].queue[ queue_index ].file_duration    = file_duration
   LMS_players[ player_id ].queue[ queue_index ].repeats          = repeats
 
  else
 
   LMS_players[ player_id ].is_saying = true
 
   if LMS_players[ player_id ].current_cmd == nil 
    then
     LMS_players[ player_id ].current_cmd = {}
    end
 
   LMS_players[ player_id ].current_cmd.LMS_ip        = LMS_ip
   LMS_players[ player_id ].current_cmd.LMS_port      = LMS_port
   LMS_players[ player_id ].current_cmd.file          = file
   LMS_players[ player_id ].current_cmd.file_duration = file_duration
   LMS_players[ player_id ].current_cmd.repeats       = repeats
 
   if LMS_players[ player_id ].current_state == nil 
    then
     LMS_players[ player_id ].current_state = {}
    end
 
   LMS_players[ player_id ].current_state.power  = LMS_CLI( LMS_ip, LMS_port, player_id, 'power ?'          )
   LMS_players[ player_id ].current_state.track  = LMS_CLI( LMS_ip, LMS_port, player_id, 'playlist index ?' )
   LMS_players[ player_id ].current_state.offset = LMS_CLI( LMS_ip, LMS_port, player_id, 'time ?'           )
   LMS_players[ player_id ].current_state.mode   = LMS_CLI( LMS_ip, LMS_port, player_id, 'mode ?'           )
 
   if ( message1 ~= '' ) and ( message1 ~= nil ) and ( message_duration > 0 )
    then
 
     LMS_CLI( LMS_ip, LMS_port, player_id, 'display ' .. tostring(message1) .. ' ' .. tostring(message2) .. ' ' .. tostring( message_duration ) )
 
     luup.call_delay( 'LMS_Say_play_file', message_duration, player_id )
 
    else
 
     LMS_Say_play_file( player_id )
 
    end
 
  end
 
 end
 
end -- LMS_Say
 
---------------------------------------------------------------------------------------------------
 
function LMS_Say_play_file( player_id )
 
 local cmd   = LMS_players[ player_id ].current_cmd
 local state = LMS_players[ player_id ].current_state
 
 if  ( cmd.file ~= '' ) 
    and 
     ( cmd.file ~= nil ) 
    and 
     ( cmd.repeats > 0 )
  then
 
   -- Add announcement file to playlist
 
   local playlist_add = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist add ' .. cmd.file )
 
   -- V1.1: Sometimes type( state.tracks_total ) is a function ...
   -- V1.2: countdown
 
   local count_down = 5
 
   repeat
 
    -- V1.5: bugfix
    state.tracks_total = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist tracks ?'         )
 
    count_down = count_down - 1 
 
    -- V1.5: bugfix
   until ( type( state.tracks_total ) == 'string' ) or ( count_down < 1 )
 
    -- V1.5: bugfix
   state.tracks_total = tonumber( string.match( state.tracks_total, '%s(%d+)' ) )
 
   LMS_Say_play_file_execute( player_id )
 
  else
 
   LMS_check_queue( player_id )
 
  end
 
end -- LMS_Say_play_file
 
---------------------------------------------------------------------------------------------------
 
function LMS_Say_play_file_execute( player_id )
 
 local cmd   = LMS_players[ player_id ].current_cmd
 local state = LMS_players[ player_id ].current_state
 
    -- V1.5: bugfix
 local playlist_set = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist index ' .. tostring( state.tracks_total - 1 ) )
 
 cmd.repeats = cmd.repeats - 1
 
 if cmd.repeats >= 0 
  then
 
   luup.call_delay( 'LMS_Say_play_file_execute', cmd.file_duration, player_id )
 
  else
 
   LMS_check_queue( player_id )
 
  end
 
end -- LMS_Say_play_file_execute
 
---------------------------------------------------------------------------------------------------
 
function LMS_check_queue( player_id )
 
 local cmd   = LMS_players[ player_id ].current_cmd
 local state = LMS_players[ player_id ].current_state
 
  -- Restore previous state of player 
 
    -- V1.5: bugfix
 local playlist_del = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist delete ' .. tostring( state.tracks_total - 1 ) )
 local playlist_set = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, ''       , state.track  )
 local time_set     = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, ''       , state.offset )
 local mode_set     = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, ''       , state.mode   )
 local power_set    = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, ''       , state.power  )
 
 local waiting = LMS_players[ player_id ].waiting_in_queue or 0
 
 -- Check queue
 
 if waiting > 0
  then
 
   local q = LMS_players[ player_id ].queue[ waiting ]
 
   LMS_players[ player_id ].waiting_in_queue = waiting - 1
 
   LMS_players[ player_id ].is_saying = false
 
   LMS_Say( q.LMS_ip          ,
            q.LMS_port        ,
            player_id         ,
            q.message1        ,
            q.message2        , 
            q.message_duration, 
            q.file            ,
            q.file_duration   , 
            q.repeats           )
 
  else
 
   LMS_players[ player_id ].is_saying = false
 
  end
 
end -- LMS_check_queue
 
---------------------------------------------------------------------------------------------------
 
-- V1.3 'repair' a stuck queue
 
max_LMS_queue_length = 5
 
function LMS_queues_watchdog()
 
 if type( LMS_players ) == 'table'
  then
 
   for mac, _ in pairs( LMS_players )
    do
 
     local w_i_q = LMS_players[ mac ].waiting_in_queue    
 
     if ( w_i_q or 0 ) > max_LMS_queue_length
      then
 
       LMS_players[ mac ].waiting_in_queue = 0
       LMS_players[ mac ].is_saying = false
 
      end 
 
    end
 
  end
 
 luup.call_delay( 'LMS_queues_watchdog', 5 * 60, '' )
 
end -- LMS_queues_watchdog
 
luup.call_delay( 'LMS_queues_watchdog', 70, '' )
 
------------------------------------------------------------------------------------------------------------

SPB - Squeezebox Preset Button device

SPB maps preset buttons to Luup events.

http://forum.micasaverde.com/index.php/topic,9059.0.html

USP - Unified Squeezebox Plugin (Technology demo only)

http://forum.micasaverde.com/index.php/topic,10020.0.html

squeezedVera and squeezedVeraScenes

squeezedVera is a plugin for the Logitech Squeezebox, and it gives you the possibility to run scripts in different ways that can control your z-wave devices through Vera.

squeezedVeraScenes will run the same scripts as squeezedVera but here you define conditions for when they shall run in a configuration file, e.g at sunset on Mondays and Tuesdays. You can also define different scenes with different behaviour.

http://forum.micasaverde.com/index.php/topic,1047.0.html

Morphing the Sonos plugin into a Squeezebox plugin

http://forum.micasaverde.com/index.php/topic,9532.0.html

Importing LMS devices into MiOS

Use Whitebear Media Server or the native UPnP support in LMS 7.7.2+ to import your LMS devices into MiOS:

http://forum.micasaverde.com/index.php/topic,10220.0.html

Using Google's TTS engine for announcements

Requirement: http://wiki.micasaverde.com/index.php/Squeezebox#SAD_-_Squeezebox_Server_Announcement_Device

local lul_temp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1","CurrentTemperature", 111)
if ( tonumber( lul_temp ) > 25 ) or ( luup.sunrise() - os.time() > 86400 - 300 ) 
 then 
  os.execute( 'cd /tmp; wget -U Mozilla -O GHBewAnn.mp3 "http://translate.google.com/translate_tts?tl=de&q=Gewaechshaus+wird+bewaessert.+Innentemperatur:+'..tostring( lul_temp )..'+Grad+Celsius."; ftpput -u **** -p **** 192.168.x.y public/HA_Announcements/GHBewAnn.mp3 GHBewAnn.mp3' )
  SBS_announcement( '192.168.a.b'                                  , 
                    9090                                           , 
                    '00:04:20:xx:xx:xx'                            , 
                    'Gewaechshaus%20wird%20bewaessert'             , 
                    tostring(lul_temp)..'%20Grad%20Celsius'        , 
                    5                                              , 
                    '/volume1/public/HA_Announcements/GHBewAnn.mp3',
                    10                                               )
 luup.call_action( "urn:upnp-ap15e-com:serviceId:SND1", "SendMail", { subject = 'Gewaechshaus wird bewaessert ('..tostring(lul_temp)..')', body = os.date('%Y-%m-%d %H:%M:%S '..os.time()) }, 25 )
end

or even simpler:

<MAC address> playlist play http://translate.google.com/translate_tts?tl=en&q=Just+a+test

Controlling the BASETech RGB LED light bulb

http://wiki.micasaverde.com/index.php/BASETech_RGB_LED

Squeezebox clone

http://wiki.micasaverde.com/index.php/Raspberry_Pi_-_Interfacing_with_Vera#Squeezebox

Personal tools