Forum Discussion

btpoole's avatar
btpoole
Channel Surfer
9 years ago

rsgNode & Task

Is it possible to pass the rsgNode to a task? I have a rgsnode for a grid that is populated by a parse that has to be executed in a task. The code is not actually in the task but is in a function included in the task.  Part of the function references the rsgNode of the grid for such things as column widths, itemfocus and others,  The code looks something like the following.  I need to finda a way to pass the m.programmarkupgrid to the task to be referenced in the function. I can't just run the function without execution timeout. Thanks for any help

step1.brs
function prearray()
m.ContentTask_preslot = createObject("RoSGNode","GridContent")
m.ContentTask_preslot.array1=m.array1data
m.ContentTask_preslot.array2=m.array2data
m.ContentTask_preslot.array3=m.array3data
m.ContentTask_preslot.ObserveField("state", "pre_grid")
m.ContentTask_preslot.control = "RUN"
end function

function setGridContent()
?"in setGridContent--"
m.array1=m.top.array1
m.array2=m.top.array2
m.array3=m.top.array3
gridx=1
rows=0
temp=[]

m.programmarkupgrid.numColumns= m.array3
?"NUMBER OF COLUMNS>>>>>>>>>>>>>>>>>>>>>>>>> "m.programmarkupgrid.numColumns
for i = 0 to m.programmarkupgrid.numColumns
temp[i]=312
end for
m.programmarkupgrid.columnwidths=temp
end function





mytask.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="GridContent" extends="Task">

  <interface>
        <field  id = "array1"  type = "roArray" />
      <field id = "array2"   type = "roArray" />
     <field id = "array3"   type = "roArray" />
    </interface>
    <script type="text/brightscript" uri="pkg:/source/step1.brs" />
 
<script type="text/brightscript">
<![CDATA[

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

function taskRun() as void
?"in GridContent Task"
setGridContent()
end Function


  ]]>
  </script>
</component>

9 Replies

  • destruk's avatar
    destruk
    Streaming Star
    I'd add a field to the task interface - that way you can store your value into that field and the task can play with it.
    Yeah, just tested, that works.
    For your xml interface field add --
     <field id="share" type="node" />

    That will allow you to throw a value to the task node using the share field for an roSGNode object.
  • btpoole's avatar
    btpoole
    Channel Surfer
    Passing the individual fields not a problem, was wondering if the rsgnode could be visible to the task as a whole. I guess from what I have tried only the individual fields can be passed.
    Thanks any way
  • destruk's avatar
    destruk
    Streaming Star
    I don't think I understand what your concern is.
    In your main scenegraph thread you can grab any node in the app by doing a m.mynodeineed=m.top.findnode("id name") provided it is specified in the xml markup as a required object to load - and then you can access it and modify anything it contains or displays or controls from that main scenegraph thread.
    In the component threads you can grab any node from the main app by doing a m.mynodeineed=m.global.findnode("id name") - provided it has been loaded in the main thread (AFIK?) and then you can access it and modify anything it contains or displays or controls from that component thread.
    In the component or task threads, if something is specified in its own xml, you would use m.top.findnode to grab it and utilize it.
    The individual values of a node, once you have found it, can be edited anywhere.

    Just how many items are you trying to parse or build here?

    Would this code make any sense to you?
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- ***** gridcontent.xml ***** -->
    <component name="GridContent" extends="Task">

    <interface>
    <field id="array1" type="roArray" />
    <field id="array2" type="roArray" />
    <field id="array3" type="roArray" />
    <!-- added status field which will notify observers every time the value changes -->
    <field id="status" type="string" alwaysnotify="TRUE"/>
    </interface>
    <script type="text/brightscript" uri="pkg:/components/gridcontent.brs" />
    </component>


    '**** gridcontent.brs
    Sub init()
    m.top.functionName="setGridContent"
    m.programmarkupgrid=m.global.findnode("programmarkupgrid") 'We're going to use this in SetGridContent() so we need to find it
    End Sub

    Function setGridContent()
    Print "in setGridContent--"
    m.array1=m.top.array1
    m.array2=m.top.array2
    m.array3=m.top.array3 'if m.array3 is an array then we need to reference by numerical index or associative index or for each unless we're just referencing the array as the entire object
    gridx=1 'this variable isn't used or referenced
    rows=0 'this variable isn't used or referenced
    temp=[] 'creates an array called temp
    m.programmarkupgrid.numColumns=m.array3
    Print "NUMBER OF COLUMNS>>>>>>>>>>>>>>>>>>>>>>>>> "+(m.programmarkupgrid.numColumns.count()-1).ToStr()
    For i=0 To (m.programmarkupgrid.numColumns.count()-1) 'this expects a numerical value for m.programmarkupgrid.numColumns so add a "count()-1"
    temp[i]=312
    Next
    m.programmarkupgrid.columnwidths=temp 'This sets columnwidths to the newly populated array 'temp'
    End Function





    'Calling thread to initiate the task
    Function prearray()
    m.ContentTask_preslot=createObject("RoSGNode","GridContent")
    m.ContentTask_preslot.array1=m.array1data 'this loads the gridcontent component's array1 field with the m.array1data conent
    m.ContentTask_preslot.array2=m.array2data 'this loads the gridcontent component's array2 field with the m.array2data conent
    m.ContentTask_preslot.array3=m.array3data 'this loads the gridcontent component's array3 field with the m.array3data conent
    m.ContentTask_preslot.ObserveField("staus","pre_grid") 'this monitors for a change in the status field and then jumps to the pre_grid function in the current thread
    m.ContentTask_preslot.control="RUN"
    End Function

  • btpoole's avatar
    btpoole
    Channel Surfer
    "destruk" wrote:
    I don't think I understand what your concern is.
    In your main scenegraph thread you can grab any node in the app by doing a m.mynodeineed=m.top.findnode("id name") provided it is specified in the xml markup as a required object to load - and then you can access it and modify anything it contains or displays or controls from that main scenegraph thread.
    In the component threads you can grab any node from the main app by doing a m.mynodeineed=m.global.findnode("id name") - provided it has been loaded in the main thread (AFIK?) and then you can access it and modify anything it contains or displays or controls from that component thread.
    In the component or task threads, if something is specified in its own xml, you would use m.top.findnode to grab it and utilize it.
    The individual values of a node, once you have found it, can be edited anywhere.

    Just how many items are you trying to parse or build here?

    Would this code make any sense to you?
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- ***** gridcontent.xml ***** -->
    <component name="GridContent" extends="Task">

    <interface>
    <field id="array1" type="roArray" />
    <field id="array2" type="roArray" />
    <field id="array3" type="roArray" />
    <!-- added status field which will notify observers every time the value changes -->
    <field id="status" type="string" alwaysnotify="TRUE"/>
    </interface>
    <script type="text/brightscript" uri="pkg:/components/gridcontent.brs" />
    </component>


    '**** gridcontent.brs
    Sub init()
    m.top.functionName="setGridContent"
    m.programmarkupgrid=m.global.findnode("programmarkupgrid") 'We're going to use this in SetGridContent() so we need to find it
    End Sub

    Function setGridContent()
    Print "in setGridContent--"
    m.array1=m.top.array1
    m.array2=m.top.array2
    m.array3=m.top.array3 'if m.array3 is an array then we need to reference by numerical index or associative index or for each unless we're just referencing the array as the entire object
    gridx=1 'this variable isn't used or referenced
    rows=0 'this variable isn't used or referenced
    temp=[] 'creates an array called temp
    m.programmarkupgrid.numColumns=m.array3
    Print "NUMBER OF COLUMNS>>>>>>>>>>>>>>>>>>>>>>>>> "+(m.programmarkupgrid.numColumns.count()-1).ToStr()
    For i=0 To (m.programmarkupgrid.numColumns.count()-1) 'this expects a numerical value for m.programmarkupgrid.numColumns so add a "count()-1"
    temp[i]=312
    Next
    m.programmarkupgrid.columnwidths=temp 'This sets columnwidths to the newly populated array 'temp'
    End Function





    'Calling thread to initiate the task
    Function prearray()
    m.ContentTask_preslot=createObject("RoSGNode","GridContent")
    m.ContentTask_preslot.array1=m.array1data 'this loads the gridcontent component's array1 field with the m.array1data conent
    m.ContentTask_preslot.array2=m.array2data 'this loads the gridcontent component's array2 field with the m.array2data conent
    m.ContentTask_preslot.array3=m.array3data 'this loads the gridcontent component's array3 field with the m.array3data conent
    m.ContentTask_preslot.ObserveField("staus","pre_grid") 'this monitors for a change in the status field and then jumps to the pre_grid function in the current thread
    m.ContentTask_preslot.control="RUN"
    End Function



    Makes perfect sense. I believe you answered my question in that making the node global or defining it in its own xml. Since the post I kept working around and was able to pass only the needed info to the task. All of my rsgnodes are defined in a single xml file, probably not great way to do it but until recently worked very well, they loaded when script initialized and were waiting on orders. I did think about making global but was just hoping that the rsgnode as a whole would be seen by the task. Thank you for taking the time to spell it out with examples. Part of the example code I posted was for a reference only and not the exact code and the majority of the function was left out (ie gridx=1 stuff)  because it didn't apply to my problem or was "clutter". .  Thanks again.
  • destruk's avatar
    destruk
    Streaming Star
    No problem btpoole - I looked over the wiki pages again and it appears nodes created within a task node are unable to be exported outside the task node?  I'm not sure if I read that right.  I wasn't able to use interface fields of a task node's xml if they were objects 😞  This makes sense as they don't want some objects to be allowed outside a task node so it's easier to block every possible object than to have to look at what it is before deciding.
  • "btpoole" wrote:
    Makes perfect sense. I believe you answered my question in that making the node global or defining it in its own xml. Since the post I kept working around and was able to pass only the needed info to the task. All of my rsgnodes are defined in a single xml file, probably not great way to do it but until recently worked very well, they loaded when script initialized and were waiting on orders. I did think about making global but was just hoping that the rsgnode as a whole would be seen by the task.

    Ah? I did not get that - are you saying that you were defining multiple custom components in a single XML file and that was working (no error) - plus they were sharing data or scriprs somehow? I haven't seen that documented as supported and have no idea what the outcome might be - but do tell more - did it work before? Does it still work? How does it differ from doing 1-component-per-file?
  • "destruk" wrote:
    I looked over the wiki pages again and it appears nodes created within a task node are unable to be exported outside the task node?  I'm not sure if I read that right.  I wasn't able to use interface fields of a task node's xml if they were objects 😞  This makes sense as they don't want some objects to be allowed outside a task node so it's easier to block every possible object than to have to look at what it is before deciding.

    That shouldn't be the case - not sure, but does not sound right. Can you show minimal example and/or point to exact doco wording?
  • destruk's avatar
    destruk
    Streaming Star
    From the docs --
    Task Node Thread Fully-Owned Node Objects

    Task node threads can create node and ContentNode node objects that are fully owned by the Task node thread. These node objects cannot be parented to unowned nodes, or be set as fields of unowned nodes. Entire trees of the nodes fully owned by the Task node thread may be created.
  • btpoole's avatar
    btpoole
    Channel Surfer
    "RokuNB" wrote:
    "btpoole" wrote:
    Makes perfect sense. I believe you answered my question in that making the node global or defining it in its own xml. Since the post I kept working around and was able to pass only the needed info to the task. All of my rsgnodes are defined in a single xml file, probably not great way to do it but until recently worked very well, they loaded when script initialized and were waiting on orders. I did think about making global but was just hoping that the rsgnode as a whole would be seen by the task.

    Ah? I did not get that - are you saying that you were defining multiple custom components in a single XML file and that was working (no error) - plus they were sharing data or scriprs somehow? I haven't seen that documented as supported and have no idea what the outcome might be - but do tell more - did it work before? Does it still work? How does it differ from doing 1-component-per-file?

    Maybe I used wrong terminology. My single xml file is similar to this:
    HomeScene.xml
    <?xml version="1.0" encoding="utf-8" ?>
    <!--********** Copyright 2016 Roku Corp.  All Rights Reserved. **********-->
    <component name="HomeScene" extends="Scene" xsi:noNamespaceSchemaLocation="https://devtools.web.roku.com/schema/RokuSceneGraph.xsd">

    <script type="text/brightscript" uri="pkg:/source/main.brs" />
    <children>
    <!--******************************************** -->
    <!--INITIAL TOPLOGO AND BACK GROUND -->

      <Overhang
        title = ""
        showOptions = "true"
        height= "115"
        logoBaselineOffset="15"
        optionsAvailable = "true" />


        <Rectangle
                id="background"
                color="#000000"
                width="1280"
                height="720"
                translation="[0,97]"
                 />
       <Poster
           id = "TopLogo"
           translation = "[10, 0 ]"
           width = "250"
           height = "97"
           uri= "pkg:/images/beta_overhang_logo.png"
           visible= "true">
        </Poster>
    <!--******************************************** -->

    <Label
      id = "instructLabel"
      text = "" />

      <Poster
          id="Background"
          width="1280"
          height="720"
          />
    <!--************************************************  -->

    <!--  -->
     <Label
     id = "ActivationDate"
     height = "50"
     width = "300"
     text = ""
     color="#f44242"
     font = "font:MediumBoldSystemFont"
     translation = "[300,20]"
     visible= "false"
      />

    <!--************************************************  -->
    <!--  ACTIVATION DIALOG-->
    <Label
    id = "Message"
    height = "50"
    width = "600"
    wrap="true"
    text = ""
    numLines="2"
    color="#f1f442"
    font = "font:MediumBoldSystemFont"
    translation = "[290,60]"
    visible= "false"
     />
     <Label
       id = "theMessage"
       text = "" />

       <Poster
           id="MessageBackground"
           width="1280"
           height="720"
           />
    <!--************************************************  -->
        <MarkupList
            id="ChannelList"
            itemComponentName="ChannelListItem"
            focusFootprintBitmapUri= "pkg:/images/channellist.9.png"
            itemSize="[65,70]"
            itemSpacing="[0, 5]"
            translation="[40,360]"
            numRows= "4"
            numColumns="1"
        />


      <MarkupGrid
          id= "TimeList"
        itemComponentName="TimeListItem"
          columnWidths="[300,300,300,300]"
          itemSize="[15,40]"
          rowHeights="[15, 20]"
        numColumns="4"
        numRows="1"
          itemSpacing="[0,50]"
        translation="[220,320]"
          />

        <MarkupGrid
          id= "ProgramGrid"
          itemComponentName="ProgramGridItem"
          focusBitmapUri= "pkg:/images/1focus_grid.9.png"
          numRows="4"
          itemSpacing="[4,6]"
          numColumns="1"
          translation= "[160, 350]"
          columnWidths="[312]"
          itemSize="[25,70]"
          fixedlayout="false"
          drawFocusFeedbackOnTop="false"
          />
    </children>
    </component>

    There are more in there than shown.  After the first main.brs runs, the HomeScene is created using the Home.xml In the home.brs I am setting the rsgnodes
    m.ProgramMarkupGrid = m.top.findNode("ProgramGrid")

    and so on. My initial problem was making the m.ProgramMarkupGrid visible in a task. I knew I could pass the fields to the task, do whatever I needed to the value and return back a value on the other side to utilize. In this particular case I was setting column widths based on the result of the task. I was hoping to call the m.ProgramMarkupGrid directly from the task but I was unable to do so. To get it to work I passed only the fields needed.