Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
pudewinbond
Visitor

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