Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
pudewinbond
Level 7

roPosterScreen with roku new video player

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


0 Kudos