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: 
dcringo
Visitor

Escaping from a Play All loop

I have pieced together some ideas I found in this forum, plus some stuff I made up myself, to make a "Play All Videos" option from my video details screen.

It works great, and even loops back to the first video once the last one in the playlist is played. The issue is that if I hit the "back" button to stop the video, it would just start the video over again. I fixed it to send me back out to my app home screen as a work-around, but that doesn't work either because my "stack" still has the videoplayer screen in it still in the loop.

What I would like to have happen is if I hit the back button, I would like for the video to stop, the video details screen of the current video to show (or even the video that we played to start the loop). I would even be happy if it would just take me back to the home screen and clear the stack. Is there some easy way to clear the stack? Here is some of the code.

This code is called when someone selects "Play all videos" (showVideoPlayerScreenAll()) from any video details screen in the playlist. An array (items) is passed in as the playlist. The index of the selected choice (passIndex) is passed in. The actual video itself and all of its parameters are being passed in (video) and is actually an associative array containing the name, id, caption and all sorts of other info about the video that is pulled and filtered from JSON at a vendor's API.

After the first video is complete, getNewVidInfo runs increments the passIndex and sets up the new video. It passes the initial items array, the new passIndex and the new video into playAllVids which sets the screen name and play start and then calles the main showVideoPlayerAll function again, completing the first iteration of the overall loop.

I am open to any suggestions on this.

Function getNewVidInfo (items, passIndex)

passIndex = passIndex + 1

if (passIndex = items.count())
passIndex = 0
end if

index = passIndex

feedUrl = "/asset?id=" + tostr(items[index].ContentId) + "&fields=hls_url,closed_caption_urls,rating,duration,time_start,date,trick_mode_urls"
conn = InitFeedConnection(feedUrl)
response = conn.LoadFeed()
if response = invalid
return -1
end if
print "the contentID in question is " items[index].contentId
video = convertDvidsApiAssetResponse(response,items[index])

playAllVids(items, passIndex, video)

End Function



Function playAllVids(items, passIndex, video)

while true

screenName = "asset_watch/" + right(video.ContentId,6)
analyticsTrackScreenview(screenName)

video.PlayStart = video.TimeStart
showVideoPlayerScreenAll(items, passIndex, video)

end while


End Function


Function showVideoPlayerScreenAll(items, passIndex, video As Object, pageTitle = invalid, parentPageTitle = invalid) As Integer
print "we are on video screen and items are " items
print "we are on video screen and index is " passIndex
if type(video) <> "roAssociativeArray" then
print "invalid data passed to showVideoPlayerScreen"
return -1
endif

'print video

port = CreateObject("roMessagePort")
screen = CreateObject("roVideoScreen")
screen.setMessagePort(port)

if(video.ContentId <> invalid)
PlayStartVariableName = right(video.ContentId,6)+"pos" ' remove video- from contentid
screen.SetPositionNotificationPeriod(5)
endif
screenName = "asset_watch/" + right(video.ContentId,6)
screen.SetContent(video)
setBreadCrumbs(screen, pageTitle, parentPageTitle)
screen.Show()

while true
event = wait(0, port)

if type(event) = "roVideoScreenEvent" then
'if event.getmessage()="Playback interrupted by user." then
'print "playback interrupted by user"
'showHomeScreen()
'end if
if event.isScreenClosed()
print "Screen closed by user"
showHomeScreen()
'return -1
else if event.isFullResult()
print "video finished"

if(RegRead(PlayStartVariableName) <> invalid)
RegDelete(PlayStartVariableName)
end if

getNewVidInfo(items, passIndex)
'return 0
'print "showHomeScreen | event = "; event.getMessage() " | index = "; event.GetIndex()
'else if event.isScreenClosed()
'print "Screen closed by user"
'showHomeScreen()
'return -1
else if event.isRequestFailed()
'print "Video request failure: "; event.GetIndex(); " " event.GetData()
else if event.isStatusMessage()
'print "Video status: "; event.GetIndex(); " " event.GetData()
else if event.isButtonPressed()
'print "Button pressed: "; event.GetIndex(); " " event.GetData()
else if event.isPlaybackPosition() then
currentPosition = event.GetIndex()
' If we're less than 10 seconds from the end of the video go ahead and delete the position tracker
if(currentPosition + 10 > video.length and RegRead(PlayStartVariableName) <> invalid)
RegDelete(PlayStartVariableName)
else
'print "CurrentPosition";currentPosition
RegWrite(PlayStartVariableName, currentPosition.toStr())
end if
end if
end if
end while

End Function
0 Kudos
6 REPLIES 6
dcringo
Visitor

Re: Escaping from a Play All loop

***UPDATE***

Apparently what was happening is that when I hit the "back" button during a video after the first video, "back" was not sending me back a PAGE, rather it was sending me back by one FUNCTION. The function it was sending me back to was the "playAllVids" function, which then immediately ran the showVideoPlayerScreenAll function again... setting up a vicious cycle.

I have taken all of the code from both functions and placed it in the conditional statement that happens if event.isFullResult.

Now, the back button does take me back to the detail screen of the video i started with, which is desirable, but for some reason I have to hit "back" twice to get it to work. I could even live with that, but I worry that it is an indication of some other problem that I can't see at the moment. Here is the new code.

Function showVideoPlayerScreenAll(items, passIndex, video As Object, pageTitle = invalid, parentPageTitle = invalid) As Integer
print "we are on video screen and items are " items
print "we are on video screen and index is " passIndex
if type(video) <> "roAssociativeArray" then
print "invalid data passed to showVideoPlayerScreen"
return -1
endif

'print video

port = CreateObject("roMessagePort")
screen = CreateObject("roVideoScreen")
screen.setMessagePort(port)

if(video.ContentId <> invalid)
PlayStartVariableName = right(video.ContentId,6)+"pos" ' remove video- from contentid
screen.SetPositionNotificationPeriod(5)
endif
screenName = "asset_watch/" + right(video.ContentId,6)
screen.SetContent(video)
setBreadCrumbs(screen, pageTitle, parentPageTitle)
screen.Show()

while true
event = wait(0, port)

if type(event) = "roVideoScreenEvent" then
if event.getmessage()="Playback interrupted by user." then
'index = passIndex

return -1
end if
if event.isFullResult()
print "video finished"

if(RegRead(PlayStartVariableName) <> invalid)
RegDelete(PlayStartVariableName)
end if

passIndex = passIndex + 1

if (passIndex = items.count())
passIndex = 0
end if

index = passIndex

feedUrl = "/asset?id=" + tostr(items[index].ContentId) + "&fields=hls_url,closed_caption_urls,rating,duration,time_start,date,trick_mode_urls"
conn = InitFeedConnection(feedUrl)
response = conn.LoadFeed()
if response = invalid
return -1
end if
print "the contentID in question is " items[index].contentId
video = convertDvidsApiAssetResponse(response,items[index])

video.PlayStart = video.TimeStart
showVideoPlayerScreenAll(items, passIndex, video)

'getNewVidInfo(items, passIndex)
'return 0
print "showHomeScreen | event = "; event.getMessage() " | index = "; event.GetIndex()
else if event.isScreenClosed()
'print "Screen closed"
return -1
else if event.isRequestFailed()
'print "Video request failure: "; event.GetIndex(); " " event.GetData()
else if event.isStatusMessage()
'print "Video status: "; event.GetIndex(); " " event.GetData()
else if event.isButtonPressed()
'print "Button pressed: "; event.GetIndex(); " " event.GetData()
else if event.isPlaybackPosition() then
currentPosition = event.GetIndex()
' If we're less than 10 seconds from the end of the video go ahead and delete the position tracker
if(currentPosition + 10 > video.length and RegRead(PlayStartVariableName) <> invalid)
RegDelete(PlayStartVariableName)
else
'print "CurrentPosition";currentPosition
RegWrite(PlayStartVariableName, currentPosition.toStr())
end if
end if
end if
end while

End Function
0 Kudos
dcringo
Visitor

Re: Escaping from a Play All loop

I am still struggling to find an answer to why I have to hit the Back button twice to escape the loop.

Additionally, most of the time the playlist will play all eleven current videos fine and then start over at the beginning just fine. Occasionally, after 8-10 videos, it will have a connection issue. I assume this is related to my internet connectivity.

I am retrieving JSON from a web API to get all of my video data. My occasional error is happening when the JSON returns INVALID, triggering the error I get. Any ideas why JSON would be returned INVALID at random and only occasionally? (Besides some web connectivity issue)

I have a lot of stuff being logged in the console while I am testing. Is there any way that having a lot of console logging can disrupt functionality?
0 Kudos
sjb64
Roku Guru

Re: Escaping from a Play All loop

I log a lot to the console, especially during channel launch and have never had a problem with it interfering, unless I dump details during large loops (thousands of iterations), the system still works but it does have a performance impact then. The Roku Ad Framework also logs a tremendous amount of data to the console with no noticeable ill affects.

One thing I have done is created a variable (m.dev) that I set if its in development and then surround my trace (meaning write to console) calls in a if (m.dev) ... end if block. On some complex calls it could make a difference for end users.

As far as a JSON question, that does sound to me like a failed webcall returning invalid, but I'm only guessing. I'd put some traceng on your urURLTransfer calls.
0 Kudos
dcringo
Visitor

Re: Escaping from a Play All loop

"sjb64" wrote:
As far as a JSON question, that does sound to me like a failed webcall returning invalid, but I'm only guessing. I'd put some traceng on your urURLTransfer calls.



I would love to do this. Could someone give me a little help with the syntax and location for this in my example code?
0 Kudos
sjb64
Roku Guru

Re: Escaping from a Play All loop

"dcringo" wrote:
Could someone give me a little help with the syntax and location for this in my example code?

My assumption is it's in conn.InitFeedConnection / conn.LoadFeed but I don't see those routines in the listings, just the calls.
0 Kudos
dcringo
Visitor

Re: Escaping from a Play All loop

"sjb64" wrote:

My assumption is it's in conn.InitFeedConnection / conn.LoadFeed but I don't see those routines in the listings, just the calls.



Thanks for the help. I used the trace to figure out the problem was NOT related to connectivity, and I dug deeper. As it turns out, I had unintentionally set a limit on the number of videos allowed in the playlist, although the real array of videos was much longer, so while cycling the full array, it ran out of available results.

That problem cant been seen in the code I posted as it was happening elsewhere.

BUT, a close look at the last code I had posted will reveal a very rookie mistake. My function has a call to itself inside, meaning it is recursive. I have gone back to scratch for now on how to handle it, or something closer to my first code, but I can't figure out how to get one function to tell the other that the back button was pressed. I posted the question in the original thread where I got the base code for this. viewtopic.php?f=34&t=73760
0 Kudos