Author: bklaas
Date: Wed Dec 10 09:55:57 2008
New Revision: 3484

URL: http://svn.slimdevices.com?rev=3484&root=Jive&view=rev
Log:
Bug: 7186
Description: full browse history memory for SlimBrowse menus

Modified:
    7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/DB.lua
    
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/SlimBrowserApplet.lua
    7.4/trunk/squeezeplay/src/squeezeplay/share/jive/slim/Player.lua

Modified: 7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/DB.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/DB.lua?rev=3484&root=Jive&r1=3483&r2=3484&view=diff
==============================================================================
--- 7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/DB.lua 
(original)
+++ 7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/DB.lua Wed 
Dec 10 09:55:57 2008
@@ -46,7 +46,6 @@
 
 
 local BLOCK_SIZE = 200
-
 
 -- init
 -- creates an empty database object
@@ -83,6 +82,9 @@
        return self.windowSpec.labelItemStyle
 end
 
+function getBlockSize(self)
+       return BLOCK_SIZE
+end
 
 -- getRadioGroup
 -- either returns self.radioGroup or creates and returns it
@@ -176,7 +178,13 @@
        end
 
        -- store chunk
-       local key = math.modf(cFrom / BLOCK_SIZE)
+       local key = math.floor(cFrom/BLOCK_SIZE)
+
+       -- helpful debug flags to show what chunk key and range is being loaded
+       log:debug('********************************* loading key number ', key)
+       log:debug('********************************* cFrom: ', cFrom)
+       log:debug('********************************* cTo:   ', cTo)
+
        self.store[key] = chunk["item_loop"]
 
        return self, self.count, cFrom, cTo
@@ -218,8 +226,8 @@
 end
 
 
-function missing(self, accel, dir, index)
-       log:debug(self, " missing accel=", accel, " index=", index, " dir=", 
dir)
+-- the missing method's job is to identify the next chunk to load
+function missing(self, index)
 
        -- use our cached result
        if self.complete then
@@ -227,53 +235,103 @@
                return
        end
 
-       -- load first chunk
-       if not self.store[0] then
+       -- if index isn't defined we load first chunk, last chunk, then all 
middle chunks from the top down
+       -- otherwise we load the chunk that contains index, then chunks on 
either side of it back-and-forth until top and bottom chunks are filled
+       if not self.last_chunk or not self.last_chunk.count then
                return 0, BLOCK_SIZE
        end
-       
+
        local count = tonumber(self.last_chunk.count)
 
-       -- load last chunk
+       -- determine the key for the last chunk in the chunk list
        local lastKey = 0
        if count > BLOCK_SIZE then
                lastKey = math.modf(count / BLOCK_SIZE)
                if lastKey * BLOCK_SIZE == count then
                        lastKey = lastKey - 1
                end
+       end
+       
+       local firstChunkFrom = 0
+       local firstChunkKey  = 0
+
+       if not index then
+               -- load first chunk if we don't have it
+               if not self.store[0] then
+                       return 0, BLOCK_SIZE
+               end
+               -- load the last chunk if we don't have it
                if not self.store[lastKey] then
                        return lastKey * BLOCK_SIZE, BLOCK_SIZE
                end
-       end
-
-       -- otherwise load in the direction of scrolling
-       local fromKey, toKey, step = 1, lastKey, 1
-       if dir < 0 then
-               fromKey, toKey, step = toKey, fromKey, -1
+               -- up is done, so start searching downward
+               self.searchDirection = 'down'
+               self.upCompleted  = true
        end
 
        -- search for chunks to load
-       for key = fromKey, toKey, step do
-               if not self.store[key] then
-                       local idx = key * BLOCK_SIZE
-
-                       log:debug(self, " missing ", BLOCK_SIZE, " items from 
pos ", idx)
-                       return idx, BLOCK_SIZE
-               end
-       end
-
-       -- if we reach here we're complete (for next time)
-       log:debug(self, " complete (calculated)")
-       self.complete = true
-       return
-end
-
+       -- get key for first chunk if we don't have it
+       if index then
+               firstChunkFrom = index - ( index % BLOCK_SIZE )
+               firstChunkKey  = math.floor(firstChunkFrom/BLOCK_SIZE)
+       end
+
+       -- don't search down if the first chunk loaded is also the last chunk
+       if firstChunkFrom + BLOCK_SIZE >= count then
+               self.downCompleted = true
+               self.searchDirection = 'up'
+       end
+
+       -- if both down and up are done, then we are done
+       if self.downCompleted and self.upCompleted then
+               -- if we reach here we're complete (for next time)
+               log:warn(self, " scan complete (calculated)")
+               self.complete = true
+               return
+       end
+
+       -- go up and down around firstChunkKey until we have self.store[0] and 
self.store[lastKey]
+       if not self.searchDirection then
+               self.searchDirection = 'up'
+       end
+       if self.searchDirection == 'up' and not self.upCompleted then
+               -- start with previous key to first chunk, go to beginning
+               local fromKey, toKey, step = firstChunkKey-1, 0, -1
+
+               if not self.downCompleted then
+                       self.searchDirection = 'down'
+               end
+               -- search for chunks to load
+               for key = fromKey, toKey, step do
+                       if not self.store[key] then
+                               local thisChunkFrom = key * BLOCK_SIZE
+                               return thisChunkFrom, BLOCK_SIZE
+                       end
+               end
+               self.upCompleted = true
+       end
+
+       if self.searchDirection == 'down' and not self.downCompleted then
+               if not self.upCompleted then
+                       self.searchDirection = 'up'
+               end
+               -- start with next key from first chunk, go to end
+               local fromKey, toKey, step = firstChunkKey+1, lastKey, 1
+               for key = fromKey, toKey, step do
+                       if not self.store[key] then
+                               local thisChunkFrom = key * BLOCK_SIZE
+                               return thisChunkFrom, BLOCK_SIZE
+                       end
+               end
+               self.downCompleted = true
+       end
+
+end
 
 function __tostring(self)
        return "DB {" .. tostring(self.windowSpec.text) .. "}"
 end
 
-
 --[[
 
 =head1 LICENSE

Modified: 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/SlimBrowserApplet.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/SlimBrowserApplet.lua?rev=3484&root=Jive&r1=3483&r2=3484&view=diff
==============================================================================
--- 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/SlimBrowserApplet.lua
 (original)
+++ 
7.4/trunk/squeezeplay/src/squeezeplay/share/applets/SlimBrowser/SlimBrowserApplet.lua
 Wed Dec 10 09:55:57 2008
@@ -144,6 +144,75 @@
        return res
 end
 
+-- turns a jsonAction table into a string that can be saved for a 
browseHistory key
+local function _stringifyJsonRequest(jsonAction)
+
+       if not jsonAction then
+               return nil
+       end
+
+       local command = {}
+
+       -- jsonActions can be uniquely identified by the cmd and params 
components
+       if jsonAction.cmd then
+               for i, v in ipairs(jsonAction.cmd) do
+                       log:warn('cmd ', i, ': ', v)
+                       command[#command + 1] = ' ' .. v
+               end
+       end
+       if jsonAction.params then
+               local sortedParams = table.sort(jsonAction.params)
+               for k in table.pairsByKeys (jsonAction.params) do
+                       log:warn('key: ', k, ' val: ', jsonAction.params[k])
+                       command[#command + 1] = ' ' .. k .. ":" .. 
jsonAction.params[k]
+               end
+       end
+
+       return table.concat(command)
+end
+
+local function _getNewStartValue(index)
+       -- start with the first item if we have no history
+       if not index then
+               return 0
+       end
+       local BLOCK_SIZE = DB:getBlockSize()
+
+       -- if we have history, we want what is going to be the selected item to 
be included in the first chunk requested
+       return math.floor(index/BLOCK_SIZE) * BLOCK_SIZE
+end
+
+
+-- _decideFirstChunk
+-- figures out the from values for performJSONAction, including logic for 
finding the previous browse index in this list
+local function _decideFirstChunk(db, jsonAction)
+       local qty           = DB:getBlockSize()
+       local commandString = _stringifyJsonRequest(jsonAction)
+       local lastBrowse    = _player:getLastBrowse(commandString)
+
+       if not lastBrowse then
+               _player.menuAnchor = nil
+       end
+
+       local from = 0
+
+       log:debug('Saving this json command to browse history table:')
+       log:debug(commandString)
+
+       if lastBrowse then
+               from = _getNewStartValue(lastBrowse.index)
+               _player.menuAnchor = lastBrowse.index 
+       else
+               lastBrowse = { index = 1 }
+               _player:setLastBrowse(commandString, lastBrowse)
+       end
+
+       log:debug('We\'ve been here before, lastBrowse index was: ', 
lastBrowse.index)
+       _player.lastKeyTable = lastBrowse
+       
+       return from, qty
+
+end
 
 -- _priorityAssign(key, defaultValue, table1, table2, ...)
 -- returns the first non nil value of table1[key], table2[key], etc.
@@ -412,6 +481,7 @@
 -- performs the JSON action...
 local function _performJSONAction(jsonAction, from, qty, step, sink)
        log:debug("_performJSONAction(from:", from, ", qty:", qty, "):")
+
        local cmdArray = jsonAction["cmd"]
        
        -- sanity check
@@ -944,6 +1014,9 @@
                        -- count == 0 responses should not be typical
                elseif step.menu then
                        step.menu:setItems(step.db:menuItems(data))
+                       if _player.menuAnchor then
+                               step.menu:setSelectedIndex(_player.menuAnchor)
+                       end
 
                        -- update the window properties
                        step.menu:setStyle(step.db:menuStyle())
@@ -1013,7 +1086,7 @@
                        end
 
                        -- what's missing?
-                       local from, qty = 
step.db:missing(step.menu:isAccelerated())
+                       local from, qty = step.db:missing(_player.menuAnchor)
                
                        if from then
                                _performJSONAction(step.data, from, qty, step, 
step.sink)
@@ -1141,7 +1214,7 @@
                                                                        
step.window:show()
                                                                        
_curStep = step
                                                                else
-                                                                       from, 
qty = step.db:missing(step.menu and step.menu:isAccelerated())
+                                                                       from, 
qty = _decideFirstChunk(step.db, jsonAction)
 
                                                                        
_lockedItem = item
                                                                        
jiveMain:lockItem(item,
@@ -1181,7 +1254,7 @@
 local function _requestStatus()
        local step = _statusStep
 
-       local from, qty = step.db:missing(step.menu:isAccelerated())
+       local from, qty = step.db:missing()
        if from then
                -- note, this is not a userRequest as the playlist is
                -- updated when the playlist changes
@@ -1512,7 +1585,7 @@
                                        or ( item['addAction'] == 'go' and 
actionName == 'add' ) then
                                        step, sink = _newDestination(_curStep, 
item, _newWindowSpec(db, item), _browseSink, jsonAction)
                                        if step.menu then
-                                               from, qty = 
step.db:missing(step.menu:isAccelerated())
+                                               from, qty = 
_decideFirstChunk(step.db, jsonAction)
                                        end
                                end
 
@@ -1587,10 +1660,22 @@
 -- _browseMenuListener
 -- called 
 local function _browseMenuListener(menu, db, menuItem, dbIndex, event)
+       log:debug("_browseMenuListener(", event:tostring(), ", " , index, ")")
+       
 
        -- ok so joe did press a key while in our menu...
        -- figure out the item action...
        local evtType = event:getType()
+
+       local currentlySelectedIndex = _curStep.menu:getSelectedIndex()
+       if _player.lastKeyTable and evtType == EVENT_FOCUS_GAINED then
+               if currentlySelectedIndex then
+                       _player.lastKeyTable.index = currentlySelectedIndex 
+               else
+                       _player.lastKeyTable.index = 1
+               end
+       end
+
 
        -- we don't care about focus: we get one everytime we change current 
item
        -- and it just pollutes our logging.
@@ -1601,8 +1686,6 @@
                return EVENT_UNUSED
        end
 
-       log:debug("_browseMenuListener(", event:tostring(), ", " , index, ")")
-       
        -- we don't care about events not on the current window
        -- assumption for event handling code: _curStep corresponds to current 
window!
        if _curStep.menu != menu then

Modified: 7.4/trunk/squeezeplay/src/squeezeplay/share/jive/slim/Player.lua
URL: 
http://svn.slimdevices.com/7.4/trunk/squeezeplay/src/squeezeplay/share/jive/slim/Player.lua?rev=3484&root=Jive&r1=3483&r2=3484&view=diff
==============================================================================
--- 7.4/trunk/squeezeplay/src/squeezeplay/share/jive/slim/Player.lua (original)
+++ 7.4/trunk/squeezeplay/src/squeezeplay/share/jive/slim/Player.lua Wed Dec 10 
09:55:57 2008
@@ -153,6 +153,18 @@
        jnt:notify("playerCurrent", currentPlayer)
 end
 
+
+function getLastBrowse(self, key)
+       if self.browseHistory[key] then
+               return self.browseHistory[key]
+       else
+               return nil
+       end
+end
+
+function setLastBrowse(self, key, lastBrowse)
+       self.browseHistory[key] = lastBrowse
+end
 
 -- _getSink
 -- returns a sink with a closure to self
@@ -253,7 +265,10 @@
                isOnStage = false,
 
                -- current song info
-               currentSong = {}
+               currentSong = {},
+
+               -- browse history
+               browseHistory = {}
        })
 
        playerIds[obj.id] = obj
@@ -368,6 +383,8 @@
        if oldInfo.power ~= self.info.power then
                self.jnt:notify('playerPower', self, self.info.power)
        end
+
+       log:debug('oldInfo.connected says: ', oldInfo.connected, ' 
self.info.connected says: ', self.info.connected)
 
        -- Check if the player connected status has changed
        if oldInfo.connected ~= self.info.connected then

_______________________________________________
Jive-checkins mailing list
[email protected]
http://lists.slimdevices.com/cgi-bin/mailman/listinfo/jive-checkins

Reply via email to