Squeezebox

From MiOS
(Difference between revisions)
Jump to: navigation, search
m (SAD - Squeezebox Server Announcement Device)
m (SAD - Squeezebox Server Announcement Device)
Line 396: Line 396:
  
 
---------------------------------------------------------------------------------------------------
 
---------------------------------------------------------------------------------------------------
 +
 +
-- V1.3 'repair' a stuck queue
 +
 +
max_LMS_queue_length = 5
 +
 +
function LMS_queues_watchdog()
 +
 +
logger( 'STATUS', 'LMS queue watchdog' )
 +
 +
if type( LMS_players ) == 'table'
 +
  then
 +
 +
  for mac, _ in pairs( LMS_players )
 +
    do
 +
 +
    local w_i_q = LMS_players[ mac ].waiting_in_queue   
 +
 +
logger( 'STATUS', 'LMS queue watchdog kicked in MAC ' .. tostring( mac ) .. ' qlength ' .. tostring( w_i_q ) .. ' mlen ' .. tostring( max_LMS_queue_length ) )
 +
 +
    if ( w_i_q or 0 ) > max_LMS_queue_length
 +
      then
 +
 +
      LMS_players[ mac ].waiting_in_queue = 0
 +
      LMS_players[ mac ].is_saying = false
 +
 +
      logger( 'STATUS', 'LMS queue watchdog kicked in ' .. tostring( mac ) .. ' ' .. tostring( w_i_q )  )
 +
 +
      luup.call_action( P_SND_SERVICE_ID, 'SendMail', { subject = 'LMS queue watchdog kicked in ' .. tostring( mac ) .. ' ' .. tostring( w_i_q ), body = os.date('%Y-%m-%d %H:%M:%S '..os.time()) }, P_SND_Webcontrol_ID )
 +
 +
      end
 +
 +
    end
 +
 +
  end
 +
 +
luup.call_delay( 'LMS_queues_watchdog', 5 * 60, '' )
 +
 +
end -- LMS_queues_watchdog
 +
 +
luup.call_delay( 'LMS_queues_watchdog', 70, '' )
 +
 +
------------------------------------------------------------------------------------------------------------
 
</source>
 
</source>
  

Revision as of 20:22, 2 April 2013


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):

---------------------------------------------------------------------------------------------------
 
-- 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
 
 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 -- 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.track ) is a function ...
   -- V1.2: countdown
 
   local count_down = 5
 
   repeat
 
    state.track        = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist tracks ?'         )
 
    count_down = count_down - 1 
 
   until ( type( state.track ) == 'string' ) or ( count_down < 1 )
 
   state.track = tonumber( string.match( state.track, '%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
 
 local playlist_set = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist index ' .. tostring( state.track - 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 
 
 local playlist_del = LMS_CLI( cmd.LMS_ip, cmd.LMS_port, player_id, 'playlist delete ' .. tostring( state.track - 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()
 
logger( 'STATUS', 'LMS queue watchdog' )
 
 if type( LMS_players ) == 'table'
  then
 
   for mac, _ in pairs( LMS_players )
    do
 
     local w_i_q = LMS_players[ mac ].waiting_in_queue    
 
logger( 'STATUS', 'LMS queue watchdog kicked in MAC ' .. tostring( mac ) .. ' qlength ' .. tostring( w_i_q ) .. ' mlen ' .. tostring( max_LMS_queue_length ) )
 
     if ( w_i_q or 0 ) > max_LMS_queue_length
      then
 
       LMS_players[ mac ].waiting_in_queue = 0
       LMS_players[ mac ].is_saying = false
 
       logger( 'STATUS', 'LMS queue watchdog kicked in ' .. tostring( mac ) .. ' ' .. tostring( w_i_q )  )
 
       luup.call_action( P_SND_SERVICE_ID, 'SendMail', { subject = 'LMS queue watchdog kicked in ' .. tostring( mac ) .. ' ' .. tostring( w_i_q ), body = os.date('%Y-%m-%d %H:%M:%S '..os.time()) }, P_SND_Webcontrol_ID )
 
      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

Personal tools