Author: titmuss
Date: Thu Jan 17 04:54:29 2008
New Revision: 1478
URL: http://svn.slimdevices.com?rev=1478&root=Jive&view=rev
Log:
Bug: N/A
Description:
Move udap class into main jive application.
Detect squeezeboxen in setup mode in Choose Players, at the moment this goes
nowhere.
Added:
trunk/jive/src/pkg/jive/share/jive/net/Udap.lua
Removed:
trunk/jive/src/pkg/jive_squeezeboxjive/share/applets/SetupSqueezebox/udap.lua
Modified:
trunk/jive/src/pkg/jive/share/applets/SelectPlayer/SelectPlayerApplet.lua
trunk/jive/src/pkg/jive/share/applets/SelectPlayer/strings.txt
Modified:
trunk/jive/src/pkg/jive/share/applets/SelectPlayer/SelectPlayerApplet.lua
URL:
http://svn.slimdevices.com/trunk/jive/src/pkg/jive/share/applets/SelectPlayer/SelectPlayerApplet.lua?rev=1478&root=Jive&r1=1477&r2=1478&view=diff
==============================================================================
--- trunk/jive/src/pkg/jive/share/applets/SelectPlayer/SelectPlayerApplet.lua
(original)
+++ trunk/jive/src/pkg/jive/share/applets/SelectPlayer/SelectPlayerApplet.lua
Thu Jan 17 04:54:29 2008
@@ -17,9 +17,11 @@
-- stuff we use
-local pairs, ipairs, tostring = pairs, ipairs, tostring
+local assert, pairs, ipairs, tostring = assert, pairs, ipairs, tostring
local oo = require("loop.simple")
+local os = require("os")
+local string = require("string")
local Applet = require("jive.Applet")
local AppletManager = require("jive.AppletManager")
@@ -32,6 +34,9 @@
local Label = require("jive.ui.Label")
local Framework = require("jive.ui.Framework")
+local SocketUdp = require("jive.net.SocketUdp")
+local udap = require("jive.net.Udap")
+
local log = require("jive.utils.log").logger("applets.setup")
local debug = require("jive.utils.debug")
@@ -39,6 +44,8 @@
local jnt = jnt
local EVENT_WINDOW_POP = jive.ui.EVENT_WINDOW_POP
+local EVENT_WINDOW_ACTIVE = jive.ui.EVENT_WINDOW_ACTIVE
+local EVENT_WINDOW_INACTIVE = jive.ui.EVENT_WINDOW_INACTIVE
-- load SetupWallpaper for use in previewing Wallpapers
local SetupWallpaper = AppletManager:loadApplet("SetupWallpaper")
@@ -49,23 +56,26 @@
function init(self, ...)
self.playerItem = {}
+ self.scanResults = {}
+
jnt:subscribe(self)
-
self:manageSelectPlayerMenu()
end
+
function notify_playerDelete(self, playerObj)
- local playerMac = playerObj.id
+ local mac = playerObj.id
manageSelectPlayerMenu(self)
- if self.playerMenu and self.playerItem[playerMac] then
- self.playerMenu:removeItem(self.playerItem[playerMac])
- self.playerItem[playerMac] = nil
- end
-end
+ if self.playerMenu and self.playerItem[mac] then
+ self.playerMenu:removeItem(self.playerItem[mac])
+ self.playerItem[mac] = nil
+ end
+end
+
function notify_playerNew(self, playerObj)
-- get number of players. if number of players is > 1, add menu item
- local playerMac = playerObj.id
+ local mac = playerObj.id
manageSelectPlayerMenu(self)
if self.playerMenu then
@@ -73,10 +83,12 @@
end
end
+
function notify_playerCurrent(self, playerObj)
self.selectedPlayer = playerObj
self:manageSelectPlayerMenu()
end
+
function manageSelectPlayerMenu(self)
local sdApplet = AppletManager:getAppletInstance("SlimDiscovery")
@@ -106,12 +118,18 @@
end
end
+
+function _unifyMac(mac)
+ return string.upper(string.gsub(mac, "[^%x]", ""))
+end
+
+
function _addPlayerItem(self, player)
- local playerMac = player.id
+ local mac = player.id
local playerName = player.name
- log:warn("_addPlayerItem")
local item = {
+ id = _unifyMac(mac),
text = playerName,
sound = "WINDOWSHOW",
callback = function()
@@ -119,22 +137,44 @@
self.setupNext()
end,
focusGained = function(event)
- self:_showWallpaper(playerMac)
+ self:_showWallpaper(mac)
end,
weight = 1
}
self.playerMenu:addItem(item)
- self.playerItem[playerMac] = item
+ self.playerItem[mac] = item
if self.selectedPlayer == player then
self.playerMenu:setSelectedItem(item)
end
end
+
+-- add a squeezebox discovered using udap or an adhoc network
+function _addSqueezeboxItem(self, mac, name, adhoc)
+ local item = {
+ id = _unifyMac(mac),
+ text = name or self:string("SQUEEZEBOX_NAME", string.sub(mac,
7)),
+ sound = "WINDOWSHOW",
+ callback = function()
+ log:error("SETUP SQUEEZEBOX")
+ --self.setupNext()
+ end,
+ focusGained = function(event)
+ self:_showWallpaper(nil)
+ end,
+ weight = 1
+ }
+ self.playerMenu:addItem(item)
+ self.playerItem[mac] = item
+end
+
+
function _showWallpaper(self, playerId)
log:info("previewing background wallpaper for ", playerId)
SetupWallpaper:_setBackground(nil, playerId)
end
+
function setupShow(self, setupNext)
-- get list of slimservers
@@ -150,13 +190,13 @@
window:hide(Window.transitionPushLeft)
end
- local sdApplet = AppletManager:getAppletInstance("SlimDiscovery")
- if not sdApplet then
+ self.discovery = AppletManager:getAppletInstance("SlimDiscovery")
+ if not self.discovery then
return
end
- self.selectedPlayer = sdApplet:getCurrentPlayer()
- for playerMac, playerObj in sdApplet:allPlayers() do
+ self.selectedPlayer = self.discovery:getCurrentPlayer()
+ for mac, playerObj in self.discovery:allPlayers() do
_addPlayerItem(self, playerObj)
end
@@ -173,30 +213,92 @@
})
end
- --[[
- -- no player for debugging
- self.playerMenu:addItem({
- text = "NO PLAYER (DEBUG)",
- sound = "WINDOWSHOW",
- callback = function()
-
self:selectPlayer(nil)
- self.setupNext()
- end,
- weight = 9
- })
- --]]
-
window:addWidget(menu)
- sdApplet:discover()
- window:addTimer(1000, function() sdApplet:discover() end)
+ window:addTimer(1000, function() self:_scan() end)
+
+
+ window:addListener(EVENT_WINDOW_ACTIVE,
+ function()
+ self:_scanActive()
+ self:_scan()
+ end)
+
+ window:addListener(EVENT_WINDOW_INACTIVE,
+ function()
+ self:_scanInactive()
+ end)
self:tieAndShowWindow(window)
return window
end
+
+function _scanActive(self)
+ -- socket for udap discovery
+ if not self.socket then
+ self.socket = assert(SocketUdp(jnt, function(chunk, err)
+
self:_udapSink(chunk, err)
+ end))
+ end
+end
+
+
+function _scanInactive(self)
+ self.socket:close()
+ self.socket = nil
+end
+
+
+function _udapSink(self, chunk, err)
+ if chunk == nil then
+ return -- ignore errors
+ end
+
+ local pkt = udap.parseUdap(chunk.data)
+
+ if pkt.uapMethod ~= "adv_discover"
+ or pkt.ucp.device_status ~= "wait_slimserver"
+ or pkt.ucp.type ~= "squeezebox" then
+ -- we are only looking for squeezeboxen trying to connect to SC
+ return
+ end
+
+ local mac = pkt.source
+ local name = pkt.ucp.name
+ if not self.scanResults[mac] then
+ self.scanResults[mac] = {
+ lastScan = os.time(),
+ udap = true,
+ }
+
+ self:_addSqueezeboxItem(mac, name, nil)
+ end
+end
+
+
+function _scan(self)
+ -- SqueezeCenter and player discovery
+ self.discovery:discover()
+
+ -- udap discovery
+ local packet = udap.createAdvancedDiscover(nil, 1)
+ self.socket:send(function() return packet end, "255.255.255.255",
udap.port)
+
+ -- remove squeezeboxen not seen for 10 seconds
+ local now = os.time()
+ for mac, entry in pairs(self.scanResults) do
+ if os.difftime(now, entry.lastScan) > 10 then
+ self.playerMenu:removeItem(self.playerItem[mac])
+ self.playerItem[mac] = nil
+ self.scanResults[mac] = nil
+ end
+ end
+end
+
+
function selectPlayer(self, player)
- log:warn("Selected player is now ", player)
+ log:info("Selected player=", player)
local manager = AppletManager:getAppletInstance("SlimDiscovery")
if manager then
@@ -205,6 +307,7 @@
return true
end
+
function free(self)
Modified: trunk/jive/src/pkg/jive/share/applets/SelectPlayer/strings.txt
URL:
http://svn.slimdevices.com/trunk/jive/src/pkg/jive/share/applets/SelectPlayer/strings.txt?rev=1478&root=Jive&r1=1477&r2=1478&view=diff
==============================================================================
--- trunk/jive/src/pkg/jive/share/applets/SelectPlayer/strings.txt (original)
+++ trunk/jive/src/pkg/jive/share/applets/SelectPlayer/strings.txt Thu Jan 17
04:54:29 2008
@@ -16,4 +16,11 @@
IT Configura Squeezebox
NL Squeezebox instellen
+SQUEEZEBOX_NAME
+ DE Squeezebox %s
+ EN Squeezebox %s
+ ES Squeezebox %s
+ FR Squeezebox %s
+ IT Squeezebox %s
+ NL Squeezebox %s
Added: trunk/jive/src/pkg/jive/share/jive/net/Udap.lua
URL:
http://svn.slimdevices.com/trunk/jive/src/pkg/jive/share/jive/net/Udap.lua?rev=1478&root=Jive&view=auto
==============================================================================
--- trunk/jive/src/pkg/jive/share/jive/net/Udap.lua (added)
+++ trunk/jive/src/pkg/jive/share/jive/net/Udap.lua Thu Jan 17 04:54:29 2008
@@ -1,0 +1,374 @@
+
+local pairs, ipairs, print, tonumber, unpack = pairs, ipairs, print, tonumber,
unpack
+
+local oo = require("loop.base")
+
+local socket = require("socket")
+local string = require("string")
+local table = require("table")
+
+
+module(..., oo.class)
+
+
+port = 0x4578
+
+
+-- Squeezebox nvram settings
+local configSettings = {
+ [ "lan_ip_mode" ] = { 4, 1 },
+ [ "lan_network_address" ] = { 5, 4 },
+ [ "lan_subnet_mask" ] = { 9, 4 },
+ [ "lan_gateway" ] = { 13, 4 },
+ [ "hostname" ] = { 17, 33 },
+ [ "bridging" ] = { 50, 1 },
+ [ "interface" ] = { 52, 1 },
+ [ "primary_dns" ] = { 59, 4 },
+ [ "secondary_dns" ] = { 67, 4 },
+ [ "server_address" ] = { 71, 4 },
+ [ "slimserver_address" ] = { 79, 4 },
+ [ "wireless_mode" ] = { 173, 1 },
+ [ "SSID" ] = { 183, 33 },
+ [ "channel" ] = { 216, 1 },
+ [ "region_id" ] = { 218, 1 },
+ [ "keylen" ] = { 220, 1 },
+ [ "wep_key" ] = { 222, 13 },
+ [ "wepon" ] = { 274, 1 },
+ [ "wpa_cipher" ] = { 275, 1 },
+ [ "wpa_enabled" ] = { 277, 1 },
+ [ "wpa_mode" ] = { 276, 1 },
+ [ "wpa_psk" ] = { 278, 64 }
+}
+
+
+-- ucp methods
+local ucpMethods = {
+ "discover",
+ "get_ip",
+ "set_ip",
+ "reset",
+ "get_data",
+ "set_data",
+ "error",
+ "credentials_error",
+ "adv_discover",
+ nil,
+ "get_uuid"
+}
+
+
+-- ucp discovery codes
+local ucpCodes = {
+ nil,
+ "name",
+ "type",
+ "use_dhcp",
+ "ip_addr",
+ "subnet_mask",
+ "gateway_addr",
+ nil,
+ "firmware_rev",
+ "hardware_rev",
+ "device_id",
+ "device_status",
+ "uuid"
+}
+
+
+function packNumber(v, len)
+ local t = {}
+
+ for i = 1,len do
+ t[#t + 1] = string.char(v & 0xFF)
+ v = v >> 8
+ end
+
+ return string.reverse(table.concat(t))
+end
+
+
+function unpackString(str, pos, len)
+ local v = ""
+ for i = pos, pos+len-1 do
+ v = string.format("%s%02x", v, string.byte(string.sub(str, i,
i+1)))
+ end
+
+ return v, pos + len
+end
+
+
+function unpackNumber(str, pos, len)
+ local v, offset = unpackString(str, pos, len)
+ return tonumber(v, 16), offset
+end
+
+
+function parseDiscover(pkt, recv, offset)
+ pkt.ucp = {}
+ while offset < #recv do
+ local ucp_code, ucp_len, ucp_pkt
+
+ ucp_code, offset = unpackNumber(recv, offset, 1)
+ ucp_len, offset = unpackNumber(recv, offset, 1)
+ ucp_data = string.sub(recv, offset, offset + ucp_len - 1)
+ offset = offset + ucp_len
+
+ pkt.ucp[ucpCodes[ucp_code]] = ucp_data
+ end
+end
+
+
+function parseGetData(pkt, recv, offset)
+ local num, off, len, data
+
+ pkt.data = {}
+
+ num, offset = unpackNumber(recv, offset, 2)
+ for i = 1,num do
+ off, offset = unpackNumber(recv, offset, 2)
+ len, offset = unpackNumber(recv, offset, 2)
+ data = string.sub(recv, offset, offset + len - 1)
+ offset = offset + len
+
+ for k,v in pairs(configSettings) do
+ if v[1] == off and v[2] == len then
+ pkt.data[k] = data
+ break
+ end
+ end
+ end
+end
+
+
+function parseGetUUID(pkt, recv, offset)
+ local num, off, len, data
+
+ pkt.data = {}
+
+ len, offset = unpackNumber(recv, offset, 2)
+ local n = { string.byte(string.sub(recv, offset, offset + len - 1), 1,
len) }
+
+ pkt.uuid = {}
+ for k,v in ipairs(n) do
+ pkt.uuid[#pkt.uuid + 1] = string.format("%02x", v)
+ end
+ pkt.uuid = table.concat(pkt.uuid)
+end
+
+
+local ucpMethodHandlers = {
+ [ "discover" ] = parseDiscover,
+ [ "get_ip" ] = parseDiscover,
+ [ "set_ip" ] = nil,
+ [ "reset" ] = nil,
+ [ "get_data" ] = parseGetData,
+ [ "set_data" ] = nil,
+ [ "error" ] = nil,
+ [ "credentials_error" ] = nil,
+ [ "adv_discover" ] = parseDiscover,
+ [ "get_uuid" ] = parseGetUUID,
+}
+
+
+function parseUdap(recv)
+ local offset = 1
+ local pkt = {}
+
+ pkt.destType, offset = unpackNumber(recv, offset, 2)
+ if pkt.destType == 1 then
+ -- mac address
+ pkt.dest, offset = unpackString(recv, offset, 6)
+ elseif pkt.destType == 2 then
+ -- ip address
+ pkt.dest, offset = unpackString(recv, offset, 6)
+ else
+ error("uknown address type " .. pkt.destType)
+ end
+
+ pkt.sourceType, offset = unpackNumber(recv, offset, 2)
+ if pkt.sourceType == 1 then
+ -- mac address
+ pkt.source, offset = unpackString(recv, offset, 6)
+ elseif pkt.sourceType == 2 then
+ -- ip address
+ pkt.source, offset = unpackString(recv, offset, 6)
+ else
+ error("uknown address type " .. pkt.sourceType)
+ end
+
+ pkt.seqno, offset = unpackNumber(recv, offset, 2)
+ pkt.udapType, offset = unpackNumber(recv, offset, 2)
+ pkt.udapFlag, offset = unpackNumber(recv, offset, 1)
+ pkt.uapClass, offset = unpackString(recv, offset, 4)
+ pkt.uapMethodId, offset = unpackNumber(recv, offset, 2)
+
+ pkt.uapMethod = ucpMethods[pkt.uapMethodId]
+
+ if ucpMethodHandlers[pkt.uapMethod] then
+ ucpMethodHandlers[pkt.uapMethod](pkt, recv, offset)
+ end
+
+ return pkt
+end
+
+
+function createUdap(mac, seq, ...)
+ local macstr = {}
+ local bcast = 0
+
+ if mac == nil then
+ bcast = 1
+ mac = "000000000000"
+ end
+
+ for i=1,12,2 do
+ macstr[#macstr + 1] = string.char(tonumber(string.sub(mac, i,
i+1), 16))
+ end
+
+ return table.concat {
+ packNumber(bcast, 1), -- broadcast
+ packNumber(0x01, 1), -- ethernet
+ table.concat(macstr), -- destination mac
+ packNumber(0x0002, 2), -- source type udp
+ packNumber(0x00000000, 4), -- source ip
+ packNumber(0x0000, 2), -- source port
+ packNumber(seq, 2), -- seqno number
+ packNumber(0xC001, 2), -- udap_type_ucp
+ packNumber(0x01, 1), -- flags
+ packNumber(0x00001, 2), -- uap_class_ucp
+ packNumber(0x00001, 2),
+ table.concat({...})
+ }
+end
+
+
+function createDiscover(mac, seq)
+ return createUdap(mac,
+ seq,
+ packNumber(0x0001, 2) -- discover
+ )
+end
+
+
+function createAdvancedDiscover(mac, seq)
+ return createUdap(mac,
+ seq,
+ packNumber(0x0009, 2) -- discover
+ )
+end
+
+
+function createReset(mac, seq)
+ return createUdap(mac,
+ seq,
+ packNumber(0x0004, 2) -- reset
+ )
+end
+
+
+function createGetIPAddr(mac, seq)
+ return createUdap(mac,
+ seq,
+ packNumber(0x0002, 2) -- get ip
+ )
+end
+
+
+function createGetUUID(mac, seq)
+ return createUdap(mac,
+ seq,
+ packNumber(0x000b, 2) -- get uuid
+ )
+end
+
+
+function createGetData(mac, seq, args)
+ local req = {
+ packNumber(0x0005, 2), -- get data
+ string.rep("\0", 16), -- username
+ string.rep("\0", 16), -- password
+ packNumber(#args, 2), -- num of items
+ }
+
+ for i,k in ipairs(args) do
+ local p = configSettings[k]
+ if p ~= nil then
+ req[ #req + 1 ] = packNumber(p[1], 2) -- offset
+ req[ #req + 1 ] = packNumber(p[2], 2) -- length
+ end
+ end
+
+ return createUdap(mac,
+ seq,
+ unpack(req))
+end
+
+
+function createSetData(mac, seq, args)
+ local num = 0
+ for k,v in pairs(args) do
+ num = num + 1
+ end
+
+ local req = {
+ packNumber(0x0006, 2), -- set data
+ string.rep("\0", 16), -- username
+ string.rep("\0", 16), -- password
+ packNumber(num, 2), -- num of items
+ }
+
+ for k,v in pairs(args) do
+ local p = configSettings[k]
+ if p ~= nil then
+ req[ #req + 1 ] = packNumber(p[1], 2) -- offset
+ req[ #req + 1 ] = packNumber(p[2], 2) -- length
+ req[ #req + 1 ] = v .. string.rep("\0", p[2] - #v)
+ end
+ end
+
+ return createUdap(mac,
+ seq,
+ unpack(req))
+end
+
+
+function tostringUdap(pkt)
+ local t = {
+ "source:\t\t" .. pkt.source,
+ "dest:\t\t" .. pkt.dest,
+ "seq:\t\t" .. pkt.seqno,
+ "udap type:\t" .. string.format("%04x", pkt.udapType),
+ "udap flag:\t" .. string.format("%02x", pkt.udapFlag),
+ "uap class:\t" .. pkt.uapClass,
+ "uap method:\t" .. pkt.uapMethod,
+ }
+ if pkt.ucp then
+ for k,v in pairs(pkt.ucp) do
+ t[#t + 1] = k .. ":\t" .. v
+ end
+ end
+ if pkt.data then
+ for k,v in pairs(pkt.data) do
+ local hex = ""
+ for i = 1,#v do
+ hex = hex .. string.format("%02x",
string.byte(string.sub(v, i, i)))
+ end
+
+ t[#t + 1] = k .. " (#" .. #v .. "):\t" .. hex
+ end
+ end
+
+ return table.concat(t, "\n")
+end
+
+
+--[[
+
+=head1 LICENSE
+
+Copyright 2007 Logitech. All Rights Reserved.
+
+This file is subject to the Logitech Public Source License Version 1.0. Please
see the LICENCE file for details.
+
+=cut
+--]]
_______________________________________________
Jive-checkins mailing list
[email protected]
http://lists.slimdevices.com/cgi-bin/mailman/listinfo/jive-checkins