commit ba6bb1628819954419ea0d882b86ad5e1e2da02f
parent 5500447f6a455e0a1f7b8ffbb42f0e8f0ced7b6e
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Sat, 19 Nov 2022 12:19:59 -0800
MainScene: Organize and document the functions
Diffstat:
1 file changed, 168 insertions(+), 96 deletions(-)
diff --git a/HMS/components/MainScene.brs b/HMS/components/MainScene.brs
@@ -10,6 +10,7 @@ sub Init()
 
     StartClock()
 
+    ' Get the server URL from the registry or a user dialog
     url = RegRead("ServerURL")
     if url = invalid then
         RunSetupServerDialog("")
@@ -18,9 +19,17 @@ sub Init()
         RunValidateURLTask(url)
     end if
 
+    ' Setup the video player node
     SetupVideoPlayer()
 end sub
 
+
+'****************
+' Clock functions
+'****************
+
+' StartClock starts displaying the clock in the upper right of the screen
+' It calls UpdateClock every 5 seconds
 sub StartClock()
     m.clock = m.top.FindNode("clock")
     m.clockTimer = m.top.FindNode("clockTimer")
@@ -29,6 +38,7 @@ sub StartClock()
     UpdateClock()
 end sub
 
+' Update the clock, showing HH:MM AM/PM in the upper right of the screen
 sub UpdateClock()
     now = CreateObject("roDateTime")
     now.ToLocalTime()
@@ -54,6 +64,14 @@ sub UpdateClock()
     m.clock.text = now.GetWeekday()+" "+hour+":"+minutes+ampm
 end sub
 
+
+'******************
+' Content functions
+'******************
+'
+' RunContentTask is called when the server url has been set from the registry or
+' entered by the user, and verified to be valid.
+' It then starts the task to load the list of categories
 sub RunContentTask()
     print "MainScene->RunContentTask()"
 
@@ -63,45 +81,20 @@ sub RunContentTask()
     m.contentTask.control = "run"
 end sub
 
-sub GetKeystoreValue(key as string, callback as string)
-    m.keystoreTask.serverurl = m.top.serverurl
-    m.keystoreTask.key = key
-    m.keystoreTask.value = ""
-    m.keystoreTask.command = "get"
-    if callback <> ""
-        m.keystoreTask.ObserveField("done", callback)
-    end if
-    m.keystoreTask.control = "run"
-end sub
-
-sub SetKeystoreValue(key as string, value as string, callback as string)
-    m.keystoreTask.serverurl = m.top.serverurl
-    m.keystoreTask.key = key
-    m.keystoreTask.value = value
-    m.keystoreTask.command = "set"
-    if callback <> ""
-        m.keystoreTask.ObserveField("done", callback)
-    end if
-    m.keystoreTask.control = "run"
-end sub
-
-sub ResetKeystoreTask()
-    m.keystoreTask.UNObserveField("done")
-    m.keystoreTask.done = false
-end sub
-
+' OnCategoriesLoaded is called when the list of categories has been recalled
+' from the server. It is returned as a list of strings and is displayed on
+' the left side of the screen.
 sub OnCategoriesLoaded()
     print "MainScene->OnCategoriesLoaded()"
     print m.contentTask.categories
     m.categories = m.contentTask.categories
 
-    ' Add these to the list on the left side of the screen... how?
+    ' Add these to the list on the left side of the screen
     m.panels = m.top.FindNode("panels")
     m.listPanel = m.panels.CreateChild("ListPanel")
     m.listPanel.observeField("createNextPanelIndex", "OnCreateNextPanelIndex")
 
     m.labelList = CreateObject("roSGNode", "LabelList")
-    m.labelList.observeField("focusedItem", "OnLabelListSelected")
     m.listPanel.list = m.labelList
     m.listPanel.appendChild(m.labelList)
     m.listPanel.SetFocus(true)
@@ -115,6 +108,8 @@ sub OnCategoriesLoaded()
     m.labelList.content = ln
 end sub
 
+' OnCreateNextPanelIndex is called when a new category is selected (up/down)
+' It populates the poster grid on the right of the screen
 sub OnCreateNextPanelIndex()
     print "MainScene->OnCreateNextPanelIndex()"
     print m.listPanel.createNextPanelIndex
@@ -123,6 +118,8 @@ sub OnCreateNextPanelIndex()
     RunCategoryLoadTask(m.categories[m.listPanel.createNextPanelIndex])
 end sub
 
+' RunCategoryLoadTask runs a task to get the metadata for the selected category
+' It calls OnMetadataLoaded when it is done
 sub RunCategoryLoadTask(category as string)
     print "MainScene->RunCategoryLoadTask()"
     print category
@@ -134,6 +131,9 @@ sub RunCategoryLoadTask(category as string)
     m.metadataTask.control = "run"
 end sub
 
+' OnMetadataLoaded is called when it has retrieved the metadata for the category
+' It creates one GridPanel and one PosterGrid then re-populates them with each
+' new batch of metadata.
 sub OnMetadataLoaded()
     print "MainScene->OnMetadataLoaded()"
     m.metadata = m.metadataTask.metadata
@@ -179,12 +179,46 @@ sub OnMetadataLoaded()
     m.posterGrid.content = cn
 end sub
 
+' OnPosterSelected it called when OK is hit on the selected poster
+' It starts the video player
 sub OnPosterSelected()
     print "MainScene->OnPosterSelected()"
     print m.posterGrid.itemSelected
     StartVideoPlayer(m.posterGrid.itemSelected)
 end sub
 
+' OnPosterFocused updates the information at the top of the screen with the
+' category name and the name of the selected video
+sub OnPosterFocused()
+    print "MainScene->OnPosterFocused()"
+    print m.posterGrid.itemFocused
+    print m.metadata[m.posterGrid.itemFocused].ShortDescriptionLine1
+    m.details.text = m.categories[m.listPanel.createNextPanelIndex] + " | " + m.metadata[m.posterGrid.itemFocused].ShortDescriptionLine1
+end sub
+
+
+'***********************
+' Video player functions
+'***********************
+
+' SetupVideoPlayer sets up the observers for the video node
+' and how often it will report the playback position
+sub SetupVideoPlayer()
+    ' Setup the video player
+    m.video = m.top.FindNode("player")
+    m.video.observeField("state", "OnVideoStateChange")
+    m.video.observeField("position", "OnVideoPositionChange")
+    m.video.notificationInterval = 5
+    ' map of events that should be handled on state change
+    m.statesToHandle = {
+        finished: ""
+        error:    ""
+    }
+end sub
+
+' StartVideoPlayer is called with the index of the video to play
+' It runs a keystore task to retrieve the last playback position for the
+' selected video and then calls StartPlayback
 sub StartVideoPlayer(index as integer)
     print "MainScene->StartVideoPlayer()"
     print m.metadata[index].ShortDescriptionLine1
@@ -194,8 +228,8 @@ sub StartVideoPlayer(index as integer)
     GetKeystoreValue(m.video.content.Title, "StartPlayback")
 end sub
 
-
-' Called by GetKeystoreValue
+' StartPlayback is called by GetKeystoreValue which may have a starting
+' position. If so, it is set, and playback is started.
 sub StartPlayback()
     print "MainScene->StartPlayback()"
     ResetKeystoreTask()
@@ -210,71 +244,8 @@ sub StartPlayback()
     m.video.control = "play"
 end sub
 
-sub OnPosterFocused()
-    print "MainScene->OnPosterFocused()"
-    print m.posterGrid.itemFocused
-    print m.metadata[m.posterGrid.itemFocused].ShortDescriptionLine1
-    m.details.text = m.categories[m.listPanel.createNextPanelIndex] + " | " + m.metadata[m.posterGrid.itemFocused].ShortDescriptionLine1
-end sub
-
-sub OnLabelListSelected()
-    print "MainScene->OnLabelListSelected()"
-end sub
-
-sub RunValidateURLTask(url as string)
-    print "MainScene->RunValidateURLTask()"
-
-    m.validateTask = CreateObject("roSGNode", "ValidateURLTask")
-    m.validateTask.serverurl = url
-    m.validateTask.ObserveField("valid", "OnValidateChanged")
-    m.validateTask.control = "run"
-end sub
-
-sub OnValidateChanged()
-    print "MainScene->OnValidateChanged"
-    print "server url = "; m.validateTask.serverurl
-    print "valid? "; m.validateTask.valid
-    print "keystore? "; m.validateTask.keystore
-    if not m.validateTask.valid then
-        ' Still invalid, run it again
-        RunSetupServerDialog(m.validateTask.serverurl)
-    else
-        ' Valid url, trigger the content load
-        m.top.serverurl = m.validateTask.serverurl
-        ' And save it for next time
-        RegWrite("ServerURL", m.validateTask.serverurl)
-        m.keystoreTask.has_keystore = m.validateTask.keystore
-    end if
-end sub
-
-sub RunSetupServerDialog(url as string)
-    print "MainScene->RunSetupServerDialog()"
-    m.serverDialog = createObject("roSGNode", "SetupServerDialog")
-    m.serverDialog.ObserveField("serverurl", "OnSetupServerURL")
-    m.serverDialog.text = url
-    m.top.dialog = m.serverDialog
-end sub
-
-sub OnSetupServerURL()
-    print "MainScene->OnSetupServerURL()"
-    print m.serverDialog.serverurl
-
-    RunValidateURLTask(m.serverDialog.serverurl)
-end sub
-
-sub SetupVideoPlayer()
-    ' Setup the video player
-    m.video = m.top.FindNode("player")
-    m.video.observeField("state", "OnVideoStateChange")
-    m.video.observeField("position", "OnVideoPositionChange")
-    m.video.notificationInterval = 5
-    ' map of events that should be handled on state change
-    m.statesToHandle = {
-        finished: ""
-        error:    ""
-    }
-end sub
-
+' OnVideoStateChanged is called when the playback is finished or there is an error
+' it will save the last playback position and close the video player
 sub OnVideoStateChange()
     print "MainScene->OnVideoStateChange()"
     ? "video state: " + m.video.state
@@ -290,6 +261,8 @@ sub OnVideoStateChange()
     end if
 end sub
 
+' CloseVideoPlayer coses the player and stops playback, returning focus to the
+' poster grid.
 sub CloseVideoPlayer()
     print "MainScene->CloseVideoPlayer()"
     m.video.visible = false
@@ -297,6 +270,8 @@ sub CloseVideoPlayer()
     m.posterGrid.SetFocus(true)
 end sub
 
+' OnVideoPositionChange is called every 5 seconds and it sends the position
+' to the keystore server
 sub OnVideoPositionChange()
     print "MainScene->OnVideoPositionChange()"
     if m.video.positionInfo = invalid
@@ -306,6 +281,8 @@ sub OnVideoPositionChange()
     SetKeystoreValue(m.video.content.Title, m.video.positionInfo.video.ToStr(), "ResetKeystoreTask")
 end sub
 
+' onKeyEvent handles hitting 'back' during playback and play when selecting a poster grid
+' which normally doesn't start playback.
 function onKeyEvent(key as String, press as Boolean) as Boolean
     if press
         if key = "back"  'If the back button is pressed
@@ -320,3 +297,98 @@ function onKeyEvent(key as String, press as Boolean) as Boolean
         end if
     end if
 end Function
+
+
+'***********************
+' Server setup functions
+'***********************
+
+' RunSetupServerDialog runs the dialog prompting the user for the server url
+sub RunSetupServerDialog(url as string)
+    print "MainScene->RunSetupServerDialog()"
+    m.serverDialog = createObject("roSGNode", "SetupServerDialog")
+    m.serverDialog.ObserveField("serverurl", "OnSetupServerURL")
+    m.serverDialog.text = url
+    m.top.dialog = m.serverDialog
+end sub
+
+' OnSetupServerURL is called when the user has entered a url, it then validates it
+' by calling RunValidateURLTask
+sub OnSetupServerURL()
+    print "MainScene->OnSetupServerURL()"
+    print m.serverDialog.serverurl
+
+    RunValidateURLTask(m.serverDialog.serverurl)
+end sub
+
+' RunValidateURLTask is called to validate the url that the user entered in the dialog
+' it starts a task and calls OnValidateChanged when done.
+sub RunValidateURLTask(url as string)
+    print "MainScene->RunValidateURLTask()"
+
+    m.validateTask = CreateObject("roSGNode", "ValidateURLTask")
+    m.validateTask.serverurl = url
+    m.validateTask.ObserveField("valid", "OnValidateChanged")
+    m.validateTask.control = "run"
+end sub
+
+' OnValidateChanged checks the result of validating the URL and either runs the setup
+' dialog again, or sets the serverurl which triggers loading the categories and the
+' rest of the screen.
+sub OnValidateChanged()
+    print "MainScene->OnValidateChanged"
+    print "server url = "; m.validateTask.serverurl
+    print "valid? "; m.validateTask.valid
+    print "keystore? "; m.validateTask.keystore
+    if not m.validateTask.valid then
+        ' Still invalid, run it again
+        RunSetupServerDialog(m.validateTask.serverurl)
+    else
+        ' Valid url, trigger the content load
+        m.top.serverurl = m.validateTask.serverurl
+        ' And save it for next time
+        RegWrite("ServerURL", m.validateTask.serverurl)
+        m.keystoreTask.has_keystore = m.validateTask.keystore
+    end if
+end sub
+
+
+' ******************
+' Keystore functions
+' ******************
+
+' GetKeystoreValue retrieves a string from the keystore server
+' It calls the callback when it is done (or has failed)
+' The callback needs to call ResetKeystoreTask to clear the
+' done field.
+sub GetKeystoreValue(key as string, callback as string)
+    m.keystoreTask.serverurl = m.top.serverurl
+    m.keystoreTask.key = key
+    m.keystoreTask.value = ""
+    m.keystoreTask.command = "get"
+    if callback <> ""
+        m.keystoreTask.ObserveField("done", callback)
+    end if
+    m.keystoreTask.control = "run"
+end sub
+
+' SetKeystoreValue sets a key to a string on the keystore server
+' It calls the callback when it is done (or has failed)
+' The callback needs to call ResetKeystoreTask to clear the
+' done field.
+sub SetKeystoreValue(key as string, value as string, callback as string)
+    m.keystoreTask.serverurl = m.top.serverurl
+    m.keystoreTask.key = key
+    m.keystoreTask.value = value
+    m.keystoreTask.command = "set"
+    if callback <> ""
+        m.keystoreTask.ObserveField("done", callback)
+    end if
+    m.keystoreTask.control = "run"
+end sub
+
+' ResetKeystoreTask clears the observer and sets done back to false
+sub ResetKeystoreTask()
+    m.keystoreTask.UNObserveField("done")
+    m.keystoreTask.done = false
+end sub