Hey,
I do some server requests in a task. eventually I get the final response with the videos I need to display. that’s fine. I send a callback to the VideoGridScene.
Now, I need to request something again from the server. let’s say, when the video pauses.
My task has a property with the Video node, and I get the ‘pause’ event.
But, on that point, I cannot access the registry to get some values nor can I request
Errors:
‘Dot’ Operator attempted with invalid BrightScript Component or interface reference. (runtime error &hec)
and
BRIGHTSCRIPT: ERROR: roUrlTransfer: class PLUGIN|MARKUP on thread RENDER: pkg:/components/Task.xml(378)
BRIGHTSCRIPT: ERROR: roMessagePort: Trying to construct a message port on a non-plugin thread: pkg:/components/Task.xml(379)
Hard to read your tea leafs but seems as if you are trying to use some components that are “haram” in RSG (render thread, specifically). Seeing that “Task.xml” is mentioned, you are probably doing it before spawning a task thread.
“EnTerr” wrote:
Hard to read your tea leafs but seems as if you are trying to use some components that are “haram” in RSG (render thread, specifically). Seeing that “Task.xml” is mentioned, you are probably doing it before spawning a task thread.
See also https://sdkdocs.roku.com/display/sdkdoc … pt+Support
Not sure I understood (I did understand the Haram part
Anyhow, I guess what I am saying is that I need a task node that can act as a continuous server.
Task.xml is just a sample. that’s not the real name of the node of course. my function within the task sends the result to the observer gets it and all is good.[/font][/color]
My question was actually about next step: I need to send more requests according to the player event (star, stop, pause and so on…).[/font][/color]
To use a Task as a continuous server, use the port form of ObserveField(), specifying an roMessagePort used to wait for changes on each item that you wish to observe. You can use the same port you use for your roUrlTransfer object. In the Task thread code, define a message loop that calls Wait() on the port. If an observed field changes, an roSGNodeEvent message is received. Call GetField() and GetData() on this message to get the name of the field that changed and its value. You only need to set the Task’s control field to “RUN” one time, to start it up. Thereafter, it will handle observed field changes each time they occur in its main Wait loop.
BRIGHTSCRIPT: ERROR: roUrlTransfer: class PLUGIN|MARKUP on thread RENDER: pkg:/components/Task.xml(378)
BRIGHTSCRIPT: ERROR: roMessagePort: Trying to construct a message port on a non-plugin thread: pkg:/components/Task.xml(379)
Seems awfully peculiar - could this be caused by assigning a Video node to a Task field?
Not something i would have tried but it shouldn’t bind the task spawned to the render thread, right?
PS. Why is the diagnostic text so weird? Is it trying to say that PLUGIN and MARKUP are mutually exclusive flags? I am guessing #378 is userRequest = CreateObject("roUrlTransfer")? Why is this the RENDER thread if it’s in the Task runner function?
“EnTerr” wrote:
How do we explain the bizarre “colonics”?
BRIGHTSCRIPT: ERROR: roUrlTransfer: class PLUGIN|MARKUP on thread RENDER: pkg:/components/Task.xml(378)
BRIGHTSCRIPT: ERROR: roMessagePort: Trying to construct a message port on a non-plugin thread: pkg:/components/Task.xml(379)
Seems awfully peculiar - could this be caused by assigning a Video node to a Task field?
Not something i would have tried but it shouldn’t bind the task spawned to the render thread, right?
PS. Why is the diagnostic text so weird? Is it trying to say that PLUGIN and MARKUP are mutually exclusive flags? I am guessing #378 is userRequest = CreateObject("roUrlTransfer")? Why is this the RENDER thread if it’s in the Task runner function?
Yes, #378 is CreateObject(“roUrlTransfer”)
“belltown” wrote:
To use a Task as a continuous server, use the port form of ObserveField(), specifying an roMessagePort used to wait for changes on each item that you wish to observe. You can use the same port you use for your roUrlTransfer object. In the Task thread code, define a message loop that calls Wait() on the port. If an observed field changes, an roSGNodeEvent message is received. Call GetField() and GetData() on this message to get the name of the field that changed and its value. You only need to set the Task’s control field to “RUN” one time, to start it up. Thereafter, it will handle observed field changes each time they occur in its main Wait loop.
Not so sure I understood what should I do in the Scene level & in the task level. any code snippet?
Here’s a very simplified example that illustrates the concept. Note that I don’t include the Video node as a field in the Task node as you’ve done. That just seems weird to me. It makes more sense to keep the Video node contained within the Render thread and communicate any state changes that the Task needs to know about via an interface field on the Task node that only contains the information the Task needs to know (i.e. the video state in this case). The Task just prints out any changes to the Video state by observing its interface field. You can add your own code to use your roUrlTransfer object to send that data where it needs to go.
sub init()
m.taskServerNode = m.top.findNode("taskServerNode")
m.taskServerNode.ObserveField("stateOutput", "onTaskStateOutput")
m.videoNode = m.top.findNode("videoNode")
m.videoNode.SetFocus(true)
m.videoNode.ObserveField("state", "onVideoState")
m.videoNode.control = "play"
end sub
sub onVideoState()
m.taskServerNode.stateInput = m.videoNode.state
end sub
sub onTaskStateOutput()
print "Task state: "; m.taskServerNode.stateOutput
end sub
function onKeyEvent(key as string, press as boolean) as boolean
handled = false
if press
if key = "play"
if m.videoNode.state = "playing"
m.videoNode.control = "pause"
else if m.videoNode.state = "paused"
m.videoNode.control = "resume"
else if m.videoNode.state = "stopped"
m.videoNode.control = "play"
end if
handled = true
end if
end if
return handled
end function
sub init()
m.top.functionName = "taskRun"
m.top.control = "RUN"
end sub
function taskRun() as void
port = CreateObject("roMessagePort")
m.top.ObserveField("stateInput", port)
while true
msg = Wait(0, port)
if Type(msg) = "roSGNodeEvent"
field = msg.GetField()
state = msg.GetData()
if field = "stateInput"
print "stateInput: "; state
m.top.stateOutput = state
end if
end if
end while
end function
“belltown” wrote:
I don’t know exactly what you’re asking here. But yes, there is a 3rd state. …
Yes - you got it what i was asking.
Hmm, i was musing last night when going to sleep - albeit it hasn’t crystalized when i woke up, so need more brain power: can we come with some “pattern” if you will, some code/contraption atop Tasks, that can be used to handle “haram” functionality? So that one does not have to write a separate Task for every little method but instead maybe there is only one task^ with magazine of methods under it - and those get invoked function-call like, the behavior handled by a framework. The calls in general being asynchronous^^, either doing callback at the end or passing result message back to a common queue. And each “call” does not have to necessarily spawn a new thread - there could be a pool of waiting threads, or a new call-message may just wait till a worker thread is available. That could all be built using the primitives, the question is the result being more usable/intuitive than the current er, paradigm…
(^) task “factory” of sorts; is already a factory: tickling its .control forks threads
(^^) I am also musing about synchronous option, like wrapping in await() call, which to take care of collecting the async result and only then returning - but unsure if this is not counterproductive, in defeating the purpose of the “haram” list
“belltown” wrote:
Here’s a very simplified example that illustrates the concept… …
Given the example code in the previous posts showing use of the Task Node, how would one then send data from the Task Node back to the Scene? Register another observed field ??
I’m thinking, some data pulled from a server, or a command to pause a video.
“belltown” wrote:
Here’s a very simplified example that illustrates the concept… …
Given the example code in the previous posts showing use of the Task Node, how would one then send data from the Task Node back to the Scene? Register another observed field ??
I’m thinking, some data pulled from a server, or a command to pause a video.
Yes, use an interface field in the Task node, which the Task can set when it has data to go back to the Scene. In the Scene, use an observer on the Task’s field to detect data passed back from the Task.