Economy Size Geek - Remix the Internet and Your Television with the Roku DVP
Listing 1. HelloWorld.brs
'Copyright 2010 Dirk Elmendorf
Function Main() as Integer
print "Hello World! to the console"
print ' you will not see this '
p = CreateObject("roMessagePort")
screen = CreateObject("roSpringboardScreen")
screen.SetMessagePort(p)
o = CreateObject("roAssociativeArray")
o.ContentType = "episode"
o.Title = "Sample App"
o.Description = "Hello World!"
o.SDPosterURL = "pkg:/images/episode_icon_sd.png"
o.HDPosterURL = "pkg:/images/episode_icon_sd.png"
screen.SetContent(o)
screen.AddButton(1, "Exit")
screen.Show()
while true
msg = wait(0, p)
if msg.isButtonPressed()
print "Goodbye World!"
return 0
endif
end while
end Function
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.
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 github.com/economysizegeek/linux_journal_roku).
Listing 2. KEXP.brs
'Copyright 2010 Dirk Elmendorf
Function Init() as Object
obj = {
port: CreateObject("roMessagePort")
screen: CreateObject("roSpringboardScreen")
player: CreateObject("roAudioPlayer")
screen_options: CreateObject("roAssociativeArray")
song: CreateObject("roAssociativeArray")
status: ""
drawScreen: function(description)
m.screen_options.Description = description
m.screen.SetContent(m.screen_options)
m.screen.Show()
end function
playingNow: function()
m.screen.ClearButtons()
m.screen.AddButton(1, "Pause Stream")
m.screen.AddButton(3, "Exit")
m.DrawScreen("Live MP3 Stream from KEXP.org")
end function
play: function()
if m.status = "" then
m.player.AddContent(m.song)
m.player.SetLoop(true)
m.player.play()
m.status = "playing"
else if m.status = "paused"
m.player.resume()
m.status = "playing"
endif
m.screen.ClearButtons()
m.screen.AddButton(3, "Exit")
m.drawScreen("Buffering....")
end function
pause: function()
if m.status = "playing" then
m.player.pause()
m.status = "paused"
endif
m.screen.ClearButtons()
m.screen.AddButton(2, "Resume Stream")
m.screen.AddButton(3, "Exit")
m.drawScreen("Stream Paused")
end function
exit: function()
print "Goodbye World!"
m.player.stop()
return 0
end function
}
obj.screen.SetMessagePort(obj.port)
obj.player.SetMessagePort(obj.port)
obj.screen_options.ContentType = "episode"
obj.screen_options.Title = "KEXP"
obj.screen_options.SDPosterURL = "pkg:/images/episode_icon_sd.png"
obj.screen_options.HDPosterURL = "pkg:/images/episode_icon_sd.png"
obj.screen.SetStaticRatingEnabled(false)
obj.song.Url = "http://kexp-mp3-2.cac.washington.edu:8000/"
obj.song.StreamFormat = "mp3"
obj.status = ""
return(obj)
end Function
Function Main() as Integer
app = Init()
app.play()
while true
msg = wait(0, app.port)
if type(msg) = "roAudioPlayerEvent"
if msg.isStatusMessage() then
print "Audio Player Event:"; msg.getmessage()
if msg.GetMessage() = "start of play" then
app.playingNow()
endif
endif
else if msg.isButtonPressed() then
if msg.GetIndex() = 1 then
app.pause()
else if msg.GetIndex() = 2 then
app.play()
else if msg.GetIndex() = 3 then
return app.exit()
endif
else if msg.isScreenClosed() then
return app.exit()
endif
end while
end Function
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 (blog.brianlane.com/2009/12/20/streaming-local-video-with-your-roku).
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.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- RSS Feeds
- Trying to Tame the Tablet
- New Products
- What's the tweeting protocol?
- Dart: a New Web Programming Experience
Enter to Win an Adafruit Prototyping Pi Plate Kit for Raspberry Pi

It's Raspberry Pi month at Linux Journal. Each week in May, Adafruit will be giving away a Pi-related prize to a lucky, randomly drawn LJ reader. Winners will be announced weekly.
Fill out the fields below to enter to win this week's prize-- a Prototyping Pi Plate Kit for Raspberry Pi.
Congratulations to our winners so far:
- 5-8-13, Pi Starter Pack: Jack Davis
- 5-15-13, Pi Model B 512MB RAM: Patrick Dunn
- Next winner announced on 5-21-13!
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.




2 hours 2 min ago
6 hours 41 min ago
9 hours 3 min ago
1 day 1 hour ago
1 day 4 hours ago
1 day 5 hours ago
1 day 6 hours ago
1 day 6 hours ago
1 day 11 hours ago
1 day 12 hours ago