Home AMX User Forum NetLinx Studio

Optimization needed

I have 64 buttons on panel and i need only 1 event handler for all these buttons. What is the best approach to do it?
Now i have:
DEFINE_CONSTANT
devchan switchbuttons[64] {{dvTP,1},{dvTP,2},...{dvTP,64}}
DEFINE_EVENT
BUTTON_EVENT [switchbuttons]{
    PUSH:{
	do_switch(button.input.channel,button.input.channel/8+1)
    }
}
The problem is: i don't want to enter array of so many devchan's every time i need one handler for many channels. How to make it more simple? I know about code wizard, but i don't like it's method (code becomes really huge).

Comments

  • Here's one way: define a button array in DEFINE_VARIABLE, use a FOR loop in define start to fill the array, something like this;

    FOR (nCount=1;nCount<=64;nCount++)
    btnSwitch[nCount] = nCount

    Then add the following event;

    BUTTON_EVENT [dvTP,btnSwitch]
    {
    //etc
    }

    Only limitation to this approach is that your channels need to be contiguous
  • DHawthorneDHawthorne Posts: 4,584
    I generally do it this way:
    DEFINE_VARIABLE
    
    VOLATILE DEV dvPanels[] = {dvTP1, dvTP2, dvTP...} ;
    VOLATILE INTEGER iBUttons[] = {1, 2, 3, 4, ...} ;
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvPanels, iButtons]
    {
         PUSH :
         {
              STACK_VAR INTEGER iPanelIndex ;
              STACK_VAR INTEGER iButnIndex ;
    
              iPanelIndex = GET_LAST(dvPanels) ;
              iButnIndex = GET_LAST(iButtons) ;
    
              // code here
         }
    }
    

    You can use the sequential numbering feature in Studio to populate the channel array; I usually hand type one line, then cut-and-paste it as many times as I need, then use the numbering tool to set them properly.

    Some of the advantages to this are you can re-use those arrays for different events and in different places. You can make other arrays of the same size to work as look-up tables: I like to make an array with default audio zones per panel, and default volume levels - once I have the index of the panel in my PUSH handler, the same index can be used in the other arrays to get that default data.
  • Optimization needed
    Here's one way: define a button array in DEFINE_VARIABLE, use a FOR loop in define start to fill the array, something like this;

    FOR (nCount=1;nCount<=64;nCount++)
    btnSwitch[nCount] = nCount
    Assuming that you initialize the button array in DEFINE_START, be sure to issue the following Netlinx directive afterward or the dynamic BUTTON_EVENT specification will not work: REBUILD_EVENT(). This forces Netlinx to rebuild the event table at which time the newly created array of buttons will be evaluated and added to the event table.
  • Short method

    Greetings... My first post but thought it was worth weighing in.
    BUTTON_EVENT [dv64, button.input.channel] {
        PUSH:{
    	do_switch(button.input.channel,(button.input.channel / 8) + 1)
        }
    }
    
    Note: the parenthesis make the operator precedence more obvious
  • DHawthorneDHawthorne Posts: 4,584
    kphlight wrote:
    Greetings... My first post but thought it was worth weighing in.
    BUTTON_EVENT [dv64, button.input.channel] {
        PUSH:{
    	do_switch(button.input.channel,(button.input.channel / 8) + 1)
        }
    }
    
    Note: the parenthesis make the operator precedence more obvious
    You don't want to use button.input.channel in the EVENT definition. On start up, it's going to resolve to null because there were no button events yet, so unless you rebuilt the event table on every button press, it would never trigger. IT might work if you rebuilt the event table in mainline, depending on whether mainline directives happen before or after system variables are updated, but that would be horribly inefficient.

    I shy away from using button.input.channel except in the most simple of circumstances. If for any reason you need to adjust the channel assignments in your panel, you've now broken the code. Working from an index lets you make the channels whatever you like, and all you have to do is update the array. It's more work to set up, but far easier to maintain and modify in the future.
  • BUTTON_EVENT [dv64, button.input.channel]

    0 as the channel in a BUTTON_EVENT or CHANNEL_EVENT is the wildcard for "all channels".
    Using button.input.channel is effectively the same as using 0, because at compile time button.input.channel is 0.
    Be aware that 0 works fine for the PUSH and RELEASE handlers, but doesn't work with the HOLD handler.

    What I've been using lately for this problem is Edit menu/Sequentially Renumber Selection.
    Assign it the hotkey Ctrl-Alt-R, and you'll have much easier time renumbering DEVCHAN's.
    See TN 758 http://www.amx.com/techsupport/PDNTechNote.asp?id=758 for an in-depth description.
  • Watch out when using 0 as a parameter of a button event

    As Guy indicated using 0 as a parameter of a button event is like using a wildcard. Please remember that if that is done any button presses for that device (or device array) will be trapped by the button event handler. That's usually not an issue unless you are using system calls in the define program section of your code. Then the system call will never be called since all the button pushes are handled in the button event.

    PDK
  • frthomasfrthomas Posts: 176
    All of this talk about the usage of 0 makes me think you could actually use it to solve the original problem...

    BUTTON_EVENT[dTP, 0]
    {
    PUSH:
    IF (button.input.channel < 65)
    {
    do_switch(...)
    }
    }

    Does not work for HOLD as mentioned + it will eat mainline events, but you can still have other button_events for other channels on dTP and they will be handled. There is a slight performance hit as it gets called for every button press on the TP but that should not be an issue...

    Fred
  • DHawthorneDHawthorne Posts: 4,584
    I've never used the 0 shortcut; it seems to me too easy to get a situation where you have channels firing an unintended event. Subsequently, I forgot it even existed :).
Sign In or Register to comment.