Economy Size Geek - Remix the Internet and Your Television with the Roku DVP

Developing custom channels for the Roku.

Let's do a walk-through of the code, but if the version you get from the git repository is different, it means I fixed a bug after this went to press.

The first code listing is a crash course in BrightScript. All it does is create a Main that builds a single screen and exits on any button push. The print statements are spit out to the Roku console. The console also allows you to enter a debugger and see any syntax errors. You can access the Roku console by entering telnet $ROKU_DEV_TARGET 8085. I had to use it a couple times to find out why the channel wasn't showing up (which often means there is a syntax error).

As you can see, I created a function called Main. This is the entry point for all BrightScript applications. I included two different print statements. The first one works, but the second one only prints out a blank line, because a single quote is considered a comment in BrightScript. Then, I created two objects. The roMessagePort is where messages (events) are sent. The roSpringboardScreen is a BrightScript component. This is basically a screen you can reconfigure by providing information. Roku ships with a number of these screens for your use. I chose this one because it was the easiest to work with. I connect the screen and the port. This tells the system to send all events from the screen to the message port I created. There probably are cases where you need to have different message ports for different events, but so far, I have used only a single message port shared with every screen.

Then, I create a roAssociativeArray. This is very much like a hash (or a plain JavaScript object). I use it to set up up a number of predefined fields. This gets passed into the screen. Next, I create a single button on the screen and tell the system to draw the screen. The last step is to set up an infinite loop. The wait allows the system to sit until an event is triggered. Then, I can have the result of that event processed. In this case, it means the program exits.

Rocking Out

The next step was to add in another BrightScript component—namely roAudioPlayer. This component handles playing MP3 streams. I wrote a new script from scratch to do this. The channel to handle streaming is in the kexp directory. The main file (Listing 2) is in the source/KEXP.brs (at

Listing 2 is for this channel. It is different in two main ways. First, this time, the event loop actually looks at the button being pushed. The loop is now able to trigger a different behavior depending on the index value of the button that was pushed. The other change is that I created an application object. I wanted to demonstrate that Roku has provided an incredibly dynamic language, so I built it up much the same way you would in JavaScript. The one odd thing to notice is the use of “m.” inside the methods for the app object. The “m.” is a pointer to the object. You can read it as “this.”, because that is how Roku is resolving it when it gets compiled.

The event code is also tracking the state of the stream itself. The roAudioPlayer considers it an error if you try to pause a stream that is not playing or try to resume a stream that is not paused. The code handles those cases. It also handles shutting down the stream when you exit.

With a working streaming application in hand, I started trying to get the “on-demand” portion of the KEXP Web site integrated into it. The first step was to navigate to a show and find a URL for a single show. This took some work, because the on-demand programs are served using a different protocol and URL from the live feed. Eventually, I was able to get a URL by downloading and opening files that the KEXP server provides.

Unfortunately, I ran into a Roku platform limitation. It does not support the codec that KEXP is using. Currently, there is no way for a third-party developer to add additional codec support. Because the live stream is available in MP3, the Roku handles it fine, which has been the case for a number of the radio feeds I looked at. So, if the stream you want to use streams via Flash or some other codec, you may be out of luck as well. Roku also supports WMA, but that seems to be more for files than streams.

For this article, I wrote everything from scratch. When you are working on your own projects, you won't need to do that. Roku includes a number of different sample applications in the SDK. The code gives a great tour of the components and how they can be used, including audio, video, XML parsing and handling a registration process. Those examples also are a lot more polished than the code I have provided here (they include examples of how to create your own theme for the channel).

The next thing to play with is video streaming. I chose to focus on audio for this article, because it's very straightforward. Streaming video means obtaining a video source, as well as encoding it properly, and then you have to generate an XML document to describe it. You will need a Web server that can serve both the video and the XML. Once you have everything working, you should be able to run your own little Netflix-style video-streaming service. Now that you have your feet wet with Roku development, head over to Brian Lane's blog. He has documented some hacking he's done to get all of this working (

My goal with this article was to get streaming up for my wife (which I mostly achieved—I'm still working on getting the Shake the Shack show on demand). I was incredibly surprised at how easy it was to get up and hacking. Originally, I was turned off by having to deal with a new language, but BrightScript is close enough to JavaScript that it wasn't the hurdle I thought it would be. For me, the best part is that the Roku already had earned its place in my AV rack thanks to Netflix. Adding the ability to hack on it and the opportunity to try channels other people have built makes it that much more awesome.

Dirk Elmendorf is cofounder of Rackspace, some-time home-brewer, longtime Linux advocate and even longer-time programmer.