commit 645c03cf6d44f471d1c8863bdc173b0fc8d3c166
parent 5804294d12d72ce9b911436846cf5daac47e1c2f
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Thu, 17 Nov 2022 19:43:22 -0800
Add using keystore to save playback position
Diffstat:
3 files changed, 102 insertions(+), 6 deletions(-)
diff --git a/HMS/components/KeystoreTask.brs b/HMS/components/KeystoreTask.brs
@@ -0,0 +1,35 @@
+'********************************************************************
+'**  Home Media Server Application - KeystoreTask
+'**  Copyright (c) 2022 Brian C. Lane All Rights Reserved.
+'********************************************************************
+sub Init()
+    print "KeystoreTask->Init()"
+
+    m.top.functionName = "ExecuteCommand"
+end sub
+
+' ExecuteCommand is executed when  m.keystoreTask.control = "run" from MainScene
+' This needs to be reset along with UNObserveField("done") to prevent accidental re-triggering
+sub ExecuteCommand()
+    print "KeystoreTask->ExecuteCommand()"
+    print "Server url = "; m.top.serverurl
+    print "command = "; m.top.command
+    print "key = "; m.top.key
+    print "value = "; m.top.value
+
+    if not m.top.has_keystore
+        m.top.done = true
+        return
+    end if
+
+    if m.top.command = "get"
+        m.top.value = getKeyValue(m.top.serverurl, m.top.key)
+        print "new value = "; m.top.value
+    else if m.top.command = "set"
+        setKeyValue(m.top.serverurl, m.top.key, m.top.value)
+    end if
+
+    m.top.done = true
+end sub
+
+
diff --git a/HMS/components/KeystoreTask.xml b/HMS/components/KeystoreTask.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<component name="KeystoreTask" extends="Task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
+    <script type="text/brightscript" uri="pkg:/source/generalUtils.brs" />
+    <script type="text/brightscript" uri="pkg:/source/urlUtils.brs" />
+    <script type="text/brightscript" uri="pkg:/source/keystore.brs" />
+    <script type="text/brightscript" uri="KeystoreTask.brs" />
+
+    <interface>
+        <field id="serverurl" type="uri" />
+        <field id="has_keystore" type="bool" />
+        <field id="command" type="string" />
+        <field id="key" type="string" />
+        <field id="value" type="string" />
+        <field id="done" type="bool" />
+    </interface>
+</component>
diff --git a/HMS/components/MainScene.brs b/HMS/components/MainScene.brs
@@ -6,6 +6,7 @@ sub Init()
     print "MainScene->Init()"
     m.top.ObserveField("serverurl", "RunContentTask")
     m.details = m.top.FindNode("details")
+    m.keystoreTask = CreateObject("roSGNode", "KeystoreTask")
 
     StartClock()
 
@@ -62,6 +63,33 @@ 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
+
 sub OnCategoriesLoaded()
     print "MainScene->OnCategoriesLoaded()"
     print m.contentTask.categories
@@ -167,9 +195,21 @@ sub StartVideoPlayer(index as integer)
     content.Title = item.ShortDescriptionLine1
     ' TODO fix the category metadata
     content.Url = item.StreamURLS[0]
+    m.video.content = content
 
+    GetKeystoreValue(content.Title, "StartPlayback")
+end sub
+
+
+' Called by GetKeystoreValue
+sub StartPlayback()
+    ResetKeystoreTask()
+
+    ' Was there a result?
+    if m.keystoreTask.value <> ""
+        m.video.seek = m.keystoreTask.value.ToInt()
+    end if
     ' Play the selected video
-    m.video.content = content
     m.video.visible = true
     m.video.SetFocus(true)
     m.video.control = "play"
@@ -197,8 +237,9 @@ end sub
 
 sub OnValidateChanged()
     print "MainScene->OnValidateChanged"
-    print m.validateTask.serverurl
-    print m.validateTask.valid
+    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)
@@ -207,7 +248,7 @@ sub OnValidateChanged()
         m.top.serverurl = m.validateTask.serverurl
         ' And save it for next time
         RegWrite("ServerURL", m.validateTask.serverurl)
-        m.top.keystore = m.validateTask.keystore
+        m.keystoreTask.has_keystore = m.validateTask.keystore
     end if
 end sub
 
@@ -231,7 +272,7 @@ sub SetupVideoPlayer()
     m.video = m.top.FindNode("player")
     m.Video.observeField("state", "OnVideoStateChange")
     m.Video.observeField("position", "OnVideoPositionChange")
-    m.Video.notificationInterval = 1
+    m.Video.notificationInterval = 5
     ' map of events that should be handled on state change
     m.statesToHandle = {
         finished: ""
@@ -259,7 +300,11 @@ end sub
 
 sub OnVideoPositionChange()
     print "MainScene->OnVideoPositionChange()"
-    ' TODO save position to keystore at intervals
+    if m.video.positionInfo = invalid
+        return
+    end if
+    print "position = "; m.video.positionInfo.video
+    SetKeystoreValue(m.video.content.Title, m.video.positionInfo.video.ToStr(), "ResetKeystoreTask")
 end sub
 
 function onKeyEvent(key as String, press as Boolean) as Boolean