Creating RAF instance - in Task and not

Hello and greetings.

I try to use RAF.

When I invoke Roku_Ads() in the main thread (main.brs → showChannelSGScreen () ) , RAF instance created fine, all methods on-the-place:

{
    adpodcache: invalid
    adpodcacheupdated: false
    adurl: ""
    clearadbufferscreenlayers: <Function: roku_ads_clearadbufferscreenlayers>
    drawadbufferingprogressbar: <Function: roku_ads_drawadbufferingprogressbar>
    enableadbuffermessaging: <Function: roku_ads_enableadbuffermessaging>
    enablegarbagecollection: <Function: roku_ads_enablegarbagecollection>
    enablenielsendar: <Function: roku_ads_enablenielsendar>
...

But, the I create in in the Task, all methods are invalid:

{
    adpodcache: invalid
    adpodcacheupdated: false
    adurl: ""
    clearadbufferscreenlayers: invalid
    drawadbufferingprogressbar: invalid
    enableadbuffermessaging: invalid
    enablegarbagecollection: invalid
    enablenielsendar: invalid

Why? Where is a problem?

The code in the Task, if it is useful:

sub createAds()
    m.top.ads = Roku_Ads()
end sub

Where ‘ads’ definition is:

<interface>
 <field id="ads" type="assocarray" />
 </interface>

That’s very interesting. Can you please tell me all places where you invoke Roku_Ads()? And where is the first place you call it? Is it possible you do that in the render thread?

Don’t assign it to m.top.ads. Assign it to the internal ‘m’, as in m.ads. Assigning the AA to a node field does the thread-safe filtering of functions you see here. Also, I think instantiating RAF in a task is only supported as of 2.0, so be sure that is the version you see reported on the console.

“Veeta” wrote:
Don’t assign it to m.top.ads. Assign it to the internal ‘m’, as in m.ads. Assigning the AA to a node field does the thread-safe filtering of functions you see here.
Great catch, Veeta!
And a most amusing, ummm behavior.

Btw, one does not need really to persist the Roku_Ads() result. Calling it repeatedly is “cheap” so just assign it in local variable (e.g. ads and not m.ads) every time needed.

Also, I think instantiating RAF in a task is only supported as of 2.0, so be sure that is the version you see reported on the console.
Yes, that is the new feature of 2.0 i hear about - plus passing the RSG Node as a 3rd parameter (view) where you want the ads to temporarily hang their UI. I believe 2.0 is already on all Roku players already though (well maybe except Sky), being separate from the firmware update schedule.

Another note for implementing RAF in a Task thread. Google did it for their DAI SDK, which has a Roku implementation. Find the details at https://support.google.com/dfp_premium/answer/7298842?hl=en , look at the SceneGraph example.

This shows RAF used from a Task:
https://github.com/rokudev/RAF4RSG-sample

“Veeta” wrote:
Don’t assign it to m.top.ads. Assign it to the internal ‘m’, as in m.ads. Assigning the AA to a node field does the thread-safe filtering of functions you see here. Also, I think instantiating RAF in a task is only supported as of 2.0, so be sure that is the version you see reported on the console.
I don’t understand, how to do this. m here is a task, and I think to assign Roku_Ads instance to the field. m.top.ads in a field. If I assign it to m.ads, the ‘observeField’ will not work.
And yes, RAF version is 2.0.

“EnTerr” wrote:
This shows RAF used from a Task:
https://github.com/rokudev/RAF4RSG-sample
That’s interesting, thank you. But I can’t define main difference (with my code) yet. Will looking more…

“EnTerr” wrote:
That’s very interesting. Can you please tell me all places where you invoke Roku_Ads()? And where is the first place you call it? Is it possible you do that in the render thread?
1st place (successfully):
main.brs:

sub showChannelSGScreen()
    screen = CreateObject("roSGScreen")
    m.port = CreateObject("roMessagePort")
    screen.setMessagePort(m.port)
    scene = screen.CreateScene("MainScene")
    screen.show()
    MakeSome()  '<---- HERE

Where MakeSome() stored in athother file, same filder, name mixin.brs:

sub MakeSome()

    ads = Roku_Ads()

Errorneous creation:
Task xml:

<?xml version="1.0" encoding="UTF-8"?>
<component name="CreateAdsTask" extends="Task" xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">
	<script uri="pkg:/components/CreateAdsTask.brs" />
	<interface>
		<field id="ads" type="assocarray" />
	</interface>
</component>

Task script:

Library "Roku_Ads.brs"

Sub Init()
  m.top.functionName = "createAds"
End Sub

sub createAds()
    m.top.ads = Roku_Ads()
end sub

Invoking - in the main Scene (only one scene present in project):

    m.adsTask = createObject("RoSGNode", "CreateAdsTask")
    m.adsTask.observeField("ads", "setAds")
  [size=85][font=Helvetica Neue, Helvetica, Arial, sans-serif]    m.adsTask.control = "RUN"[/font][/size]

setAds:

sub setAds()

    m.ads = m.adsTask.ads

Where m is current Scene.

“EnTerr” wrote:
Btw, one does not need really to persist the Roku_Ads() result. Calling it repeatedly is “cheap” so just assign it in local variable (e.g. ads and not m.ads) every time needed.
Really? Sounds good.
But, i think to separate it to the Task will be useful to share it between different Scenes and Players.

“EnTerr” wrote:
Btw, one does not need really to persist the Roku_Ads() result. Calling it repeatedly is “cheap” so just assign it in local variable (e.g. ads and not m.ads) every time needed.
I try to create Roku-Ads()in the Scene,init(), and got this error:

BRIGHTSCRIPT: ERROR: roAppInfo: class PLUGIN|MARKUP on thread RENDER: roku_ads_lib:/Roku_Ads.brs(560)
BRIGHTSCRIPT: ERROR: roMessagePort: Trying to construct a message port on a non-plugin thread: roku_ads_lib:/Roku_Ads.brs(335)
BRIGHTSCRIPT: ERROR: roUrlTransfer: class PLUGIN|MARKUP on thread RENDER: roku_ads_lib:/Roku_Ads.brs(336)
So, to create Roku_Ads() ‘any time’ is not so easy :disappointed_face:

“mape” wrote:

“EnTerr” wrote:
Btw, one does not need really to persist the Roku_Ads() result. Calling it repeatedly is “cheap” so just assign it in local variable (e.g. ads and not m.ads) every time needed.
Really? Sounds good.
But, i think to separate it to the Task will be useful to share it between different Scenes and Players.
That is already done internally, it is being shared every time you call Roku_Ads(). I.e. RAF is already smart and does not create new instances on each invocation. To throw a buzzword, do you know the “signleton pattern”? RAF is a singleton already.

“EnTerr” wrote:

“mape” wrote:
That is already done internally, it is being shared every time you call Roku_Ads(). I.e. RAF is already smart and does not create new instances on each invocation. To throw a buzzword, do you know the “signleton pattern”? RAF is a singleton already.
Got it, thank you.