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: 
renojim
Community Streaming Expert

Re: roUniversalControlEvent - Pause/Play functions

You appear to have multiple variables referring to whether or not the video is paused:
m.paused
m.player.paused
this.paused

You really need to clean this up. I doubt there's any reason to have anything other than a variable just called paused.

-JT
Roku Community Streaming Expert

Help others find this answer and click "Accept as Solution."
If you appreciate my answer, maybe give me a Kudo.

I am not a Roku employee.
0 Kudos
Transparent
Visitor

Re: roUniversalControlEvent - Pause/Play functions

"renojim" wrote:
You appear to have multiple variables referring to whether or not the video is paused:
m.paused
m.player.paused
this.paused

You really need to clean this up. I doubt there's any reason to have anything other than a variable just called paused.

-JT


Hi Jim,
That code is actually from CustomVideoPlayer, supplied by Roku https://sourceforge.net/projects/rokusdkexamples/files/
0 Kudos
belltown
Roku Guru

Re: roUniversalControlEvent - Pause/Play functions

"Transparent" wrote:
"renojim" wrote:
You appear to have multiple variables referring to whether or not the video is paused:
m.paused
m.player.paused
this.paused

You really need to clean this up. I doubt there's any reason to have anything other than a variable just called paused.

-JT


Hi Jim,
That code is actually from CustomVideoPlayer, supplied by Roku https://sourceforge.net/projects/rokusdkexamples/files/

The Custom Video Player SDK example you linked to works just fine (if you use a working stream url). So if your code doesn't handle play/pause, you must have changed something that introduced the error. I suggest you look at what you've changed, perhaps even go back to the original code, substitute your own Stream url, make sure the StreamFormat is correct, e.g. "ism", and it should work.

I also noticed that the code you posted is not the same code as that in the Custom Video Player example. For instance, there's no use of m.player.paused in the SDK example.
0 Kudos
Transparent
Visitor

Re: roUniversalControlEvent - Pause/Play functions

The Custom Video Player SDK example you linked to works just fine (if you use a working stream url). So if your code doesn't handle play/pause, you must have changed something that introduced the error. I suggest you look at what you've changed, perhaps even go back to the original code, substitute your own Stream url, make sure the StreamFormat is correct, e.g. "ism", and it should work.

I also noticed that the code you posted is not the same code as that in the Custom Video Player example. For instance, there's no use of m.player.paused in the SDK example.



I can't even run CustomVideoPlayer as an error pops up on the line 'Sub Setup() As Object', I prob have to add something, so I havn't really seen it in action.

The pause works in that? Did you Pause it through the terminal like the command i've above, if not, can you please and tell me if it works? I don't want to have the stream url used inside the program, I want to be able to send it to the channel remotely, I guess the issue I have it trying to integrate the Pausing/Playing code in CVP into my own app

Sorry Yeah you're right (sorry Jim), m.player.paused is not in the custom video player but m.paused is, I guess I was just playing around with it trying to get it to work.
0 Kudos
belltown
Roku Guru

Re: roUniversalControlEvent - Pause/Play functions

Here's what I did:

1. Download customvideoplayer.zip from: https://sourceforge.net/projects/rokusdkexamples/files/customvideoplayer.zip/download
2. Un-zip customvideoplayer.zip into a new folder, customvideoplayer
3. Remove the read-only attribute recursively from the new folder, its subfolders, and files (at least on Windows, not sure about other systems, the SDK examples are unzipped by default into a read-only folder, which must be changed in order to edit the contents)
4. Edit customvideoplayer/source/main.brs
5. Change the SetContentList statement in Sub Setup() to:
    this.player.SetContentList([{
REM Stream: { url: "http://ec2-184-72-239-149.compute-1.amazonaws.com:1935/demos/smil:bigbuckbunnyiphone.smil/playlist.m3u8" }
Stream: { url: "http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest" }
REM StreamFormat: "hls"
StreamFormat: "ism"
REM SwitchingStrategy: "full-adaptation"
}])

6. Zip and deploy the channel to my Roku
7. Play/pause successfully using both the Roku remote and the following curl command:
curl -d '' http://192.168.0.6:8060/keypress/Play

8. As an added bonus, modified the code to specify the url using ECP
9. Launched and played the video successfully using the following curl command:
curl -d '' http://192.168.0.6:8060/launch/dev?url=http%3A%2F%2Fplayready.directtaps.net%2Fsmoothstreaming%2FSSWSS720H264%2FSuperSpeedway_720.ism%2FManifest


Here's the final version of the code.

' ********************************************************************
' ********************************************************************
' ** Roku Custom Video Player Channel (BrightScript)
' **
' ** May 2010
' ** Copyright (c) 2010 Roku Inc. All Rights Reserved.
' ********************************************************************
' ********************************************************************

Sub RunUserInterface(params As Object)
Print "Launch url: "; params.url
o = Setup(params.url)
o.setup()
o.paint()
o.eventloop()
End Sub

Sub Setup(launchUrl As String) As Object
this = {
port: CreateObject("roMessagePort")
progress: 0 'buffering progress
position: 0 'playback position (in seconds)
paused: false 'is the video currently paused?
fonts: CreateObject("roFontRegistry") 'global font registry
canvas: CreateObject("roImageCanvas") 'user interface
player: CreateObject("roVideoPlayer")
setup: SetupFramedCanvas
paint: PaintFramedCanvas
eventloop: EventLoop
}

'Static help text:
this.help = "Press the right or left arrow buttons on the remote control "
this.help = this.help + "to seek forward or back through the video at "
this.help = this.help + "approximately one minute intervals. Press down "
this.help = this.help + "to toggle fullscreen. To exit the sample, press "
this.help = this.help + "the remote control Home key."

'Register available fonts:
this.fonts.Register("pkg:/fonts/caps.otf")
this.textcolor = "#406040"

'Setup image canvas:
this.canvas.SetMessagePort(this.port)
this.canvas.SetLayer(0, { Color: "#000000" })
this.canvas.Show()

'Resolution-specific settings:
mode = CreateObject("roDeviceInfo").GetDisplayMode()
if mode = "720p"
this.layout = {
full: this.canvas.GetCanvasRect()
top: { x: 0, y: 0, w:1280, h: 130 }
left: { x: 249, y: 177, w: 391, h: 291 }
right: { x: 700, y: 177, w: 350, h: 291 }
bottom: { x: 249, y: 500, w: 780, h: 300 }
}
this.background = "pkg:/images/back-hd.jpg"
this.headerfont = this.fonts.get("lmroman10 caps", 50, 50, false)
else
this.layout = {
full: this.canvas.GetCanvasRect()
top: { x: 0, y: 0, w: 720, h: 80 }
left: { x: 100, y: 100, w: 280, h: 210 }
right: { x: 400, y: 100, w: 220, h: 210 }
bottom: { x: 100, y: 340, w: 520, h: 140 }
}
this.background = "pkg:/images/back-sd.jpg"
this.headerfont = this.fonts.get("lmroman10 caps", 30, 50, false)
end if

this.player.SetMessagePort(this.port)
this.player.SetLoop(true)
this.player.SetPositionNotificationPeriod(1)
this.player.SetDestinationRect(this.layout.left)
this.player.SetContentList([{
REM Stream: { url: "http://ec2-184-72-239-149.compute-1.amazonaws.com:1935/demos/smil:bigbuckbunnyiphone.smil/playlist.m3u8" }
REM Stream: { url: "http://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest" }
Stream: { url: launchUrl }
REM StreamFormat: "hls"
StreamFormat: "ism"
REM SwitchingStrategy: "full-adaptation"
}])
this.player.Play()

return this
End Sub

Sub EventLoop()
while true
msg = wait(0, m.port)
if msg <> invalid
'If this is a startup progress status message, record progress
'and update the UI accordingly:
if msg.isStatusMessage() and msg.GetMessage() = "startup progress"
m.paused = false
progress% = msg.GetIndex() / 10
if m.progress <> progress%
m.progress = progress%
m.paint()
end if

'Playback progress (in seconds):
else if msg.isPlaybackPosition()
m.position = msg.GetIndex()
m.paint()

else if msg.isRemoteKeyPressed()
index = msg.GetIndex()
print "Remote button pressed: " + index.tostr()
if index = 3 '<DOWN> (toggle fullscreen)
if m.paint = PaintFullscreenCanvas
m.setup = SetupFramedCanvas
m.paint = PaintFramedCanvas
rect = m.layout.left
else
m.setup = SetupFullscreenCanvas
m.paint = PaintFullscreenCanvas
rect = { x:0, y:0, w:0, h:0 } 'fullscreen
m.player.SetDestinationRect(0, 0, 0, 0) 'fullscreen
end if
m.setup()
m.player.SetDestinationRect(rect)
else if index = 4 or index = 8 '<LEFT> or <REV>
m.position = m.position - 60
m.player.Seek(m.position * 1000)
else if index = 5 or index = 9 '<RIGHT> or <FWD>
m.position = m.position + 60
m.player.Seek(m.position * 1000)
else if index = 13 '<PAUSE/PLAY>
if m.paused m.player.Resume() else m.player.Pause()
end if

else if msg.isPaused()
m.paused = true
m.paint()

else if msg.isResumed()
m.paused = false
m.paint()

end if
'Output events for debug
print msg.GetType(); ","; msg.GetIndex(); ": "; msg.GetMessage()
if msg.GetInfo() <> invalid print msg.GetInfo();
end if
end while
End Sub

Sub SetupFullscreenCanvas()
m.canvas.AllowUpdates(false)
m.paint()
m.canvas.AllowUpdates(true)
End Sub

Sub PaintFullscreenCanvas()
list = []

if m.progress < 100
color = "#000000" 'opaque black
list.Push({
Text: "Loading..." + m.progress.tostr() + "%"
TextAttrs: { font: "huge" }
TargetRect: m.layout.full
})
else if m.paused
color = "#80000000" 'semi-transparent black
list.Push({
Text: "Paused"
TextAttrs: { font: "huge" }
TargetRect: m.layout.full
})
else
color = "#00000000" 'fully transparent
end if

m.canvas.SetLayer(0, { Color: color, CompositionMode: "Source" })
m.canvas.SetLayer(1, list)
End Sub

Sub SetupFramedCanvas()
m.canvas.AllowUpdates(false)
m.canvas.Clear()
m.canvas.SetLayer(0, [
{ 'Background:
Url: m.background
CompositionMode: "Source"
},
{ 'The title:
Text: "Custom Video Player"
TargetRect: m.layout.top
TextAttrs: { valign: "bottom", font: m.headerfont, color: m.textcolor }
},
{ 'Help text:
Text: m.help
TargetRect: m.layout.right
TextAttrs: { halign: "left", valign: "top", color: m.textcolor }
}
])
m.paint()
m.canvas.AllowUpdates(true)
End Sub

Sub PaintFramedCanvas()
list = []
if m.progress < 100 'Video is currently buffering
list.Push({
Color: "#80000000"
TargetRect: m.layout.left
})
list.Push({
Text: "Loading..." + m.progress.tostr() + "%"
TargetRect: m.layout.left
})
else 'Video is currently playing
if m.paused
list.Push({
Color: "#80000000"
TargetRect: m.layout.left
CompositionMode: "Source"
})
list.Push({
Text: "Paused"
TargetRect: m.layout.left
})
else 'not paused
list.Push({
Color: "#00000000"
TargetRect: m.layout.left
CompositionMode: "Source"
})
end if
list.Push({
Text: "Current position: " + m.position.tostr() + " seconds"
TargetRect: m.layout.bottom
TextAttrs: { halign: "left", valign: "top", color: m.textcolor }
})
end if
m.canvas.SetLayer(1, list)
End Sub


That should get you started.
0 Kudos
Transparent
Visitor

Re: roUniversalControlEvent - Pause/Play functions

Wow belltown, thanks a lot! That helps so much! Really do appreciate the time you put into modifying that
I've one question though, that error I had earlier at
Sub Setup(launchUrl As String) As Object
still pops up, is that an issue? As I can still upload the channel and it runs fine, seems odd - should it be ignored?


Syntax error: unexpected token "As", expected one of <INTID>, <FLOATID>, <DOUBLEID>, <STRINGID>, <INTLITERAL>, <HEXLITERAL>, <FLOATLITERAL>, <DOUBLELITERAL>, <STRINGLITERAL>, "True", "False", "Invalid", "(", "Type", "Rnd", "GetGlobalAA", "Box", "Run", "Eval", "GetLastCompileError", "GetLastRuntimeError", "Sleep", "Wait", "CreateObject", "GetInterface", "UpTime", "RebootSystem", "ListDir", "ReadAsciiFile", "WriteAsciiFile", "CopyFile", "MatchFiles", "DeleteFile", "DeleteDirectory", "CreateDirectory", "FormatDrive", "strtoi", "Ucase", "LCase", "Asc", "Chr", "Instr", "Left", "Len", "Mid", "Right", "Str", "Stri", "String", "Stringi", "Val", "Tr", "Abs", "Atn", "Cos", "Csng", "Cdbl", "Exp", "Fix", "Int", "Log", "Sgn", "Sin", "Sqr", "Tan", <ID>, "Component", "Interface", "Event", "Exit", "Print", "?", "Goto", "Return", "Stop", <NEWLINE>, or ":"
0 Kudos
belltown
Roku Guru

Re: roUniversalControlEvent - Pause/Play functions

Interesting. I don't get an error on my Roku for that code, nor for the Roku SDK customvideoplayer example code, and I've never seen that particular error message before. I'm surprised the code still runs with a syntax error like that. Maybe it's something new. Just curious what Roku model number and OS version are you running?

What I think it's saying though is that a "Sub" cannot have a non-void return type, so change:
Sub Setup(launchUrl As String) As Object
to:
Function Setup(launchUrl As String) As Object
and change the corresponding:
End Sub
statement to:
End Function
0 Kudos
Transparent
Visitor

Re: roUniversalControlEvent - Pause/Play functions

Model: 3500X - Roku Stick
Version: 7.2.0 Build 4100 - 09

Yeap, no more errors exist now and the channel runs fine, thanks!

Edit: Was only trying to do Pause/Play but you also gave me ffw and rwd...loving it
0 Kudos
belltown
Roku Guru

Re: roUniversalControlEvent - Pause/Play functions

"Transparent" wrote:
Model: 3500X - Roku Stick
Version: 7.2.0 Build 4100 - 09

Yeap, no more errors exist now and the channel runs fine, thanks!

Curious. I have a Model 3100X with version 7.2.0 • build 4100-02, and I didn't get the error message when specifying a non-void return value on a Sub declaration. I wonder if Roku changed something in the -03 .. -09 builds.

Unless.. That was an error you saw in the Roku Debugger on port 8085 right, rather than somewhere else (like Eclipse?)
0 Kudos
EnTerr
Roku Guru

Re: roUniversalControlEvent - Pause/Play functions

Would be nice if sub can be used in lieu of function because of less typing!

Now maybe it's important for function to nag if there is no `return` statement (i am ambivalent if it should or not). But there is no good design justification for sub complaining if there is non-void return (besides nit-picking 🙂 - i said "good" reason!). Quick check... no, `function` does non ensure there is `return` (probably futile to try that compile-time), so `sub` may as well be turned to synonym of `function`.
0 Kudos