Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
wst54321
Visitor

RAF implemented in SceneGraph component thread issue.

Hi, All

I am trying to use the RAF in my components' brs instead of the main.brs, but I find both the getAds() and showAds call need a independent task node (which means been treated as and roUrlTransfer?).

Currently, my code logic is as follows :

1. In main.brs, I init the "HomeScene", set a roMessagePort
2. IN "HomeScene", I have a child which is a customized component extends "Video", called "PlayerNode"
3. In the "PlayerNode", I init the a "AdTask" node in order to make "getAds()"

However, here again after I get response, I can t call showAds here coz it gives me an error msg, seems the showAds also requires a seperate task node to accomplish the task

what is the correct way if I don t wanna put code in the main thread and I dont wanna a nested task node structure , I think I must think something wrong.

btw , after all, I also wanna know , how can my msgPort in the main.brs be able to listen to the "adPods" field which is defined in the "AdTask" node ? if I can get that to work, at least I can do the rest of the logic in the main thread, though the cons are it makes the ads handle code everywhere in the proj....( 😞 )


Library "Roku_Ads.brs"

sub init()
m.top.functionName = "getAdsContents"
end sub

sub getAdsContents()

adIface = Roku_Ads()
print "Roku_Ads library version: " + adIface.getLibVersion()
adIface.setAdPrefs(true,2)
adIface.setDebugOutput(true) 'for debug pupropse

adPodsArray = adIface.getAds()

end sub


Thanks to any help !
0 Kudos
8 REPLIES 8
TheEndless
Channel Surfer

Re: RAF implemented in SceneGraph component thread issue.

Unfortunately, RAF does not (yet?) have native SceneGraph integration, so you have to jump through a few hoops to get it working.  Take a look at the RAF/SG sample channels here: https://sdkdocs.roku.com/display/sdkdoc/Roku+Advertising+Framework#RokuAdvertisingFramework-SampleCh...
My Channels: http://roku.permanence.com - Twitter: @TheEndlessDev
Instant Watch Browser (NetflixIWB), Aquarium Screensaver (AQUARIUM), Clever Clocks Screensaver (CLEVERCLOCKS), iTunes Podcasts (ITPC), My Channels (MYCHANNELS)
0 Kudos
gsarath
Visitor

Re: RAF implemented in SceneGraph component thread issue.

Even I am also looking for same implementation of playing Ads from Scene Graph Thread or Task Node Thread. 

Can you please confirm whether we can "Integrate ads in Scene Graph Complements instead of Bright Script?", as per my analysis I have figured out that calling showAds() in either Scene Graph Thread or Task Node Thread gives the below mentioned error:
roImageCanvas: class PLUGIN on thread RENDER|MARKUP: roku_ads_lib:/Roku_Ads.brs(2614)


Even The example shared in Roku Documentation covers only integrating ads in Brightscript Main Thread:
https://sdkdocs.roku.com/display/sdkdoc ... leChannels
https://sdkdocs.roku.com/download/attac ... 119&api=v2

I am sharing the sample code of the test application for integrating the Ads in Task for reference, to check whether I am missing any integration steps.
 
Below mentioned is the code of the Sample Application - appMain.brs, VideoScene.xml and AdTask.xml:
Sub Main()
    playVideo()
End Sub

Function playVideo()
    screen = CreateObject("roSGScreen")
    m.port = CreateObject("roMessagePort")
    screen.setMessagePort(m.port)
    scene = screen.CreateScene("videobannerScene")
    screen.show()
    while(true)
        msg = wait(0, m.port)
        msgType = type(msg)
        if msgType = "roSGScreenEvent"
            if msg.isScreenClosed()
                exit while
            endif
        endif
    end while
End Function


<?xml version="1.0" encoding="utf-8" ?> 

<!--********** Copyright 2015 Roku Corp.  All Rights Reserved. **********-->

<component name="videobannerScene" extends="Scene" >

<script type="text/brightscript" >
<![CDATA[

sub init()
    initializeTask()
   setVideo()
end sub

function initializeTask()
    m.adTask = CreateObject("roSGNode", "AdTask")
    m.adTask.control = "RUN"    
end function

function setVideo() as void    
   videoContent = createObject("RoSGNode", "ContentNode")
   videoContent.url = "https://roku.s.cpl.delvenetworks.com/media/59021fabe3b645968e382ac726cd6c7b/60b4a471ffb74809beb2f7d5a15b3193/roku_ep_111_segment_1_final-cc_mix_033015-a7ec8a288c4bcec001c118181c668de321108861.m3u8"
   videoContent.title = "Closed Captions in Scene Graph"
   videoContent.streamformat = "hls"

   m.video = m.top.findNode("musicvideos")
   m.video.content = videoContent
   m.video.notificationinterval = 1

   m.video.setFocus(true)
   m.video.control = "play"
end function

]]>
</script>

<children>
    <Video id="musicvideos" width="1280" height="720" translation="[0,0]" />
</children>
</component>


<?xml version="1.0" encoding="utf-8" ?> 
<component name="AdTask" extends="Task" >
<script type="text/brightscript" >
<![CDATA[
Library "Roku_Ads.brs"
sub init()
   m.top.functionName = "initAds"
end sub

function initAds()
   adIface = Roku_Ads()
   adUrl = "file://pkg:/images/ads.xml"
   adIface.setAdUrl(adUrl)
   ads = adIface.getAds()
    if ads <> invalid and ads.count() > 0
        For Each adPod In ads
           if adPod["rendersequence"] = "preroll"
               adIface.showAds(ads)
           end if
       End For
   end if 
end function
]]>
</script>
</component>

I am able view traces of Brightscript Main Thread in 8085, Render Scene Graph Thread in 8089 and Task thread in 8090 as mentioned in the roku documentation:
https://sdkdocs.roku.com/display/sdkdoc ... plications
0 Kudos
RobSMS
Visitor

Re: RAF implemented in SceneGraph component thread issue.

I just figured it out a few days ago...   I'm going to explain as simply as possible.  These code items probably won't work, but are included to serve as an example.

I also want to point out that this is just what I've learned.  There may be better ways to do it, but this worked for me.   I'd love to hear suggestions if anyone has anything to offer.

Make sure you have added the RAF Library to your manifest
bs_libs_required=roku_ads_lib


And to the first line in your main.brs (Main thread)
Library "Roku_Ads.brs"


Then you need to setup a few fields in your main scene.  
<field id="adPlayFlag" type="bool" alwaysNotify="true" />
<field id="adFinishedPlaying" type="bool" alwaysNotify="true" />


Then in your main thread (generally main.brs) initialize RAF and add an observeField that points to the msg port
m.adIface = Roku_Ads()
m.adIface.setAdUrl()
scene.observeField("adPlayFlag", m.port)


In your while loop for the main thread
while(true)
msg = wait(0, m.port)
msgType = type(msg)

' Watches adPlayFlag for a "true" result then plays advertisement.
if msgType = "roSGNodeEvent"
if (msg.GetField() = "adPlayFlag") and scene.adPlayFlag = true
m.adPods = m.adIface.getAds()
if m.adPods <> invalid and m.adPods.count() > 0
playContent = m.adIface.showAds(m.adPods)
end if

if playContent
' Play video flag
scene.adFinishedPlaying = true
end if
end if
end if
end while


And now for the explanation....

When a user selects a piece of content to play, I set the "adPlayFlag" to true.   This triggers the RAF function in the main thread and plays the ad.

When the ad has finished playing, I set the "adFinishedPlaying" flag to true.   

I then have a observeField that that triggers the video to play when "adFinishedPlaying" is marked to true.

The above code is just an example to give you a basis of how I managed to get RAF working.  There is obviously a bit more that you will need to include [size=100](ie: "Back" button presses while ads play), but this should get you started. [/size]

Hope this helps... I'll answer any questions as best as I can.

 
Need Apps Templates? Content Management for OTT/IPTV? Check me out @ http://rovidx.com
0 Kudos
gsarath
Visitor

Re: RAF implemented in SceneGraph component thread issue.

@RobSMS: Thanks for your reply. I am able to play the RAF content in Brightscript Main Thread as mentioned in the example shared by Roku. But I am looking for playing the Ad content Scene Graph Contents either from Scene Graph Thread or Task Node Thread. 

Please confirm if you are aware this approach.
0 Kudos
RobSMS
Visitor

Re: RAF implemented in SceneGraph component thread issue.

No, you can not run RAF within SG or Task threads.   It must be run in the main thread only.   My example is the only way that I've found to render the ads while using SG.
Need Apps Templates? Content Management for OTT/IPTV? Check me out @ http://rovidx.com
0 Kudos
RPW68
Visitor

Re: RAF implemented in SceneGraph component thread issue.

Has anyone had any luck getting this to work with the Video-Player example?

I have been trying to get the example above integrated into it but can't get it to work.  I am setting the "adPlayFlag" to true right before the video plays but it isn't executing any of the code in the main While Loop.  I am fairly certain that the problem, for me, is that I am not updating the field properly  The main scene for the Video-Player example is VideoScene which is where I setup the "adPlayFlag" and "adFinishedPlaying" fields (per the example):


<field id="adPlayFlag" type="bool" alwaysNotify="true" />
<field id="adFinishedPlaying" type="bool" alwaysNotify="true" />


The video is played from the "SpringBoard" scene and when I try to set "adPlayFlag" to true either an error occurs or nothing happens:

This results in "Invalid value for left-side of expression.":
m.scene.adPlayFlag = true



This results in "Use of uninitialized variable."

scene.adPlayFlag = true

And if I do this, nothing happens (I don't get an error, but it doesn't execute RAF code within Main.brs):

adPlayFlag = true



I am sure that this is something very basic but I am still adjusting to working in Scene Graph.

Any suggestions, comments, or help would be greatly appreciated.
0 Kudos
RPW68
Visitor

Re: RAF implemented in SceneGraph component thread issue.

I finally got this working (kind of...I'll explain at the end) for the scene-graph video-player sample that is found here.

I basically took what was suggested before and then tweaked it so that it would work in this example.  Here is what I had to do:

1.  Add RAF Library to your manifest.
2.  Added the library to main.brs.
3.  Rather than setup the fields in the main scene, I did this within main.brs:

  m.global.addField("adPlayFlag", "bool", true)
  m.global.addField("adFinishedPlaying", "bool", true)
  m.global.addField("videoEventData", "int", true)

4. I had to modify the next step a little (added to the ShowHeroScreen sub of main.brs):

  m.adIface = Roku_Ads()
  m.adIface.setAdUrl()
  m.global.observeField("adPlayFlag", m.port)


5.  For the while look of the main thread (main.brs), I make it look like this:

  while(true)
    msg = wait(0, m.port)
    msgType = type(msg)
    if msgType = "roSGScreenEvent"
      if msg.isScreenClosed() then return
    end if
    if msgType = "roSGNodeEvent"
     if (msg.GetField() = "adPlayFlag") and m.global.adPlayFlag = true
          m.global.setField("adPlayFlag","false")
          m.adPods = m.adIface.getAds()
          if m.adPods <> invalid and m.adPods.count() > 0
               playContent = m.adIface.showAds(m.adPods)
          end if
         
          if playContent
             ' Play video flag
             m.global.setField("adFinishedPlaying","true")
          end if
     end if
    end if
  end while


6. On the SpringBoard.brs file I added the following to the onItemSelected sub:

  m.global.setField("videoEventData",event.getData())
  m.global.setField("adPlayFlag","true")
  m.global.observeField("adFinishedPlaying", "PlayVideo")


7.  And finally, I added the following function to the SpringBoard.brs file:

function PlayVideo() as void
  m.global.setField("adFinishedPlaying","false")
  m.Video.control = "play"
  if m.global.getField("videoEventData") <> 0 then m.Video.seek = m.top.seekposition
  m.SpringDetails.visible = false
  m.Video.visible = true
  m.Video.setFocus(true)
end function

With these slight changes, it works for me using the referenced scene graph video-player example....Mostly.  I am running into a problem where it won't play the ad a second time and I get the following error:  RAF 1.8; render failure: failed to create media player
I am not sure what is causing this problem.  From other posts it sounds like there is already another video player active that is interfering with it.  I will post something when I figure it out.  In the meantime, please offer your comments or suggestions.
0 Kudos
RPW68
Visitor

Re: RAF implemented in SceneGraph component thread issue.

Finally...To get past the latest problem (RAF 1.8; render failure: failed to create media player), you need to modify the onKeyEvent function within SpringBoard.brs so that it stops and doesn't pause:


function onKeyEvent(key as String, press as Boolean) as Boolean
  print "in SimpleVideoScene.xml onKeyEvent ";key;" "; press
  if press then
    if key = "back"
      print "------ [back pressed] ------"
      if m.Video.visible
        m.Video.control = "stop" 

With this and the previous changes, I seem to have it fully working for the SG video-player example that is available on GitHub.
0 Kudos