Forum Discussion

wst54321's avatar
wst54321
Visitor
9 years ago

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 !
  • 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
  • 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.

     
  • 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.
  • 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.
  • 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.
  • 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.