Hi i have Roku-NewVideoPlayer-master proyect , i need to get 3 diferent kind of
roPosterScreen for example on the categories.xml y get the next code
<?xml version="1.0" encoding="UTF-8"?>
<!--
'********************************************************************
'
' NewVideoPlayer - Example Multi-Level Roku Channel
'
' Copyright (c) 2015, belltown. All rights reserved. See LICENSE.txt
'
'*********************************************************************
-->
<categories>
<!--
A category can have nested category elements - and may terminate in categoryLeaf elements referring to local or remote Roku or RSS feeds
-->
<category title="TWiT TV" description="Roku Categories Example" sd_img="http://wiki.twit.tv/w/images/thumb/Brickhouse_Feed.jpg/220px-Brickhouse_Feed.jpg">
<category title="PELICULAS" description="This category has leaves" sd_img="11.890m.com/roku/otros/twd.rss">
<categoryLeaf title="PELIS VARIAS" description="" feed="311.890m.com/roku/otros/twd.rss"></categoryLeaf>
<categoryLeaf title="PELICULAS ESTRENO" description="" feed="11.890m.com/roku/otros/vodmov.xml"></categoryLeaf>
<categoryLeaf title="Coding 101" description="" feed="http://feeds.twit.tv/code_video_small.xml"></categoryLeaf>
<categoryLeaf title="Security Now" description="" feed="http://feeds.twit.tv/sn_video_small.xml"></categoryLeaf>
</category>
<category title="TWiT TV - HI" sd_img="http://twit.cachefly.net/coverart/all/all144videohi.jpg">
<categoryLeaf title="All Shows - HI" description="" feed="http://feeds.twit.tv/brickhouse_video_large.xml"></categoryLeaf>
</category>
<category title="TWiT TV - HD" sd_img="http://twit.cachefly.net/coverart/all/all144videohd.jpg">
<categoryLeaf title="All Shows - HD" description="" feed="http://feeds.twit.tv/brickhouse_video_hd.xml"></categoryLeaf>
</category>
</category>
<!--
A category can have a "feed" attribute referring to a local Roku or RSS feed
-->
<category title="TWiT Roku Feed"
description="Roku Feed Example"
sd_img="http://wiki.twit.tv/w/images/thumb/Brickhouse_Feed.jpg/220px-Brickhouse_Feed.jpg"
feed="pkg:/xml/feed.xml">
</category>
<!--
A category can have a "feed" attribute referring to an external Roku or RSS feed
-->
<category title="CANALES HD"
description="External RSS Feed Example"
sd_img="http://www.hidef.com.mx/wp-content/uploads/2008/11/hd_hdtv_logo.jpg"
feed="http://iptvservice311.890m.com/roku/otros/hd.xml">
</category>
<!--
A category can have subcategories with "feed" attributes referring to an external Roku or RSS feed
-->
<category title="TV en vivo" description="Canales de TV varios paises" sd_img="http://2.bp.blogspot.com/-AKayfNpk91w/TsmCFLsS1cI/AAAAAAAAAcw/m9uzrX4f72A/s1600/TV.jpg">
<category title="HD" description="Solo MEXICO" feed="11.890m.com/roku/otros/hd.xml" sd_img="http://www.hidef.com.mx/wp-content/uploads/2008/11/hd_hdtv_logo.jpg"></category>
<category title="Total Play" description="" feed="11.890m.com/roku/otros/mexico.rss" sd_img="http://www.gruposalinas.com/images/nv/Totalplay.png"></category>
<category title="España" description="" feed="http://feeds.feedburner.com/rokuArt" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Colombia" description="" feed="http://feeds.feedburner.com/rokuBusiness" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="USA" description="" feed="http://feeds.feedburner.com/rokuHealth" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Kids and Family" description="" feed="http://feeds.feedburner.com/rokuKidsAndFamily" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Music" description="" feed="http://feeds.feedburner.com/rokuMusic" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="News and Politics" description="" feed="http://feeds.feedburner.com/rokuNewsAndPolitics" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Science and Medicine" description="" feed="http://feeds.feedburner.com/rokuScienceAndMedicine" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Society and Culture" description="" feed="http://feeds.feedburner.com/rokuSocietyAndCulture" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
<category title="Technology" description="" feed="http://feeds.feedburner.com/rokuTechnology" sd_img="http://media.ted.com/images/ted/20891_160x160.gif"></category>
</category>
<!--
The same feeds as above, using categoryLeaf instead of category elements
-->
<category title="TED Talks" description="Category Leaves With External Feeds" sd_img="http://media.ted.com/images/ted/20891_160x160.gif">
<categoryLeaf title="Newest" description="" feed="http://feeds.feedburner.com/rokuNewest"></categoryLeaf>
<categoryLeaf title="Education" description="" feed="http://feeds.feedburner.com/rokuEducation"></categoryLeaf>
<categoryLeaf title="Art" description="" feed="http://feeds.feedburner.com/rokuArt"></categoryLeaf>
<categoryLeaf title="Business" description="" feed="http://feeds.feedburner.com/rokuBusiness"></categoryLeaf>
<categoryLeaf title="Health" description="" feed="http://feeds.feedburner.com/rokuHealth"></categoryLeaf>
<categoryLeaf title="Kids and Family" description="" feed="http://feeds.feedburner.com/rokuKidsAndFamily"></categoryLeaf>
<categoryLeaf title="Music" description="" feed="http://feeds.feedburner.com/rokuMusic"></categoryLeaf>
<categoryLeaf title="News and Politics" description="" feed="http://feeds.feedburner.com/rokuNewsAndPolitics"></categoryLeaf>
<categoryLeaf title="Science and Medicine" description="" feed="http://feeds.feedburner.com/rokuScienceAndMedicine"></categoryLeaf>
<categoryLeaf title="Society and Culture" description="" feed="http://feeds.feedburner.com/rokuSocietyAndCulture"></categoryLeaf>
<categoryLeaf title="Technology" description="" feed="http://feeds.feedburner.com/rokuTechnology"></categoryLeaf>
</category>
<!--
A category (or a root categories element) may have an in-line Roku feed
-->
<category title="Test HLS Feed" description="In-Line Roku Feed Example" sd_img="pkg:/images/mm_icon_focus_sd-248x140.png" hd_img="pkg:/images/mm_icon_focus_hd-366x210.png">
<feed title="HLS Test Feed" description="Testing 1, 2, 3" sd_img="pkg:/images/mm_icon_focus_sd-248x140.png" hd_img="pkg:/images/mm_icon_focus_hd-366x210.png">
<item>
<title>Testing HLS Feed</title>
<description>Just testing</description>
<streamFormat>hls</streamFormat>
<switchingStrategy>full-adaptation</switchingStrategy>
<media>
<streamFormat>hls</streamFormat> <!-- media streamFormat takes precedence over item streamFormat -->
<streamQuality>SD</streamQuality>
<streamBitrate>0</streamBitrate>
<streamUrl>http://content.jwplatform.com/manifests/vM7nH0Kl.m3u8</streamUrl>
</media>
</item>
<item>
<title>Test Item 2</title>
</item>
</feed>
</category>
</categories>
with ""category" " i get flat-category
https://sdkdocs.roku.com/download/attachments/1611500/worddav5cdc72f22e0a176f89cbcb7ad12debc8.png?ve...and with categoryLeaf i get DisplayCategoryGrid and flat-movie.
but i need to get need also posterscreen with (arced-portrait)
how can i do it my ui.brs is this
'********************************************************************
'
' NewVideoPlayer -- Example Multi-Level Roku Channel
'
' Copyright (c) 2015, belltown. All rights reserved. See LICENSE.txt
'
'********************************************************************
'
' To switch from using an roPosterScreen to an roGridScreen when displaying categories with leaves:
' Change uiDisplayCategoryWithLeaves () to uiDisplayCategoryGrid () in two places:
' uiDisplay () and uiDisplayCategoryWithoutLeaves ()
'
'
' Display the appropriate UI screen depending on the feed type
'
Function uiDisplay (contentItem As Object) As Void
If contentItem.xxFeedType = "category"
uiDisplayCategoryWithoutLeaves (contentItem)
' Pass in the <categories> or <category> containing <category> child elements
Else If contentItem.xxFeedType = "leaf"
uiDisplayCategoryGrid (contentItem.xxChildContentList, 0, contentItem.xxChildNamesList)
'uiDisplayCategoryGrid (contentItem.xxChildContentList, 0, contentItem.xxChildNamesList)
' Pass in the <category> containing the <categoryLeaf> child elements
Else If contentItem.xxFeedType = "feed"
' Read the feed if it is not already cached
If Not contentItem.xxIsCached
contentItem.xxChildContentList = parseXmlDocument (contentItem.xxFeedPath)
contentItem.xxIsCached = True
End If
uiDisplayCategoryWithoutLeaves (contentItem.xxChildContentList)
' Pass in the <feed> element
Else If contentItem.xxFeedType = "items"
uiDisplayCategoryWithoutLeaves (contentItem)
' Pass in the <feed> element containing the <item> child elements
Else
_debug ("uiDisplay. Invalid Feed Type: contentItem.xxFeedType")
End If
End Function
'
' A <category> element with child <category> elements is displayed as an roPosterScreen with no filter banner.
'
Function uiDisplayCategoryWithoutLeaves (contentItem As Object, breadLeft = "" As String, breadRight = "" As String) As Void
port = CreateObject ("roMessagePort")
ui = CreateObject ("roPosterScreen")
ui.SetMessagePort (port)
ui.SetCertificatesFile ("common:/certs/ca-bundle.crt") ' Allow "https" images
ui.InitClientCertificates ()
ui.SetBreadcrumbText (breadLeft, breadRight)
ui.SetListStyle ("flat-category") ' Use "flat-episodic" to display description beneath ShortDescriptionLine1/2
ui.SetContentList (contentItem.xxChildContentList) ' List of <item> or <category> or <categoryLeaf> elements
ui.Show ()
itemIndex = 0
ui.SetFocusedListItem (0)
While True
msg = Wait (0, port) : _logEvent ("uiDisplayCategoryWithoutLeaves", msg)
If msg <> Invalid
If Type (msg) = "roPosterScreenEvent"
If msg.IsScreenClosed ()
Exit While
Else If msg.IsListItemSelected ()
itemIndex = msg.GetIndex ()
selectedContentItem = contentItem.xxChildContentList [itemIndex]
' Selected item is a <category> node
If selectedContentItem.xxFeedType = "category"
uiDisplayCategoryWithoutLeaves (selectedContentItem, breadRight, selectedContentItem.Title)
' Selected item is <categoryLeaf> node
Else If selectedContentItem.xxFeedType = "leaf"
uiDisplayCategoryGrid (selectedContentItem, 0, breadRight, selectedContentItem.Title)
'uiDisplayCategoryGrid (selectedContentItem, 0, breadRight, selectedContentItem.Title)
' Selected item is a <feed> node
Else If selectedContentItem.xxFeedType = "feed"
If Not selectedContentItem.xxIsCached
selectedContentItem.xxChildContentList = parseXmlDocument (selectedContentItem.xxFeedPath) ' Read <feed> node
selectedContentItem.xxIsCached = True
End If
uiDisplayCategoryWithoutLeaves (selectedContentItem.xxChildContentList, breadRight, selectedContentItem.Title)
' Selected item is a content details item
Else
itemIndex = uiDisplayDetails (contentItem, itemIndex, breadRight, contentItem.Title) ' Pass in <feed> element
ui.SetFocusedListItem (itemIndex)
End If
End If
End If
End If
End While
End Function
'
' A lowest-level <category> element with child <categoryLeaf> elements is displayed as an roPosterScreen with a filter banner.
' To use an roGridScreen instead, change all calls to uiDisplayCategoryWithLeaves () to uiDisplayCategoryGrid ().
' The contentItem passed as a parameter contains xxChildContentList which is a list of content item lists, any one of which
' can be selected for display depending on which name in the names list is selected.
'
Function uiDisplayCategoryWithLeaves (contentItem As Object, nameIndex As Integer, breadLeft = "" As String, breadRight = "" As String) As Void
port = CreateObject ("roMessagePort")
ui = CreateObject ("roPosterScreen")
ui.SetMessagePort (port)
ui.SetCertificatesFile ("common:/certs/ca-bundle.crt") ' Allow "https" images
ui.InitClientCertificates ()
ui.SetBreadcrumbText (breadLeft, breadRight)
ui.SetListStyle ("flat-movie") ' Use "flat-episodic" to display description beneath ShortDescriptionLine1/2
ui.SetListNames (contentItem.xxChildNamesList)
'
' Read in the focused content item if it is not yet cached
'
feedContentItem = contentItem.xxChildContentList [nameIndex] ' <feed> node for content list to display
If Not feedContentItem.xxIsCached
contentItem.xxChildContentList [nameIndex] = parseXmlDocument (feedContentItem.xxFeedPath) ' Read <feed> node
feedContentItem = contentItem.xxChildContentList [nameIndex]
feedContentItem.xxIsCached = True
End If
ui.SetContentList (feedContentItem.xxChildContentList)
itemIndex = 0 ' Always set initial focus to first item
ui.SetFocusedListItem (itemIndex)
ui.Show ()
focusTimer = CreateObject ("roTimespan") ' Prevent retrieving feeds if scrolling rapidly through category list names
focusTimerRunning = False
listIndex = 0
'
' When the user is scrolling through the list names looking for a particular list,
' avoid loading the content list for each list name that is scrolled over.
' This is achieved by using a short timer that is started when the user starts scrolling through name lists.
' If the user stops scrolling for at least 750ms, then load the content list for the currently focused list name.
' TODO: Implement similar logic for Grid Screen.
'
While True
msg = Wait (10, port) : If msg <> Invalid Then _logEvent ("uiDisplayCategoryWithLeaves", msg)
If (Type (msg) = "Invalid" And focusTimerRunning And focusTimer.TotalMilliseconds () > 750) Or (Type (msg) = "roPosterScreenEvent" And msg.IsListSelected () And msg.GetIndex () <> listIndex)
focusTimerRunning = False
ui.SetFocusedListItem (0)
nameIndex = listIndex
itemIndex = 0 ' New list focused, so select the first list item
ui.SetFocusedListItem (itemIndex)
feedContentItem = contentItem.xxChildContentList [nameIndex]
If Not feedContentItem.xxIsCached
contentItem.xxChildContentList [nameIndex] = parseXmlDocument (feedContentItem.xxFeedPath)
feedContentItem = contentItem.xxChildContentList [nameIndex]
feedContentItem.xxIsCached = True
End If
ui.SetContentList (feedContentItem.xxChildContentList)
ui.ClearMessage ()
Else If Type (msg) = "roPosterScreenEvent"
If msg.IsScreenClosed ()
Exit While
'
' When a new list takes focus, don't display it right away, in case the user is rapidly scrolling though lists.
' Instead, start a timer and display the list when the timer expires.
'
Else If msg.IsListFocused ()
ui.SetContentList ([])
ui.ShowMessage ("Cargando....")
' Keep track of which item was focused on
listIndex = msg.GetIndex ()
' If focus timer is running then stop it, else start a new timer
focusTimerRunning = True
focusTimer.Mark ()
Else If msg.IsListItemSelected ()
ui.ClearMessage ()
itemIndex = msg.GetIndex ()
itemIndex = uiDisplayDetails (contentItem.xxChildContentList [nameIndex], itemIndex, breadRight, contentItem.xxChildNamesList [nameIndex])
ui.SetFocusedListItem (itemIndex)
End If
End If
End While
End Function
'
' Example code when using an roGridScreen instead of an roPosterScreen to display a category with leaves.
' To use this function, replace all calls to uiDisplayCategoryWithLeaves () with calls to uiDisplayCategoryGrid ().
'
Function uiDisplayCategoryGrid (contentItem As Object, nameIndex As Integer, breadLeft = "" As String, breadRight = "" As String) As Void
port = CreateObject ("roMessagePort")
ui = CreateObject ("roGridScreen")
ui.SetMessagePort (port)
ui.SetCertificatesFile ("common:/certs/ca-bundle.crt") ' Allow "https" images
ui.InitClientCertificates ()
ui.SetDisplayMode ("scale-to-fill") ' Fit image entirely within the bounding box - dimensions may appear distorted
'ui.SetDisplayMode ("scale-to-fit") ' Use this if the image dimensions appear too distorted with "scale-to-fill"
ui.SetGridStyle ("flat-movie") ' See the Component Reference for roGridScreen for all the styles available
'ui.SetGridStyle ("flat-square")
ui.SetupLists (contentItem.xxChildContentList.Count ())
ui.SetListNames (contentItem.xxChildNamesList)
ui.SetBreadcrumbText (breadLeft, breadRight)
If _getRokuVersion ().IsLegacy
ui.SetUpBehaviorAtTopRow ("exit") ' Only way back from the grid screen on legacy firmware
Else
ui.SetUpBehaviorAtTopRow ("stop") ' Use default behavior for post-legacy firmware
End If
' Read in the first content item if it is not yet cached
feedContentItem = contentItem.xxChildContentList [nameIndex] ' <feed> node for content list to display
If Not feedContentItem.xxIsCached
contentItem.xxChildContentList [nameIndex] = parseXmlDocument (feedContentItem.xxFeedPath) ' Read <feed> node
feedContentItem = contentItem.xxChildContentList [nameIndex]
feedContentItem.xxIsCached = True
End If
' Display the first content row
ui.SetContentList (nameIndex, contentItem.xxChildContentList [nameIndex].xxChildContentList)
' Display the next content row
nextIndex = nameIndex + 1
If nextIndex >= contentItem.xxChildContentList.Count ()
nextIndex = nameIndex
End If
If nextIndex <> nameIndex
nextContentItem = contentItem.xxChildContentList [nextIndex]
If Not nextContentItem.xxIsCached
contentItem.xxChildContentList [nextIndex] = parseXmlDocument (nextContentItem.xxFeedPath) ' Read <feed> node
nextContentItem = contentItem.xxChildContentList [nextIndex]
nextContentItem.xxIsCached = True
End If
ui.SetContentList (nextIndex, nextContentItem.xxChildContentList)
End If
ui.SetFocusedListItem (nameIndex, 2) ' Cursor starts in the middle of the row (corresponds to the third item; index = 2)
ui.Show ()
While True
msg = Wait (0, port) : _logEvent ("uiDisplayCategoryGrid", msg)
If msg <> Invalid
If Type (msg) = "roGridScreenEvent"
If msg.IsScreenClosed ()
Exit While
Else If msg.IsListItemFocused ()
nameIndex = msg.GetIndex ()
itemIndex = msg.GetData ()
' Get the feed data for the focused content row
feedContentItem = contentItem.xxChildContentList [nameIndex]
' Read the focused content row if it is not already cached
If Not feedContentItem.xxIsCached
contentItem.xxChildContentList [nameIndex] = parseXmlDocument (feedContentItem.xxFeedPath)
feedContentItem = contentItem.xxChildContentList [nameIndex]
feedContentItem.xxIsCached = True
End If
' Display the focused content row
ui.SetContentList (nameIndex, feedContentItem.xxChildContentList)
' Display the next content row
nextIndex = nameIndex + 1
If nextIndex >= contentItem.xxChildContentList.Count ()
nextIndex = nameIndex
End If
If nextIndex <> nameIndex
nextContentItem = contentItem.xxChildContentList [nextIndex]
If Not nextContentItem.xxIsCached
contentItem.xxChildContentList [nextIndex] = parseXmlDocument (nextContentItem.xxFeedPath) ' Read <feed> node
nextContentItem = contentItem.xxChildContentList [nextIndex]
nextContentItem.xxIsCached = True
End If
ui.SetContentList (nextIndex, nextContentItem.xxChildContentList)
End If
' Display the details screen for the selected item
Else If msg.IsListItemSelected ()
nameIndex = msg.GetIndex ()
itemIndex = msg.GetData ()
itemIndex = uiDisplayDetails (contentItem.xxChildContentList [nameIndex], itemIndex, breadRight, contentItem.xxChildNamesList [nameIndex])
ui.SetFocusedListItem (nameIndex, itemIndex)
End If
End If
End If
End While
End Function
'
' Display the appropriate details screen depending on the feed content type.
' The feedContentItem parameter corresponds to a single <feed> element node, whose xxFeedContentType indicates the media content type, "video", "audio", etc.
' Current only supports "video" content.
' The feed item's xxChildContentList corresponds to the content list of <item> elements displayed by the details screen.
' The index parameter indicates which particular <item> is to be displayed initially. The return index value indicates the last <item> that was displayed before returning.
'
Function uiDisplayDetails (feedContentItem As Object, index As Integer, breadLeft = "" As String, breadRight = "" As String) As Integer
If feedContentItem.xxFeedContentType = "video"
index = uiDisplayVideoDetails (feedContentItem.xxChildContentList, index, breadLeft, breadRight)
Else
uiSoftError ("uiDisplayDetails", LINE_NUM, "Unsupported Content Type: " + feedContentItem.xxFeedContentType)
End If
Return index
End Function
'
' The video details screen is displayed as an roSpringboardScreen
'
Function uiDisplayVideoDetails (contentList As Object, index As Integer, breadLeft = "" As String, breadRight = "" As String) As Integer
port = CreateObject ("roMessagePort")
ui = CreateObject ("roSpringboardScreen")
ui.SetMessagePort (port)
ui.SetCertificatesFile ("common:/certs/ca-bundle.crt")
ui.InitClientCertificates ()
ui.SetDisplayMode ("scale-to-fill")
ui.SetDescriptionStyle ("movie") ' All tags on the video screen are substituted with Content Meta-Data
ui.SetBreadcrumbText (breadLeft, breadRight)
uiDisplayVideoDetailsSetContent (ui, contentList, index)
ui.Show ()
While True
msg = Wait (0, port) : _logEvent ("uiDisplayVideoDetails", msg)
If msg <> Invalid
If msg.IsScreenClosed ()
Exit While
Else If msg.IsButtonPressed ()
buttonId = msg.GetIndex ()
' Only attempt to play the video if there is at least one media stream
streams = contentList [index].LookupCI ("Streams")
If streams <> Invalid And streams.Count () > 0
' Display a blank facade to avoid flashing back to the roSpringboardScreen between videos
facade = CreateObject ("roImageCanvas")
facade.SetLayer (0, {Color: "#FF000000"})
facade.Show ()
' Play the video
If buttonId = 0 ' Play
uiPlayVideo (contentList, index)
uiDisplayVideoDetailsSetContent (ui, contentList, index) ' Add/remove Resume button
Else If buttonId = 1 ' Play all
' Play each video from the current position
While index < contentList.Count ()
' Only play the next video if it has at least one media stream
streams = contentList [index].LookupCI ("Streams")
If streams <> Invalid And streams.Count () > 0
' Play the next video
If Not uiPlayVideo (contentList, index)
' Either the user exited the video screen with the Back button,
' or there was an error during video playback
Exit While
End If
End If
' Select next video
index = index + 1
If index < contentList.Count ()
uiDisplayVideoDetailsSetContent (ui, contentList, index)
Else
' After Play All finishes, stay on the last video
index = contentList.Count () - 1
Exit While
End If
End While
uiDisplayVideoDetailsSetContent (ui, contentList, index) ' Add/remove Resume button
Else If buttonId = 2 ' Resume
uiPlayVideo (contentList, index)
uiDisplayVideoDetailsSetContent (ui, contentList, index) ' Add/remove Resume button
Else If buttonId = 3 ' Play from beginning
REM _setBookmark (contentList [index].ContentId, 0)
' Don't store bookmarks with a zero value; delete until a position notification is received
If Not contentList [index].Live
_clearBookmark (contentList [index].ContentId)
contentList [index].Delete ("playstart") ' Don't need PlayStart in the content list any more
End If
uiPlayVideo (contentList, index)
uiDisplayVideoDetailsSetContent (ui, contentList, index) ' Add/remove Resume button
End If
facade.Close ()
Else
uiSoftError ("uiDisplayVideoDetails", LINE_NUM, "No media streams found for this item")
uiDisplayVideoDetailsSetContent (ui, contentList, index)
End If
Else If msg.IsRemoteKeyPressed ()
key = msg.GetIndex ()
If key = 4 ' Left - no wraparound
If index > 0
index = index - 1
uiDisplayVideoDetailsSetContent (ui, contentList, index)
End If
Else If key = 5 ' Right - no wraparound
If index < contentList.Count () - 1
index = index + 1
uiDisplayVideoDetailsSetContent (ui, contentList, index)
End If
End If
End If
End If
End While
Return index
End Function
'
' Set or replace the current details screen's content.
' Called when a details screen for an <item> is initially displayed,
' or when navigating laterally through <item> elements on the roSpringboardScreen.
'
Function uiDisplayVideoDetailsSetContent (ui As Object, contentList As Object, index As Integer) As Void
ui.AllowUpdates (False)
ui.ClearButtons ()
If contentList [index].Live Or _getBookmark (contentList [index].ContentId) < 10
ui.AddButton (0, "Play")
If contentList.Count () > 1 Then ui.AddButton (1, "Play all")
Else
ui.AddButton (2, "Resume")
ui.AddButton (3, "Play from beginning")
If contentList.Count () > 1 Then ui.AddButton (1, "Play all")
End If
ui.AllowNavLeft (contentList.Count () > 1)
ui.AllowNavRight (contentList.Count () > 1)
ui.SetStaticRatingEnabled (contentList [index].StarRating <> Invalid) ' Don't display stars if none in content list
ui.SetContent (contentList [index])
ui.AllowUpdates (True)
End Function
'
' The selected video content is played using an roVideoScreen
'
Function uiPlayVideo (contentList As Object, index As Integer) As Boolean
' Return True if and only if playback completed normally (end of video reached).
' Allows 'Play All' functionality to determine whether it's okay to play the next video.
normalCompletion = False
' Keep track of how long video has been playing, for retry logic
playTimer = CreateObject ("roTimespan")
' Count number of retry attempts following playback failure
MAX_RETRIES = 3
numRetries = 0
' Make sure we have a valid content index
If index >= 0 And index < contentList.Count ()
done = False ' Set to True when finished or retry limit reached
' Keep retrying failed playback attempts
While Not done
' Don't retry unless a failed playback occurs
done = True
' Set up a new screen object for each retry
port = CreateObject ("roMessagePort")
ui = CreateObject ("roVideoScreen")
ui.SetMessagePort (port)
ui.SetCertificatesFile ("common:/certs/ca-bundle.crt")
ui.InitClientCertificates ()
' Don't attempt to bookmark live content
If Not contentList [index].Live
ui.SetPositionNotificationPeriod (10)
' Set PlayStart to the currently-bookmarked position.
' Not need to set unless we're at least 10 seconds into the video.
playStart = _getBookmark (contentList [index].ContentId)
If playStart >= 10
contentList [index].PlayStart = playStart
End If
End If
' Disable Fast-Forward and Rewind for live videos
If contentList [index].Live
ui.SetPreviewMode (True)
End If
statusMessage = "" ' Keep track of last status message received
ui.SetContent (contentList [index])
ui.Show ()
While True
msg = Wait (0, port) : _logEvent ("uiPlayVideo", msg)
If msg <> Invalid
' The screen is being closed
If msg.IsScreenClosed ()
Exit While
' Keep track of the playback position
Else If msg.IsPlaybackPosition ()
' Don't start bookmarking until we're at least 10 seconds into the video
If Not contentList [index].Live And msg.GetIndex () >= 10
_setBookmark (contentList [index].ContentId, msg.GetIndex ())
End If
' If the stream started then reset the play timer
Else If msg.IsStreamStarted ()
playTimer.Mark ()
' Playback completed normally. Roku will close the screen after sending an IsScreenClosed event.
' Ensures that if Play All is in use, the next video can be played.
Else If msg.IsFullResult ()
normalCompletion = True
If Not contentList [index].Live
_clearBookmark (contentList [index].ContentId)
contentList [index].Delete ("playstart") ' Don't need PlayStart in the content list any more
End If
' Store status message to display if a request-failed message occurs
Else If msg.IsStatusMessage ()
statusMessage = msg.GetMessage ()
' Video playback failed
Else If msg.IsRequestFailed ()
failIndex = msg.GetIndex ()
message = msg.GetMessage ()
failMessage = ""
unsupportedMessage = ""
' Roku firmware doesn't appear to return a message for a request failed event,
' so use the preceding status message instead.
If message = ""
message = statusMessage
End If
' If a video has been playing for a while, reset the retry count
If playTimer.TotalSeconds () > 300
numRetries = 0
playTimer.Mark ()
End If
numRetries = numRetries + 1
If numRetries > MAX_RETRIES Or failIndex = -4 ' Don't retry if no video streams
' Roku firmware only returns a number for a failure; translate to a message to display to the user
If failIndex >= -5 And failIndex <= 0
failMessage = [ "Network error : server down or unresponsive, server is unreachable, network setup problem on the client.",
"HTTP error: malformed headers or HTTP error result.",
"Connection timed out.",
"Unknown error.",
"Empty list; no streams were specified to play.",
"Media error; the media format is unknown or unsupported." ][-failIndex]
If failIndex = -4 Or failIndex = -5
unsupportedMessage = "Possibly the feed has no Roku-compatible video content."
End If
Else
failMessage = "Unknown failure code: " + failIndex.ToStr ()
End If
' Debugging info - list the streams for this content item
For i = 0 To contentList [index].Streams.Count () - 1
stream = contentList [index].Streams [i]
_debug ("uiPlayVideo. Stream[" + i.ToStr () + "]. Url: " + stream.Url)
End For
uiDisplayMessage ("Video Playback Failed", [failMessage, message, unsupportedMessage])
Else
' Retry the failed video
_debug ("uiPlayVideo. Retry Attempt #" + numRetries.ToStr ())
uiDisplayCanvasMessage ("Video Playback Failed. " + Chr (10) + Chr (10) + "Retrying ....", 3000)
done = False
End If
' Close the screen, exiting the loop when the IsScreenClosed event is received
ui.Close ()
End If
End If
End While
End While
End If
Return normalCompletion
End Function
'
' Display an message on an image canvas.
' Keep message displayed until the timeout expires or the user presses a key.
'
Function uiDisplayCanvasMessage (message As String, timeout = 0 As Integer) As Void
port = CreateObject ("roMessagePort")
ui = CreateObject ("roImageCanvas")
ui.SetMessagePort (port)
ui.SetLayer (0, {Color: "#FF101010"})
ui.SetLayer (1, {Text: message, TextAttrs: {Color: "#FFEBEBEB", Font: "Large", HAlign: "HCenter", VAlign: "VCenter"}})
ui.Show ()
msg = Wait (timeout, port) : _logEvent ("uiDisplayCanvasMessage", msg)
ui.Close ()
End Function
'
' Display a message dialog. textList is an array of Strings, each one being a single line of text to display
'
Function uiDisplayMessage (title As String, textList As Object) As Void
port = CreateObject ("roMessagePort")
ui = CreateObject ("roMessageDialog")
ui.SetMessagePort (port)
ui.SetTitle (title)
For Each textItem In textList
ui.SetText (textItem)
End For
ui.AddButton (1, "OK")
ui.EnableBackButton (True)
ui.Show ()
While True
msg = Wait (0, port) : _logEvent ("uiDisplayMessage", msg)
If msg <> Invalid
If Type (msg) = "roMessageDialogEvent"
If msg.IsScreenClosed ()
Exit While
Else If msg.IsButtonPressed ()
ui.Close ()
End If
End If
End If
End While
End Function
'
' Display a message for a recoverable error
'
Function uiSoftError (functionString As String, lineNumber As Integer, errorString As String) As Void
msg = "Soft error in " + functionString + " on line #" + lineNumber.ToStr ()
_debug ("uiSoftError. " + msg + ". " + errorString)
uiDisplayMessage ("Error", [errorString])
End Function
'
' Display an error message then terminate the channel if an unrecoverable error occurs
'
Function uiFatalError (functionString As String, lineNumber As Integer, errorString As String) As Void
msg = "Fatal error in " + functionString + " on line #" + lineNumber.ToStr ()
_debug ("uiFatalError. " + msg + ". " + errorString)
uiDisplayMessage ("Fatal Error", [msg, errorString])
Stop
End Function