commit 476730f04baa0b92d177e9f52156ee4037ee6e14
parent b0941e10e853d1f37a7c4b175a64bb7bf02cdc12
Author: Brian C. Lane <bcl@ibrianlane.com>
Date: Sun, 28 Dec 2014 07:12:26 -0800
Add support for using a keystore
This implements support for saving and recalling the last selected video
in a row and the last playback position to a remote keyserver. It must
be aliased to the movie server url + /keystore/<key> and values are set
by POST with value=<value>
Diffstat:
4 files changed, 117 insertions(+), 21 deletions(-)
diff --git a/HMS/source/appMain.brs b/HMS/source/appMain.brs
@@ -18,7 +18,10 @@ Sub Main()
end if
end while
- mediaServer("http://"+RegRead("ServerURL"))
+ ' Check to see if the server supports keystore
+ has_keystore = isUrlValid("http://"+RegRead("ServerURL")+"/keystore/version")
+
+ mediaServer("http://"+RegRead("ServerURL"), has_keystore)
End Sub
diff --git a/HMS/source/appMediaServer.brs b/HMS/source/appMediaServer.brs
@@ -6,8 +6,9 @@
'******************************************************
'** Display a scrolling grid of everything on the server
'******************************************************
-Function mediaServer( url As String ) As Object
+Function mediaServer( url As String, has_keystore As Boolean ) As Object
print "url: ";url
+ print "has_keystore: "; has_keystore
port=CreateObject("roMessagePort")
grid = CreateObject("roGridScreen")
@@ -44,7 +45,6 @@ Function mediaServer( url As String ) As Object
' run the grid
showTimeBreadcrumb(grid, true)
- grid.SetFocusedListitem(0, 1)
grid.Show()
loadingDialog = ShowPleaseWait("Loading Movies...", "")
@@ -81,13 +81,26 @@ Function mediaServer( url As String ) As Object
list.Push(MovieObject(displayList[j], cat_url, listing_hash))
end for
grid.SetContentList(1+i, list)
+ grid.SetFocusedListitem(1+i, 0)
screen.Push(list)
+ if has_keystore = true then
+ ' Get the last selected video on this row
+ last_pos = getKeyValue(url, getLastElement(categories[i][0]))
+ if last_pos <> "" and last_pos.toint() < list.Count() then
+ grid.SetFocusedListitem(1+i, last_pos.toint())
+ end if
+ end if
+ if displayList.Count() = 0 then
+ grid.SetListVisible(1+i, false)
+ end if
else
grid.SetContentList(1+i, [])
screen.Push([])
+ grid.SetListVisible(1+i, false)
end if
end for
loadingDialog.Close()
+ grid.SetFocusedListitem(0, 1)
while true
msg = wait(30000, port)
@@ -116,7 +129,17 @@ Function mediaServer( url As String ) As Object
grid.SetContentList(0, searchRow)
grid.SetFocusedListitem(0, 2)
else
- playMovie(screen[msg.GetIndex()][msg.GetData()])
+ if has_keystore = true then
+ setKeyValue(url, getLastElement(categories[msg.GetIndex()-1][0]), tostr(msg.GetData()))
+ end if
+ result = playMovie(screen[msg.GetIndex()][msg.GetData()], url, has_keystore)
+ if result = true and msg.GetData() < screen[msg.GetIndex()].Count() then
+ ' Advance to the next video and save it
+ grid.SetFocusedListitem(msg.GetIndex(), msg.GetData()+1)
+ if has_keystore = true then
+ setKeyValue(url, getLastElement(categories[msg.GetIndex()-1][0]), tostr(msg.GetData()+1))
+ end if
+ end if
end if
endif
else if msg = invalid then
@@ -249,12 +272,18 @@ End Function
'*************************************
'** Get the last position for the movie
'*************************************
-Function getLastPosition(movie As Object) As Integer
+Function getLastPosition(title As String, url As String, has_keystore As Boolean) As Integer
' use movie.Title as the filename
- lastPos = ReadAsciiFile("tmp:/"+movie.Title)
- print "Last position of ";movie.Title;" is ";lastPos
- if lastPos <> "" then
- return strtoi(lastPos)
+ last_pos = ReadAsciiFile("tmp:/"+title)
+ if last_pos <> "" then
+ return last_pos.toint()
+ end if
+ ' No position stored on local filesystem, query keystore
+ if has_keystore = true then
+ last_pos = getKeyValue(url, title)
+ if last_pos <> "" then
+ return last_pos.toint()
+ end if
end if
return 0
End Function
@@ -285,27 +314,31 @@ End Function
'** Play the video using the data from the movie
'** metadata object passed to it
'******************************************************
-Sub playMovie(movie as Object)
+Sub playMovie(movie As Object, url As String, has_keystore As Boolean) As Boolean
p = CreateObject("roMessagePort")
video = CreateObject("roVideoScreen")
video.setMessagePort(p)
video.SetPositionNotificationPeriod(15)
- movie.PlayStart = getLastPosition(movie)
+ movie.PlayStart = getLastPosition(movie.Title, url, has_keystore)
video.SetContent(movie)
video.show()
- lastPos = 0
+ last_pos = 0
while true
msg = wait(0, video.GetMessagePort())
if type(msg) = "roVideoScreenEvent"
if msg.isScreenClosed() then 'ScreenClosed event
exit while
else if msg.isPlaybackPosition() then
- lastPos = msg.GetIndex()
- WriteAsciiFile("tmp:/"+movie.Title, tostr(lastPos))
+ last_pos = msg.GetIndex()
+ WriteAsciiFile("tmp:/"+movie.Title, tostr(last_pos))
+ if has_keystore = true then
+ setKeyValue(url, movie.Title, tostr(last_pos))
+ end if
else if msg.isfullresult() then
DeleteFile("tmp:/"+movie.Title)
+ return true
else if msg.isRequestFailed() then
print "play failed: "; msg.GetMessage()
else
@@ -313,6 +346,8 @@ Sub playMovie(movie as Object)
end if
end if
end while
+
+ return false
End Sub
'******************************************************
diff --git a/HMS/source/getDirectoryListing.brs b/HMS/source/getDirectoryListing.brs
@@ -44,3 +44,26 @@ Function getUrls(array as Object, element as Object) As Object
return array
End Function
+' ***********************************
+' * Get a value for a key
+' ***********************************
+Function getKeyValue(url As String, key As String) As String
+ result = getHTMLWithTimeout(url+"/keystore/"+key, 60)
+ if result.error and result.response <> 404 then
+ print "Error ";result.response;" getting key ";key;": ";result.reason
+ return ""
+ elseif result.error and result.response = 404 then
+ return ""
+ end if
+ return result.str
+End Function
+
+' ***********************************
+' * Set a value for a key
+' ***********************************
+Function setKeyValue(url As String, key As String, value As String)
+ result = postHTMLWithTimeout(url+"/keystore/"+key, "value="+value, 60)
+ if result.error then
+ print "Error ";result.response;" setting key ";key;"=";value;": ";result.reason
+ end if
+End Function
diff --git a/HMS/source/urlUtils.brs b/HMS/source/urlUtils.brs
@@ -47,7 +47,7 @@ Function CreateURLTransferObject2(url As String, contentHeader As String) as Obj
obj = CreateObject("roUrlTransfer")
obj.SetPort(CreateObject("roMessagePort"))
obj.SetUrl(url)
- obj.AddHeader("Content-Type", contentHeader)
+ obj.AddHeader("Content-Type", contentHeader)
obj.EnableEncodings(true)
return obj
End Function
@@ -144,7 +144,7 @@ Function http_get_to_string_with_retry() as String
event = wait(timeout%, m.Http.GetPort())
if type(event) = "roUrlEvent"
str = event.GetString()
- exit while
+ exit while
elseif event = invalid
m.Http.AsyncCancel()
REM reset the connection on timeouts
@@ -199,14 +199,14 @@ Function http_post_from_string_with_timeout(val As String, seconds as Integer) a
if (m.Http.AsyncPostFromString(val))
event = wait(timeout%, m.Http.GetPort())
if type(event) = "roUrlEvent"
- print "1"
- str = event.GetString()
+ print "1"
+ str = event.GetString()
elseif event = invalid
- print "2"
+ print "2"
Dbg("AsyncPostFromString timeout")
m.Http.AsyncCancel()
else
- print "3"
+ print "3"
Dbg("AsyncPostFromString unknown event", event)
endif
endif
@@ -238,7 +238,7 @@ Function getHTMLWithTimeout(url As String, seconds As Integer) as Object
end if
elseif event = invalid
Dbg("AsyncGetToString timeout")
- htp.AsyncCancel()
+ http.AsyncCancel()
else
Dbg("AsyncGetToString unknown event", event)
endif
@@ -250,3 +250,38 @@ Function getHTMLWithTimeout(url As String, seconds As Integer) as Object
return result
End Function
+' ********************************************************************
+' POST a value to a URL and get the response
+' ********************************************************************
+Function postHTMLWithTimeout(url As String, content As String, seconds As Integer) as Object
+ timeout% = 1000 * seconds
+
+ result = { str : "", error : false, response : 0, reason : "" }
+
+ http = CreateObject("roUrlTransfer")
+ http.SetUrl(url)
+ http.SetPort(CreateObject("roMessagePort"))
+ http.EnableFreshConnection(true) 'Don't reuse existing connections
+ if (http.AsyncPostFromString(content))
+ event = wait(timeout%, http.GetPort())
+ if type(event) = "roUrlEvent"
+ if event.GetResponseCode() = 200 then
+ result.str = event.GetString()
+ else
+ result.error = true
+ result.response = event.GetResponseCode()
+ result.reason = event.GetFailureReason()
+ end if
+ elseif event = invalid
+ Dbg("AsyncGetToString timeout")
+ http.AsyncCancel()
+ else
+ Dbg("AsyncGetToString unknown event", event)
+ endif
+ endif
+
+' print "HTTP result: "
+' print result
+
+ return result
+End Function