External Control of Netflix channel?

I have posted a version of the MOG Roku channel with support for ECP to the private channel for our betas. You can pick up the beta at https://owner.roku.com/add/mogbeta2 . This is a total hack job and I’m relying on the community to QA it.

app id=“2049” version=“1.82.0”

You must be logged in before using MOG via ECP. To do that use the app normally, in manual mode.

This takes up to 20 track IDs, plays them, and exits. Supply track IDs with the syntax trackID, trackID1, …, trackID20

Given a Roku on 192.168.0.208, the playlist at http://mog.com/playlists/499366 will play on your Roku if you POST to

http://192.168.0.208:8060/launch/2049?t … D10=302939

“whaleface” wrote:
lurking with interest over here. btw lucasgonze, since I’m assuming you are one of MOG’s channel developers, thanks for tracking this forum post down. I’m excited to see if you manage to get something working.

You’re welcome, whaleface.

I’m counting on you to actually put the thing to use!

“lucasgonze” wrote:
I have posted a version of the MOG Roku channel with support for ECP to the private channel for our betas. You can pick up the beta at https://owner.roku.com/add/mogbeta2 . This is a total hack job and I’m relying on the community to QA it.

app id=“2049” version=“1.82.0”

You must be logged in before using MOG via ECP. To do that use the app normally, in manual mode.

This takes up to 20 track IDs, plays them, and exits. Supply track IDs with the syntax trackID, trackID1, …, trackID20

Given a Roku on 192.168.0.208, the playlist at http://mog.com/playlists/499366 will play on your Roku if you POST to

http://192.168.0.208:8060/launch/2049?t … D10=302939

wow, that was fast. it sounds totally cool, got the beta installed and I’m going to give it a shot this weekend and see what I can get going. thanks again!

“lucasgonze” wrote:
Is there an ECP controller I can use for testing? Anybody have a generic web form or precompiled OS X binary?

How about a Python snippet? I use this:


import httplib

def ecp_invoke(op, path):
    conn = httplib.HTTPConnection(ROKU_IP, 8060)
    conn.request(op, path)
    r = conn.getresponse()
    res = r.read() if r.status==200 else '%d %s' % (r.status, r.reason)
    conn.close()
    return res

launch = lambda appID, params='': ecp_invoke('POST', '/launch/%s?%s'%(appID,params))
get_app_list = lambda: ecp_invoke('GET', '/query/apps')
keypress = lambda key: ecp_invoke('POST', '/keypress/' + key)
keydown = lambda key: ecp_invoke('POST', '/keydown/' + key)
keyup = lambda key: ecp_invoke('POST', '/keyup/' + key)

Then you’d start an app with

launch('2049', 'trackID=5639969')

EnTerr, the way I got this done so quickly was that I happened to have a slice of free time right when this topic came up. But today I’m busy again. So if you can help get the code written for the new arg style I’m happy to make the change (or support both argument styles for the sake of “legacy” code).

My current source code is here: http://pastebin.com/n6v6VCPT

“lucasgonze” wrote:
EnTerr, the way I got this done so quickly was that I happened to have a slice of free time right when this topic came up. But today I’m busy again. So if you can help get the code written for the new arg style I’m happy to make the change (or support both argument styles for the sake of “legacy” code).

My current source code is here: http://pastebin.com/n6v6VCPT

Ok, how about this (oops, i pasted it in pasta-bin too):


   if( params["trackIDs"] <> invalid ) then
     tidStr = params["trackIDs"] + " " 'extra space to simplify handling in loop
     playlist = []
     i = instr(1, tidStr, " ")
     while i>0
       digested =  ecp_digest_trackID(left(tidStr, i-1))
       if( digested <> invalid ) playlist.push(digested)
       tidStr = mid(tidStr, i+1)
       i = instr(1, tidStr, " ")
     end while
   end if

“EnTerr” wrote:

“lucasgonze” wrote:
EnTerr, the way I got this done so quickly was that I happened to have a slice of free time right when this topic came up. But today I’m busy again. So if you can help get the code written for the new arg style I’m happy to make the change (or support both argument styles for the sake of “legacy” code).

My current source code is here: http://pastebin.com/n6v6VCPT

Ok, how about this (oops, i pasted it in pasta-bin too):


   if( params["trackIDs"] <> invalid ) then
     tidStr = params["trackIDs"] + " " 'extra space to simplify handling in loop
     playlist = []
     i = instr(1, tidStr, " ")
     while i>0
       digested =  ecp_digest_trackID(left(tidStr, i-1))
       if( digested <> invalid ) playlist.push(digested)
       tidStr = mid(tidStr, i+1)
       i = instr(1, tidStr, " ")
     end while
   end if

That can be simplified greatly…


   if( params["trackIDs"] <> invalid ) then
     playlist = params["trackIDs"].Tokenize(" ")
   end if

I have published a new version that supports a spaces-separated list sent to an argument named trackIDs.

This is not backwards compatible with the first version. The arguments trackID, trackID1, …, trackID20 don’t work any more.

And thanks for the incantations, EnTerr and TheEndless.

gonzotek, reading the remoku source was a big help. I appreciate the learning. In the end I used hardcoded hack forms like this one, so that I could focus on just the brightscript: http://pastebin.com/8RryduUv

“TheEndless” wrote:

That can be simplified greatly…


   if( params["trackIDs"] <> invalid ) then
     playlist = params["trackIDs"].Tokenize(" ")
   end if

Phew!
Glad to hear, i have never programmed BrightScript before and i got rather disappointed today by the lack of string functions (e.g. split() ) when skimming the reference manual.

“lucasgonze” wrote:
And thanks for the incantations, EnTerr and TheEndless.

gonzotek, reading the remoku source was a big help. I appreciate the learning. In the end I used hardcoded hack forms like this one, so that I could focus on just the brightscript: http://pastebin.com/8RryduUvNo problem, glad to see the feature added into the Mog beta. Would it be ok with you/Mog to add the launch interface to remoku for end users now, or would it be better to wait until after this version of Mog leaves beta status? I have a testing version I keep locally where I’m already adding interfaces for channels that publicly support ecp launch params (right now it’s just shoutcast and soon-to-be mog). I wouldn’t want to make something public unless the developer is onboard first.

Cheers,
Cassidy
(aka Gonzotek :slightly_smiling_face: )

Ok, here is my proof of concept google chrome extension. This works like a champ for me. It adds ‘Roku’ links to album and playlist pages, then tries to find all the tracks in the page and adds Roku links next to those too. It doesn’t work everywhere (for instance the dynamic search boxes), so you have to browse to an album or playlist’s page directly to make it work.

Example: On http://mog.com/albums/mn44159503/el-guincho/pop-negro I get a Roku link next to the album title that plays all tracks in the album, and individual Roku links for each song. Same deal for http://mog.com/playlists/86773.

Go the extension’s options to set your Roku’s IP address first.

It does uglify mog.com somewhat. Here’s the source in case anybody who is better at js and html than me wants to make it prettier/more useful.

Btw, I cribbed the Roku-contacting parts from remoku, so thanks for that app. :slightly_smiling_face: If somebody could try this out and let me know if it works, that would be great. I thought I might have cross-origin problems with hitting the Roku’s ip without putting explicit permissions in the extension’s settings, but it doesn’t seem to mind?

Cassidy/gonzotek, I’d love it if you added those interfaces to Remoku. It’s hard for us to QA these things beyond just having developers use them. It’s interesting to see that whaleface also cribbed source from Remoku - it turns out to be a great way to learn ECP hacking.

We’ll push the feature out to production next time we have a batch of user-visible features which merit in-house QA time.

whaleface, I’m really psyched to see your hack. Is the only modification to the MOG UI that it adds the blue “(Roku)” link? That doesn’t look so bad, all things considering. I know from experience that modifying page layouts is a can of worms… Might as well just get started.

I haven’t gotten time to hook up the Roku today, so haven’t been able to test the extension fully. But it has been smooth so far.

I’ll be demoing MOG Roku hacks at NY Music Hack Day next weekend and will show this off. How does it detect a MOG ID? Is it possible to have your extension detect MOG IDs in tracks outside of mog.com? One way to do that is to look for links in the form http://mog.com/tracks/mn44159509/el-gui … gro/bombay

“lucasgonze” wrote:
whaleface, I’m really psyched to see your hack. Is the only modification to the MOG UI that it adds the blue “(Roku)” link? That doesn’t look so bad, all things considering. I know from experience that modifying page layouts is a can of worms… Might as well just get started.

yes, it just adds the roku links next to the album/playlist header and each track. it’s a bit ugly because they can sometimes wrap to the next line or be off-centered, etc. originally I wanted to get them in the dropdown play buttons but I couldn’t get that working quickly.

“lucasgonze” wrote:
I haven’t gotten time to hook up the Roku today, so haven’t been able to test the extension fully. But it has been smooth so far.

great! please let me know if the actual roku interaction doesn’t work because like I said I was suspicious of the permissions thing. but I was using it all weekend and it really seems to work well. even sending a playlist with 80+ tracks to the roku works fine.

“lucasgonze” wrote:
I’ll be demoing MOG Roku hacks at NY Music Hack Day next weekend and will show this off. How does it detect a MOG ID? Is it possible to have your extension detect MOG IDs in tracks outside of mog.com? One way to do that is to look for links in the form http://mog.com/tracks/mn44159509/el-gui … gro/bombay

sounds awesome. I’m actually new to chrome extensions but I don’t see any reason it couldn’t do that. it currently checks the page URL to figure out if you’re on an album or playlist page, then searches the DOM for the relevant elements. it pulls the track IDs out from the ‘new Mog.Track’ links using regular expressions, but it could just as easily pull them out of mog.com links. I’m not sure how much free time I’ll have since I have a business trip to prepare for but if I get a chance I’ll hack on it some more.

I just did a test against a live device and nothing happened on the device.

My guess is that setting the IP in the config screen isn’t working.

“lucasgonze” wrote:
I just did a test against a live device and nothing happened on the device.

My guess is that setting the IP in the config screen isn’t working.

well, darn. try grabbing the source from here and edit manifest.json to have the following:

“permissions”: [
http://your-roku-ip-address:8060/*
],

then do ‘load unpacked extension’ from the chrome extensions page and see if that fixes it. the app id is always 2049 right? you could also try hard-coding your ip in background.html.

For what it’s worth, I’ve put up a simple SHOUTcast custom URL launcher here… http://www.permanence.com/roku/shoutcast.htm
Very simple, but it gets the job done.

I uploaded a new version of the extension here that gives it permissions to do cross-origin requests anywhere, which gives you the slightly scary message that it can “access your data on all websites”. I’m not sure how else to do it though when the IP it needs to hit is configurable.

I wonder if there’s a way to have your Roku tell the extension what its IP is? Is there any Brightscript API for that?

“lucasgonze” wrote:
I wonder if there’s a way to have your Roku tell the extension what its IP is? Is there any Brightscript API for that?
The roDeviceInfo component has a GetIPAddrs() method that returns an associative array of IP addresses (wired and/or wireless), but I don’t think that’ll do what you’re talking about. The only way I know of for an external application to get that information be via SSDP broadcast. After all, there’s no way for the extension to talk to the Roku unless it already knows the IP address.