GetInfo() and external control Input command

Hi all. I’m the developer of the Roku Remote app for Android, and have been working with the external controls commands for a while. But now I’m jumping into channel development and could use some help.

Basically, I want to create a very simple channel that accepts URLs passed to it from my app using external control. For example, I’d like to send something like:

http://192.168.1.5:8060/input?url=http://www.someserver.com/somemusicfile.mp3

The channel should accept the input argument “url” and use the value to start playback. This should be possible from the external controls document:

input enables a developer to send custom events to their Brightscript application. It takes a user defined list of name-value pairs sent as query string uri parameters. The external control server places these name-value pairs into a BrightScript associative array and passes them directly through to the currently executing channel script via a Message Port attached to a created roInput object. Please refer to Section 3.1 below for more detailed recommendations on how to pass your data. Messages of type roInputEvent have a GetInfo() method that will obtain the associative array. The arguments must be URL-encoded. This command is sent via a POST with no body.
Example: POST /input?acceleration.x=0.0&acceleration.y=0.0&acceleration.z=9.8

I do have the audioapp sample working, so I’m really just looking at how to be notified that the message was received and to pull the URL value from the message.

I also see the launchparams example, but that’s not what I’m looking for. I want to send the URLs while the channel is running, not at startup.

Any help would be appreciated.

Thanks,

-Gregg Reno

You’ll need to look into the sockets support in the 3.0 SDK.

-JT

I haven’t played with this much at all yet, but you would do something along these lines…

port = CreateObject("roMessagePort")
input = CreateObject("roInput")
input.SetMessagePort(port)

while true
  msg = Wait(0, port)
  params = msg.GetInfo()

  ' do something useful with the data here
end while

And send it an event from outside like this…

curl -d "" "http://[roku_ip]:8060/input?text=hello"

Very cool - thanks Chris. I’ll give that a try.

OK, I have this sort of working. Now I’m stuck on understating how these roInput events are queued up.

I’m using the audioapp example as a starting point. Here is what I want:

  • Screen A = Main roPosterScreen screen
  • Screen B = roAudioPlayer screen
  • Screen C = not sure yet

If I get any external command (roInput), it shouldn’t matter where in the channel I am - i want it to go to the appropriate screen and process it. I’ve added roInput to the message loop of all the screens so they can all receive roInput events. If I get external message type “B”, it should play in Screen B. If I get message type “C”, it should play in Screen C.

Here is what is working:

  • Start at Screen A
  • Send external command type “B”
  • Screen B is displayed and starts playing the delivered media from passed URL
  • Send another external command type “B”
  • Screen B knows to stay on same screen, stop playing old content, start playing new content from message B

This works fine, but at this point if I hit the up/back key, Screen A now processes my second external command type “B”, even though screen B already processed it. The effect is it launches screen B again and plays the content again from the second external command.

So the question is, how can I make sure only one of these external messages is processed instead of both screen A and B message loops getting it?

This also raises another question about how I should handle message type “C” while in screen B? Should it just return to Screen A and let it handle it, or should it launch screen C? And when in screen C, I want the up/return key to go to the top level Screen A, and not retain a history of it’s path through screen B.

Hope that makes sense! Any suggestions would be appreciated.

Thanks
-Gregg

Yeah, this appears to be a bug in the RoInput event as far as I can tell, haven’t yet come up with a work around. I tried to “eat” the event by sticking another wait in the path, but it doesn’t work. The launch events can wind up in roinput event when you return from a subroutine. Very perplexing. We encountered this while creating our Android-Roku hack for MusicHackDay San Francisco. Kind of screwed up the very last part of our demo where we tried to launch another module and the same song kept playing!

  • Joel

Ran into this thread while looking for documentation on roInput. After some meditation - while there is not enough info in problem description to be 100% certain - i think i understand what was happening in @greno /@jbrave’s cases:

It must be that there were 2 roInput objects created in 2 different places (presumably with different ports) - and when /input arrives, both get the same event posted to them. And since A and B do not process their queues in sync, long time may pass till B is closed and the loop of A is ran - just to discover there is another /input copy waiting there, so it seems to be repeating.

This is not necessarily a bug of how the firmware works - nor having >1 roInput is necessarily a mistake. There might be a corner case in which this is useful, something like 2 different components wanting to get notified independently of the same /input. It may also be the case that the behavior has changed since 2011 (say making the factory createObject(“roInput”) always return the same singleton - with the consequence that screen A will stop receiving roInputEvents after B does setPort) - no idea, since there is still no documentation :face_with_tongue:

A reasonable work-around for Greno’s case (given a time machine) would be to use only 1 global roInput (with 1 own port) and each screen’s A, B, C’s event loop to also check roInput’s port on the side.