Having downloaded the hello world zip file and set up Eclipse for Roku development, I'm eager to try something.
So I'm going to try doing "Hello, World" for myself - and then we'll try and tinker with some things.
Creating a Project
The Eclipse plugin comes with a New Project Wizard, so let's see that at work.
I can certainly find the wizard - it's right at the top of the list. When I open it, there are a lot of options here that I don't understand, but that's not too surprising.
I've unpacked the zip file to a directory, so I point the project there and fill in as few fields as I can manage. It's a bit disconcerting that I see a number of errors in the console window where I'm running eclipse - including a stack overflow - but it seems to take them all in its stride.
It offers me the "BrightScript" perspective, which seems reasonable enough, so I take that. It has some "Roku Remote" on the right hand side; we will have to dig into that later. On the left hand side, I have the normal project explorer, so let's see if we can open some files.
There's a manifest which has its own editor - nice. There's a makefile that confuses me, mainly because of its simplicity. There's a single file under Source - "Main.brs" - which presumably does something; I had been considering that the simplest app might just be a splash screen. There's an XML configuration for a component which seems to be most of the work. And then there appear to be two images, each at three different resolutions.
Deploying a Project
Per the documentation, the plugin has the ability to deploy a project to the Roku box. To do this, an option has been added to the "File>Export..." menu. It's necessary to fill out a form with relevant information - such as IP address and developer password on the Roku box. Push "Finish" and ... it fails. Sadly, it would seem, because of timeout error. It does tell you how to fix this, but let's just try again. This time it works. Great!
Going back to the Roku box, everything seems to work, but I have to admit that it's hard to tell. We'll need to make a change and redeploy. But that's for another time. For now, let's dig into the code that we've got here.
Main.brs
First off, here is the code:
sub Main()
print "in showChannelSGScreen"
'Indicate this is a Roku SceneGraph application
screen = CreateObject("roSGScreen")
m.port = CreateObject("roMessagePort")
screen.setMessagePort(m.port)
'Create a scene and load /components/helloworld.xml
scene = screen.CreateScene("HelloWorld")
screen.show()
while(true)
msg = wait(0, m.port)
msgType = type(msg)
if msgType = "roSGScreenEvent"
if msg.isScreenClosed() then return
end if
end while
end sub
I'm not sure how much detail to go into, so I'm going to assume that either you are familiar with BASIC-like languages or are smart enough to guess at the syntax. So leaving that aside, together with the debugging statements and comments, this falls into two sections. The first section is the setup, which is basically as follows:
- create a new screen object
- create a new "message port"
- connect the message port to the screen
- populate the screen with the "hello, world" scene (as investigated in the next section)
- make the screen "object" project onto the actual (TV) screen
The "ro" prefix appears to be common to all the components and presumably means "Roku" rather than, say, "read only".
Then the remaining code is a simple event loop which basically just goes around and around until it sees a "close screen" message at which point it exits. I'm not quite sure what triggers that event; I form the impression from reading the documentation that an application doesn't receive any notification if, for example, the "Home" button is pressed; and certainly the Roku box wouldn't want to be held to ransom by you failing to process the "close screen" event.
One final mysterious item before we carry on: the message port is attached to an object called "m" for some reason. The actual reason why this done in this code is mysterious to me, but presumably it is just derived from "normal style". In any case, the variable m is the "this" variable in BrightScript.
helloworld.xml
As with many other programming environments (Android for example), Roku offers an XML alternative to building up a scene using "boilerplate" code. These components are processed as the application is started and put into a "library" from which they can be accessed, as by "CreateScene" above.
The XML comes with an embedded BrightScript script, but for now we will just consider the actual XML portion:
<?xml version="1.0" encoding="utf-8" ?>
<component name="HelloWorld" extends="Scene">
<children>
<Label id="myLabel"
text="Hello World!"
width="1280"
height="720"
horizAlign="center"
vertAlign="center"
/>
</children>
<!-- BrightScript Portion Elided -->
</component>
This is designed to create a "component" which appears to be much the same as a "class" in an object-oriented language. It defines the name of the component ("HelloWorld") which is the name by which it will be referenced in the component library. Because this is intended to be a scene, it extends the Scene component. As with almost all modern UI toolkits, the UI elements form an object (in this case component) hierarchy.
Inside this, it creates a simple Label, showing the desired text. The width and height seem like random numbers, but presumably correspond to the most common screen resolution (i.e. full HD). The screen size can be determined from the device info.
The script
Inside this component, there is the ability to embed a script. As the component is transpiled from XML to BRS, this script appears to be inserted into it; presumably this means you can add anything you want, but the key thing is the ability to add an init method which is called when the component is created. It is my understanding that this script is executed in the scope of the component and thus has access to things that elements outside the script do not (although there does not seem to be the notion of private and public members per se).
Here is the hello, world script:
function init()As discussed before, m refers to the current component - that is, the HelloWorld component. top refers to the top of the embedded hierarchy and findNode traverses the hierarchy to find a component with the given id. I think most of the rest of the code is self-explanatory (with the exception of the color constant which I think is RGBA).
m.top.setFocus(true)
m.myLabel = m.top.findNode("myLabel")
'Set the font size
m.myLabel.font.size=92
'Set the color to light blue
m.myLabel.color="0x72D7EEFF"
end function
Summary
So far, so good. I think I've understood (and possibly even explained) the basic operation of the "hello, world" Roku application.
So now let's try and do something a little different.
No comments:
Post a Comment