HMS

Home Media Server for Roku Players
git clone https://www.brianlane.com/git/HMS
Log | Files | Refs | README | LICENSE

commit 499284a7b2ea87fea0269b3867f6da00ef612c6d
parent 6de081f27c4f6202029337676c1d79bcfa27f546
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Sun, 13 Nov 2022 17:02:11 -0800

Add category metadata loading

This is likely not as efficient as possible (some posts indicate that
the Task is slower than render thread for parsing things). But it will
do as a start.

Diffstat:
AHMS/components/CategoryLoaderTask.brs | 18++++++++++++++++++
AHMS/components/CategoryLoaderTask.xml | 14++++++++++++++
MHMS/components/MainLoaderTask.brs | 22----------------------
MHMS/components/MainScene.brs | 18++++++++++++++++++
MHMS/source/appMediaServer.brs | 115-------------------------------------------------------------------------------
AHMS/source/getCategoryMetadata.brs | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MHMS/source/getDirectoryListing.brs | 22++++++++++++++++++++++
7 files changed, 193 insertions(+), 137 deletions(-)

diff --git a/HMS/components/CategoryLoaderTask.brs b/HMS/components/CategoryLoaderTask.brs @@ -0,0 +1,18 @@ +'******************************************************************** +'** Home Media Server Application - CategoryLoaderTask +'** Copyright (c) 2022 Brian C. Lane All Rights Reserved. +'******************************************************************** +sub Init() + print "CategoryLoaderTask->Init()" + + m.top.functionName = "GetMetadata" +end sub + +' GetMetadata is executed when m.contentTask.control = "run" from MainScene +sub GetMetadata() + print "CategoryLoaderTask->GetMetadata()" + print m.top.serverurl + print m.top.category + + m.top.metadata = getCategoryMetadata(m.top.serverurl, m.top.category) +end sub diff --git a/HMS/components/CategoryLoaderTask.xml b/HMS/components/CategoryLoaderTask.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8" ?> +<component name="CategoryLoaderTask" 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/getDirectoryListing.brs" /> + <script type="text/brightscript" uri="pkg:/source/getCategoryMetadata.brs" /> + <script type="text/brightscript" uri="CategoryLoaderTask.brs" /> + + <interface> + <field id="serverurl" type="uri" /> + <field id="category" type="string" /> + <field id="metadata" type="roArray" /> + </interface> +</component> diff --git a/HMS/components/MainLoaderTask.brs b/HMS/components/MainLoaderTask.brs @@ -42,25 +42,3 @@ Function getSortedCategoryTitles(url as String) As Object end function) return catTitles(categories) End Function - -'****************************************************** -'** Return a list of the Videos and directories -'** -'** Videos end in the following extensions -'** .mp4 .m4v .mov .wmv -'****************************************************** -Function displayFiles(files As Object, fileTypes As Object, dirs=false As Boolean) As Object - list = [] - for each f in files - ' This expects the path to have a system volume at the start - p = CreateObject("roPath", "pkg:/" + f) - if p.IsValid() and f.Left(1) <> "." then - fileType = fileTypes[p.Split().extension.mid(1)] - if (dirs and f.Right(1) = "/") or fileType = true then - list.push([f, p.Split()]) - end if - end if - end for - - return list -End Function diff --git a/HMS/components/MainScene.brs b/HMS/components/MainScene.brs @@ -53,6 +53,24 @@ end sub sub OnCreateNextPanelIndex() print "MainScene->OnCreateNextPanelIndex()" print m.listPanel.createNextPanelIndex + print m.categories[m.listPanel.createNextPanelIndex] + RunCategoryLoadTask(m.categories[m.listPanel.createNextPanelIndex]) +end sub + +sub RunCategoryLoadTask(category as string) + print "MainScene->RunCategoryLoadTask()" + print category + + m.metadataTask = CreateObject("roSGNode", "CategoryLoaderTask") + m.metadataTask.serverurl = m.top.serverurl + m.metadataTask.category = category + m.metadataTask.ObserveField("metadata", "OnMetadataLoaded") + m.metadataTask.control = "run" +end sub + +sub OnMetadataLoaded() + print "MainScene->OnMetadataLoaded()" + print m.metadataTask.metadata end sub sub OnLabelListSelected() diff --git a/HMS/source/appMediaServer.brs b/HMS/source/appMediaServer.brs @@ -315,85 +315,6 @@ Function getSetupRow(url As String) As Object return setup End Function -'********************************** -'** Return the type of the directory -'********************************** -Function directoryType(listing_hash As Object) As Integer - if listing_hash.DoesExist("photos") then - return 1 - else if listing_hash.DoesExist("songs") then - return 2 - else if listing_hash.DoesExist("episodes") then - return 3 - else if listing_hash.DoesExist("movies") then - return 4 - end if - return 0 -End Function - - -'****************************************** -'** Create an object with the movie metadata -'****************************************** -Function MovieObject(file As Object, url As String, listing_hash as Object) As Object - o = CreateObject("roAssociativeArray") - o.ContentType = "movie" - o.ShortDescriptionLine1 = file[1]["basename"] - - ' Search for SD & HD images and .bif files - if listing_hash.DoesExist(file[1]["basename"]+"-SD.png") then - o.SDPosterUrl = url+file[1]["basename"]+"-SD.png" - else if listing_hash.DoesExist(file[1]["basename"]+"-SD.jpg") then - o.SDPosterUrl = url+file[1]["basename"]+"-SD.jpg" - else - o.SDPosterUrl = url+"default-SD.png" - end if - - o.IsHD = false - ' With the roPosterScreen it always wants to request the HDPosterURL, no matter what IsHD is set to. - ' So Fake it out and reuse the -SD images for now. - if listing_hash.DoesExist(file[1]["basename"]+"-SD.png") then - o.HDPosterUrl = url+file[1]["basename"]+"-SD.png" - else if listing_hash.DoesExist(file[1]["basename"]+"-SD.jpg") then - o.HDPosterUrl = url+file[1]["basename"]+"-SD.jpg" - else - o.HDPosterUrl = url+"default-SD.png" - end if - - ' Setup the .bif file - if listing_hash.DoesExist(file[1]["basename"]+"-SD.bif") then - o.SDBifUrl = url+file[1]["basename"]+"-SD.bif" - end if - if listing_hash.DoesExist(file[1]["basename"]+"-HD.bif") then - o.HDBifUrl = url+file[1]["basename"]+"-HD.bif" - end if - - if listing_hash.DoesExist(file[1]["basename"]+".txt") then - o.Description = getDescription(url+file[1]["basename"]+".txt") - end if - - o.HDBranded = false - o.Rating = "NR" - o.StarRating = 100 - o.Title = file[1]["basename"] - o.Length = 0 - - ' Video related stuff (can I put this all in the same object?) - o.StreamBitrates = [0] - o.StreamUrls = [url + file[0]] - o.StreamQualities = ["SD"] - - streamFormat = { mp4 : "mp4", m4v : "mp4", mov : "mp4", - wmv : "wmv", hls : "hls" - } - if streamFormat.DoesExist(file[1]["extension"].Mid(1)) then - o.StreamFormat = streamFormat[file[1]["extension"].Mid(1)] - else - o.StreamFormat = ["mp4"] - end if - - return o -End Function '******************************** '** Set breadcrumb to current time @@ -501,42 +422,6 @@ Function getDescription(url As String) return "" End Function -'******************************************************************* -' Return a roArray of roAssociativeArrays for the selected category -'******************************************************************* -Function getCategoryMetadata(url As String, category As String) As Object - cat_url = url + "/" + category + "/" - listing = getDirectoryListing(cat_url) - listing_hash = CreateObject("roAssociativeArray") - for each f in listing - listing_hash.AddReplace(f, "") - end for - - ' What kind of directory is this? - dirType = directoryType(listing_hash) - if dirType = 1 then - displayList = displayFiles(listing, { jpg : true }) - else if dirType = 2 then - displayList = displayFiles(listing, { mp3 : true }) - else if dirType = 3 then - displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) - else if dirType = 4 then - displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) - else - ' Assume movies if there is no type file - displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) - end if - - Sort(displayList, function(k) - return LCase(k[0]) - end function) - list = CreateObject("roArray", displayList.Count(), false) - for j = 0 to displayList.Count()-1 - list.Push(MovieObject(displayList[j], cat_url, listing_hash)) - end for - return list -End Function - '****************************************************** ' Get the last focused item for a category ' or return 0 if there is no keystore or an error diff --git a/HMS/source/getCategoryMetadata.brs b/HMS/source/getCategoryMetadata.brs @@ -0,0 +1,121 @@ +'******************************************************************** +'** Home Media Server Application - Get the metadata for a category +'** Copyright (c) 2022 Brian C. Lane All Rights Reserved. +'******************************************************************** + +'******************************************************************* +' Return a roArray of roAssociativeArrays for the selected category +'******************************************************************* +Function getCategoryMetadata(url As String, category As String) As Object + cat_url = url + "/" + category + "/" + listing = getDirectoryListing(cat_url) + listing_hash = CreateObject("roAssociativeArray") + for each f in listing + listing_hash.AddReplace(f, "") + end for + + ' What kind of directory is this? + dirType = directoryType(listing_hash) + if dirType = 1 then + displayList = displayFiles(listing, { jpg : true }) + else if dirType = 2 then + displayList = displayFiles(listing, { mp3 : true }) + else if dirType = 3 then + displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) + else if dirType = 4 then + displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) + else + ' Assume movies if there is no type file + displayList = displayFiles(listing, { mp4 : true, m4v : true, mov : true, wmv : true } ) + end if + + Sort(displayList, function(k) + return LCase(k[0]) + end function) + list = CreateObject("roArray", displayList.Count(), false) + for j = 0 to displayList.Count()-1 + list.Push(MovieObject(displayList[j], cat_url, listing_hash)) + end for + return list +End Function + +'********************************** +'** Return the type of the directory +'********************************** +Function directoryType(listing_hash As Object) As Integer + if listing_hash.DoesExist("photos") then + return 1 + else if listing_hash.DoesExist("songs") then + return 2 + else if listing_hash.DoesExist("episodes") then + return 3 + else if listing_hash.DoesExist("movies") then + return 4 + end if + return 0 +End Function + +'****************************************** +'** Create an object with the movie metadata +'****************************************** +Function MovieObject(file As Object, url As String, listing_hash as Object) As Object + o = CreateObject("roAssociativeArray") + o.ContentType = "movie" + o.ShortDescriptionLine1 = file[1]["basename"] + + ' Search for SD & HD images and .bif files + if listing_hash.DoesExist(file[1]["basename"]+"-SD.png") then + o.SDPosterUrl = url+file[1]["basename"]+"-SD.png" + else if listing_hash.DoesExist(file[1]["basename"]+"-SD.jpg") then + o.SDPosterUrl = url+file[1]["basename"]+"-SD.jpg" + else + o.SDPosterUrl = url+"default-SD.png" + end if + + o.IsHD = false + ' With the roPosterScreen it always wants to request the HDPosterURL, no matter what IsHD is set to. + ' So Fake it out and reuse the -SD images for now. + if listing_hash.DoesExist(file[1]["basename"]+"-SD.png") then + o.HDPosterUrl = url+file[1]["basename"]+"-SD.png" + else if listing_hash.DoesExist(file[1]["basename"]+"-SD.jpg") then + o.HDPosterUrl = url+file[1]["basename"]+"-SD.jpg" + else + o.HDPosterUrl = url+"default-SD.png" + end if + + ' Setup the .bif file + if listing_hash.DoesExist(file[1]["basename"]+"-SD.bif") then + o.SDBifUrl = url+file[1]["basename"]+"-SD.bif" + end if + if listing_hash.DoesExist(file[1]["basename"]+"-HD.bif") then + o.HDBifUrl = url+file[1]["basename"]+"-HD.bif" + end if + + if listing_hash.DoesExist(file[1]["basename"]+".txt") then + o.Description = getDescription(url+file[1]["basename"]+".txt") + end if + + o.HDBranded = false + o.Rating = "NR" + o.StarRating = 100 + o.Title = file[1]["basename"] + o.Length = 0 + + ' Video related stuff (can I put this all in the same object?) + o.StreamBitrates = [0] + o.StreamUrls = [url + file[0]] + o.StreamQualities = ["SD"] + + streamFormat = { mp4 : "mp4", m4v : "mp4", mov : "mp4", + wmv : "wmv", hls : "hls" + } + if streamFormat.DoesExist(file[1]["extension"].Mid(1)) then + o.StreamFormat = streamFormat[file[1]["extension"].Mid(1)] + else + o.StreamFormat = ["mp4"] + end if + + return o +End Function + + diff --git a/HMS/source/getDirectoryListing.brs b/HMS/source/getDirectoryListing.brs @@ -32,3 +32,25 @@ Function getDirectoryListing(url As String) As Object next_href = next_quote + 2 end while End Function + +'****************************************************** +'** Return a list of the Videos and directories +'** +'** Videos end in the following extensions +'** .mp4 .m4v .mov .wmv +'****************************************************** +Function displayFiles(files As Object, fileTypes As Object, dirs=false As Boolean) As Object + list = [] + for each f in files + ' This expects the path to have a system volume at the start + p = CreateObject("roPath", "pkg:/" + f) + if p.IsValid() and f.Left(1) <> "." then + fileType = fileTypes[p.Split().extension.mid(1)] + if (dirs and f.Right(1) = "/") or fileType = true then + list.push([f, p.Split()]) + end if + end if + end for + + return list +End Function