0

How to use m in a .brs file executed by Run() function

Hi everyone,

I'm executing .brs files by using Run() function and it works fine.

The problem is when I need to use m in the .brs file executed by Run() function, in this file the m is not defined.

I tried to send the m as parameter but the player crashes and restart even if it is not used in the .brs file executed by Run()

And the question is: How can I access to m from this file?

Thank you

24 comments

  • 0
    Avatar
    Bright Scripters

    I have never used the Run() function, but am curious about your question.

    The m object has special meaning, which might make things harder to control. Typically m would be the parent content, which could be assigned to another variable.

     

    From what you are describing, I understand that you are doing something like this

     

    Run("myScript.brs", m)

     

    and in myScript.brs you somethimes attempt something like this

     

    DoSomethingWith(m)

    or

    m.SomeMethod()

     

    Could the crash be a result of missing argument in the definition of Main() inside myScript.brs?

     

    Sub Main(ParentContext)

    print "ParentContext is effectively m of the calling context"

    End Sub

     

    If it is a specific object you need access to from myScript.brs, you could pass that object, instead of m. Like so:

     

    Run( "myScript.brs", m.TheObjectYouNeedAccessTo )

     

    Not sure if I got it right, so please share more info on your use case, and what it is you need access to through m.

     

    Doesn't the serial port (or ssh) debugger give any info about the reason for crashing?

     

     

     

     

     

  • 0
    Avatar
    Horacio Cruz

    Hi,

    Yes Its what Im doign: Run("myScript.brs", m)

    And about your question: Could the crash be a result of missing argument in the definition of Main() inside myScript.brs?, no I have defined the function correct and even if I don use the m object in this function the player crashes, in fact in another test I sent the m as an element of an array and the player crashes, if I dont send the m in the array the player works perfect

    Now Its what Im doing:

    Im trying is run NodeJS like this:

        r = CreateObject("roRectangle", 0,0,1920,1080)
        random = Rnd(5000)
        Print "random = ";random
    
        is = {
            port: random
        }
        config = {
            nodejs_enabled: true
            inspector_server: is
            brightsign_js_objects_enabled: true
            url: "file:///sd:/nodejs/index.html"
        }
        m.h = CreateObject("roHtmlWidget", r, config)
        m.h.Show()

    And when I execute this from my main .brs it works fine, but only if I execute this with the m, I mean if I execute it without m like this code NodeJS is not running:

        h = CreateObject("roHtmlWidget", r, config)
        h.Show()

    And that is my issue, I need to load NodeJS from a .brs file(not from the main .brs) and in those files I have not m, do you have any idea how can I init NodeJS in a .brs file executed with Run() function?

    But as you said: If it is a specific object you need access to from myScript.brs, you could pass that object, instead of m. Yes I think it is a possible option, thank you for the tip.

     
     
  • 0
    Avatar
    Bright Scripters

    From what you are showing, the challenge is keeping the roHtmlWidget instance alive, after exiting from the external script.

     

    The documentation states: "The called script may also return arguments to the caller script.". 

    Use of m is making thing confusing, so don't use m inside myScript.brs. Instead do something like:

     

    Run("myScript.brs", m)

     

    Sub Main( ParentContext As Dynamic)

     

    ParentContext.h = CreateObject("roHtmlWidget", r, config)
    ParentContext.h.Show()

    End Sub

     

    BA Plugins are used more often in such scenarios.

    Have you considered starting node from a BA plugin, instead of through RUN()?

    https://github.com/brightsign/node.js-starter-project

     

     

     

     

  • 0
    Avatar
    Horacio Cruz

    Yes I have tried that, but the problem is that if I execute this:
    Run("myScript.brs", m)

    In that moment the player crashes when I send the m

    Now, what Im doing is: Im exeuting many .brs files via Run() sending UDP messages, and the only thing I response in myScript.brs(the one that should "loads" NodeJS) is a flag to say to my main .brs that executes a function that loads NodeJS the trick is thah in this main file the m exists, and because of it: works

    Im not shure if it is the best way, but al leats It works.

    I have one more question to reload he NodeJS in the doc says this here

    "Reloading a page which has Node.js enabled can be classified as an undefined behavior. The recommended method for restarting a Node instance is to destroy and rebuild the roHtmlWidget"

    How can I destroy the roHtmlWidget?, Do I need to set to null or something like that my instance?

     

    Than you Bright Scripters for all your replies

  • 0
    Avatar
    Bright Scripters

    When you call Run("myScript.brs", m)

    What is m at that moment?

     

    Also very important; Are you using serial or ssh debugging? Ideally, when the code stops, you would have access to the command line debugger, so you can understand exactly what is failing.

     

    Destroying a BrightScript object is done by assigning it to invalid.

    Example:

    ParentContext.h = CreateObject("roHtmlWidget", r, config)

     

    some code...

     

    ' Destroy roHtmlWidget

    ParentContext.h = invalid

     

    Are you using BrightAuthor?

    Would it be possible for you to provide a download link to the codebase for review?

     

  • 0
    Avatar
    Horacio Cruz

    Hi I use SSH, but Im running an infinite while to receive UDP messages everytime, and because of it I can't see the log.

    Thank you to telling me how to destroy the object, im prrety new ussing brisghtscript

    I used BA only to create a basic autorun and I create myplugin.brs, and in this is where Im coding.

    You can see the code here

    You can notice I added "I think" important blocks of comment of the code in lines: 148, 155, 164 and 168 of the file: myplugin.brs

    And in line 18 in runNodeJS.brs

    I really really appreciate your help

  • 0
    Avatar
    Bright Scripters

    "I use SSH, but Im running an infinite while to receive UDP messages everytime, and because of it I can't see the log."

     

    Having access to the debugger, is essential for this type of development. It is best that you gain access to the debugger, before trying anything else. The fact that cannot see the debugger, might be an indication of something fundamental that needs to be addressed.

     

    Just in case you have not enabled debug mode, here is how.

     

    Publish a stable presentation to the player

    Connect with ssh to the player

    On the player, press SVC button

    Expect ssh to show the interactive debugger command line prompt

    In ssh, type "exit" (without quotes) and press ENTER

    Expect to see the BrightSign interactive command line prompt

    In ssh, type:

    "script debug on" (without quotes)

    press ENTER

     

    Confirm that the player is in debug mode:

    In ssh type

    "script debug" (without quotes)

    Watch the output

     

    The player is now in debug mode, and should not reboot upon a coding error. Instead of crashing, the player would provide some useful info in the the debugger.

     

    To start the presentation type:

    "script autorun.brs"

    ENTER

     

    Question: Are you making changes to the autorun.brs that BrightAuthor publishes?

     

     

  • 0
    Avatar
    Horacio Cruz

    Hi, I have disabled the infinite while and I only execute the function like this Run("runNodeJS.brs", params, m), and of course the player crashes, in other tests Im able to see the deburg mode, but in this particular case I cant, the player really crashes when execute this function and it reloads and my ssh connections finish, I cant see the log, but the reason is that Im waiting for udp messages with WaitMessage() function and because of that I cant enter the debug mode, also I tried to do connecting a kewyboard, but the result is the same the code has a wait() function and also I cant enter the debug mode, beacuse Its waiting.

    Do you have any idea how can I enable the debug mode pressing SVC button and after that execute the run() function with no having a waiting() function?

    About your question:

    Are you making changes to the autorun.brs that BrightAuthor publishes?

    Nop, Its the origina autorun by BA.

    Thank you

  • 0
    Avatar
    Bright Scripters

    You have an infinite loop, and a waitMessage(0) without timeout. Which is why the debugger is not getting an opportunity to show any info.

     

    You should never have an infinite loop in your code.

     

    In Function myplugin_ProcessEvent(event As Object)

    add an else if block like so

     

    if event["EventType"] = "TV_POWER_UPDATED" then
    ? "--------Llega TV_POWER_UPDATED"
    end if

    else if type(event) = "roDatagramEvent" then

    print "UDP event found"

     

    else if type(event) = "roTimerEvent" then

    if type(m.snapshotsTimer) = "roTimer" then

     

    Your roDatagramReceiver object would need to be set to the s.msgPort  message port.

     

    Think of the CPU context as something you borrow, instead of own.

  • 0
    Avatar
    Horacio Cruz

    Uuuuuoooooo, I think that "if" is the trick, and with this I avoid the infinite while and I will be able to see the debug mode, my problem since I read your post is that I am no able to reach the myplugin_ProcessEvent() function when I send an UDP mesage(not only dont reach else if type(event) = "roDatagramEvent" then, just dont reach the myplugin_ProcessEvent() function) I dont know why, I tried with the keyboard and when I hit a key this reah the function, but with an UDP dont, Im working with this, and after I reach that funcion Im going to see the log in the debun mode about the crash of sending m as parameter, and of course Im going to post to you the result

    Thank you so so so much.

  • 0
    Avatar
    Bright Scripters

    Can you send over the current state of your code, including the BA project .bpf file?

    Are you using a remote repo?

     

    To be able to capture a UDP message, the roDatagramReceiver object must reside at a scope where it can persist. Something like

     

    s.receiver = CreateObject("roDatagramReceiver", etc...

     

    My advice is to you is minimize the functionality of the code, and get that to work with access to the debugger, and only then add functionality in small steps. Currently you are attempting to do too much, too fast.

  • 0
    Avatar
    Horacio Cruz

    Can you send over the current state of your code, including the BA project .bpf file?

    Yes I send to you the code and the .bpf file here

    Are you using a remote repo?

    No, I only use the sd card

    To be able to capture a UDP message, the roDatagramReceiver object must reside at a scope where it can persist. Something like

    I was doing it, but I was seting a wrong port, but now Im able to receive UDP messages and manage then in myplugin_ProcessEvent function, and that ugly infinite while now does not exists anymore(really really thank you)

    But I still not seeing the log in debug mode and I did all you told me Yesterday at 08:36, yes the player now does not crashes, but I cant see any log, and this happends only with this particular error, if I have any other error I can successfully watch the log with the error

    To get the error I manage a keyboard event and send the Run(m) in line 102 of myplugin.brs file.

  • 0
    Avatar
    Bright Scripters

    I found that errors that occur in the newPlugin() function, never show in the debugger. Not sure why. It is a fact of life, which BrightSign might be able to improve one day.

    Anything that is executed in newPlugin() would be harder to debug, but carefully positioning print commands as bellow, could help you narrow down cause of errors.

    print "About to initialize"

    s.init()

    print "Successfully initialized"

     

    Looking at runNodeJS.brs

    You have m in the definition of Function Main(m as Object)

    I think that would be asking for trouble.

     

    Try instead

     

    Function Main(ParentContext as Object) '- It does not work
    Print "BRS LOG.... runNodeJS.brs"
    r = CreateObject("roRectangle", 0,0,1920,1080)
    is = {
    port: 3000
    }
    config = {
    nodejs_enabled: true
    inspector_server: is
    brightsign_js_objects_enabled: true
    ' url: "file:///nodejs/index.html"
    url: "file:///sd:/nodejs/index.html"
    ' storage_path: "SD:"
    ' storage_quota: 1073741824
    }
    ParentContext.h = CreateObject("roHtmlWidget", r, config)
    ParentContext.h.Show()
    print "BRS LOG.... NodeJS Started from RUN"
    return "BRS LOG.... NodeJS Started from RUN" 
    End Function

     

     

     

  • 0
    Avatar
    Horacio Cruz

    Yes thank you, that kind of log with Print is what Im doing in many cases

    I tried the code as you suggest with ParentContext and the player crashes.

    I even have tried sending an array with the m into the array and with the simple fact of sending as a part othe array(and I mean: I dont ever get the m from that array in runNodeJS.br) the player crashes, if I dont add to the m to the array the player does not crashes.

  • 0
    Avatar
    Bright Scripters

    Are comments allowed inside an object literal?

     

    config = {
    nodejs_enabled: true
    inspector_server: is
    brightsign_js_objects_enabled: true
    ' url: "file:///nodejs/index.html"
    url: "file:///sd:/nodejs/index.html"
    ' storage_path: "SD:"
    ' storage_quota: 1073741824
    }

     

    I'll explore deeper tomorrow with the code you have provided.

     

    Meanwhile you could try to call init() from a different place, so the debugger can help like so

     

    Function myplugin_ProcessEvent(event As Object) as Boolean

    ' Init once

    if m.OnceOnly = invalid then

       m.init()
       m.OnceOnly = 1
    end if

     

     

     

     

  • 0
    Avatar
    Nick Young

    @Brightscripters

    "I found that errors that occur in the newPlugin() function, never show in the debugger. Not sure why. It is a fact of life, which BrightSign might be able to improve one day."

    I think is because plugin code is called from the autorun using eval() instead of run().

  • 0
    Avatar
    Bright Scripters

    @Nick, thanks for your comment.

    Would be nice to be able to find a workaround if possible, and suggest that as an autorun tweak.

     

    @Horacio

    Looks like Eval() results are logged with PrintDebug(), so there should be clues in the player's log, through either DWS, or serial debugging.

     

    autorun.brs snippet below

     

    for each scriptPlugin inm.scriptPlugins
    initializeFunction$ = "result = " + scriptPlugin.name$ + "_Initialize(m.msgPort, userVariables, m)"
    retVal = Eval(initializeFunction$)

    if type(retVal) = "roList"then
    ' log the failure
    m.diagnostics.PrintDebug("Failure executing Eval to initialize script plugin file: error string was " + retVal[0].ERRSTR + ", line number was " + stri(retVal[0].LINENO) + ", call was " + initializeFunction$)
    m.logging.WriteDiagnosticLogEntry(m.diagnosticCodes.EVENT_SCRIPT_PLUGIN_FAILURE, retVal[0].ERRSTR + chr(9) + stri(retVal[0].LINENO) + chr(9) + scriptPlugin.name$)
    else if retVal <> ERR_NORMAL_END then
    ' log the failure
    m.diagnostics.PrintDebug("Failure executing Eval to initialize script plugin file: return value = " + stri(retVal) + ", call was " + initializeFunction$)
    m.logging.WriteDiagnosticLogEntry(m.diagnosticCodes.EVENT_SCRIPT_PLUGIN_FAILURE, stri(retVal) + chr(9) + scriptPlugin.name$)
    else
    scriptPlugin.plugin = result
    endif
    next
  • 0
    Avatar
    Horacio Cruz

    Hi about your question

    Are comments allowed inside an object literal? Yes its allowed, but now I have removed that code

    I have called init() from myplugin_ProcessEvent as you suggest and the result is the same: I cant see any log

  • 0
    Avatar
    Brandon

    @Horacio
    m isn't intended to be used as a variable.  It's only intended to reference the persistent associative array for the module.

    If you need to pass elements to another function or module, you should copy those elements into a separate associative array or variable.

    See https://docs.brightsign.biz/display/DOC/Program+Statements#ProgramStatements-m_identifier

    @Nick
    Plugins and parsers are integrated via eval() in modern BrightAuthor version autoruns to avoid instant-crash upon execution and putting the player into a reboot loop like older BrightAuthor autoruns did.
    If you enable System Log Debugging and/or Serial Debugging you can get additional information but like in other languages, it is more difficult to track down issues, so you it's best to be verbose in debug/console output and leave yourself a breadcrumb trail to more-easily see where things fail.

    _________________________________________________________________________

    Friendly reminder, the community forum is intended for user-to-user discussion.  It is not regularly monitored. For troubleshooting problems and to ensure a timely answer from a BrightSign representative, please submit a support ticket.

  • 0
    Avatar
    Horacio Cruz

    Hi Brandon, it seem its imposible send m in that Run() function, I think Im gong to assign a value like m.h = CreateObject("roHtmlWidget", m.r, m.config), and then send only m.h

    Thank you all for your patience 

  • 0
    Avatar
    Brandon

    @Horatio
    I wouldn't be surprised if that still crashes.  You should set a separate variable that is not m or part of m to pass.

    _________________________________________________________________________

    Friendly reminder, the community forum is intended for user-to-user discussion.  It is not regularly monitored. For troubleshooting problems and to ensure a timely answer from a BrightSign representative, please submit a support ticket.

  • 0
    Avatar
    Horacio Cruz

    In fact it worked I send the param like this Run("runNodeJS.brs", m.h), no the whole m and the runNodeJS.brs file is: 

     
    Function Main(h  as Object)
        Print "BRS LOG.... runNodeJS.brs"
        r = CreateObject("roRectangle", 0,0,1920,1080)
        is = {
            port: 3000
        }
        config = {
            nodejs_enabled: true
            inspector_server: is
            brightsign_js_objects_enabled: true
            url: "file:///sd:/nodejs/index.html"
        }
        h = CreateObject("roHtmlWidget", r, config)
        h.Show()
        print "BRS LOG.... NodeJS Started from RUN"
        return "BRS LOG.... NodeJS Started from RUN"
    End Function
     
    And of course does not crashes because I did not sent the whole m, It was no my main idea about send all m array, but It worked
     
    Than you again
  • 0
    Avatar
    Bright Scripters

    Thanks for sharing your results.

    I'm noticing that the config object is now clean of any comments.

    Did you find out if comments are allowed inside object literal?

  • 0
    Avatar
    Horacio Cruz

    Oh yes yes,its possible as I said here, but I have removed to avoid any confusion.

    One more time: thank you all for your time and patience, I really really appreciate it

Please sign in to leave a comment.