Home AMX User Forum NetLinx Studio

Get_Last in a hold event

I was trying to do this and of course it doesn't work if another touchpanel triggers the event, since a hold isn't a real event, but a virtual event. So the result of get_last will change in the middle of the hold event which breaks things.

An appropriate workaround would seem to be:

1) Use device.input.number rather than an index to the TP array. This should always work anywhere inside a button event.

2) Store what get_last returns in the push section into a global and then use that in the hold event. This should always work but requires more global variables.

3) Write my own get_last that is called from a button_event with channel 0. Since this button event will process every button event it could be used to make sure that each TP has its own variable to access as it needs to. I hate having to do this but AMX gives us no choice.

Anyone have an opinion on what works the best? I searched on this topic and there is much discussion but I didn't get a clear picture as to what people think. I have a large job with multizone panels so it needs to work reliably regardless of who is doing what when.
I also use get_last in some modules outside of button_events and so far they work but I am wondering if there could be problems if the right sequence of events happens.

As far as I'm concerned there really is no valid reason why get_last doesn't work inside a hold. Considering its a controller used for systems with multiple touchpanels and holding a button is a valid action, its seems an oversight to have get_last be so unsophisticated and only return a naive result.
Thanks,
Paul

Comments

  • Hold
    a_riot42 wrote:
    I was trying to do this and of course it doesn't work if another touchpanel triggers the event, since a hold isn't a real event, but a virtual event. So the result of get_last will change in the middle of the hold event which breaks things.

    An appropriate workaround would seem to be:

    2) Store what get_last returns in the push section into a global and then use that in the hold event. This should always work but requires more global variables.

    Anyone have an opinion on what works the best? Paul

    In my opinion number 2 is the most reliable solution to use. In its simplest form think of a Hold like you would a single length Timeline_Event. The Push in the Button_Event starts the timeline and the Release kills the timeline. Manage your programming logic with this in mind.
  • a_riot42a_riot42 Posts: 1,624
    That was my thinking as well. The docs are unclear about this, but can one button_event start before another button_event has finished or does the first one have to complete before the second has started. So if my event looks like this:
    button_event[dvTPs, iChanArray]
    {
      push:
      {
        send_string 0, "'Calling big long function'"
        functionThatTakesALongTimeToComplete()
      }
    }
    
    

    If this button event is triggered twice in a row quickly, is it possible to see the send_string print the second time before the functionThatTakesALongTimeToComplete() returns or does it block until the function returns and the button_event is over? I would try this but I haven't got a controller here to try it.
    Many thanks,
    Paul
  • a_riot42 wrote:
    That was my thinking as well. The docs are unclear about this, but can one button_event start before another button_event has finished or does the first one have to complete before the second has started. So if my event looks like this:
    button_event[dvTPs, iChanArray]
    {
      push:
      {
        send_string 0, "'Calling big long function'"
        functionThatTakesALongTimeToComplete()
      }
    }
    
    

    If this button event is triggered twice in a row quickly, is it possible to see the send_string print the second time before the functionThatTakesALongTimeToComplete() returns or does it block until the function returns and the button_event is over? I would try this but I haven't got a controller here to try it.
    Many thanks,
    Paul

    The only way the function would not complete before the next button event occurs is if there is one or more waits within the function.
  • a_riot42a_riot42 Posts: 1,624
    Cool...I'll take that as truth from an ACE!
  • viningvining Posts: 4,368
    You could also just use a blocking variable to prevent any push events of the same device from a different panel while another panel is performing a hold. It would be a rare occurrence in most installations but possible. Otherwise store the get_last value in a local or global var but that could change also by the current push if a global is used so a local in the hold handler would be the deal.
    BUTTON_EVENT [dvTP_Arry,nAP_BtnArry] 
    
         {
         PUSH:
    	  {
    	  STACK_VAR INTEGER nBTN
    	  STACK_VAR CHAR cDevice[11] ;
    	  LOCAL_VAR INTEGER nLastInPut ;
      	  
    	  nBTN = GET_LAST(nAP_BtnArry)
    	  cDevice = fnDEV_TO_STRING(BUTTON.INPUT.DEVICE) ;
    	  dvCurPushTP = BUTTON.INPUT.DEVICE ;
    	  
    	  fnDebug("'Device:',cDevice,'-CHANNEL ',itoa(nAP_BtnArry[nBTN]),' Line-<',ITOA(__LINE__),'>'") ;
    	  if(nHold_In_Progress)
    	       {
    	       fnDoMSGDisplay(dvCurPushTP,'Please Wait ** System Busy',MSG_TYPE_WARNING,AP_UNIT_0) ;
    	       nHold_MSG_Sent = 1 ;
    	       }
    	  else
    	       {	  
    	       SELECT
    		    {
    		    ACTIVE (nBTN == BTN_TAKE)://3, manual take	       
    			 {
    			 nAutoSwitch = 0 ; //force auto off if on
    			 fnDoSwitch(nInput_Selected,TRUE,FALSE,FALSE) ;//source/manual switch/do all/do single
    			 }
    		    ACTIVE (nBTN == BTN_AUTO_SWITCH)://4, AutoSwitch	       
    			 {
    			 if(nAutoSwitch < 3)
    			      {
    			      nAutoSwitch ++ ; //increment Auto switch
    			      }
    			 else
    			      {
    			      nAutoSwitch = 0 ;
    			      }
    			 nLastInPut = 0 ; //used for inputs but if output pushed reset this flag.
    			 }
    
    
    HOLD[2,REPEAT]:
    	  {
    	  STACK_VAR INTEGER nBTN ;
    	  
    	  nHold_In_Progress = 1 ;
    	  devCurHoldingTP = BUTTON.INPUT.DEVICE ;
    	  nBTN = GET_LAST(nAP_BtnArry)
    	  SELECT
    	       {
    	       ACTIVE (nBTN >= BTN_VOL_UP && nBTN <= BTN_VOL_RMP_DWN)://11-14, output volume adj. steps & ramp	       
    		    {
    		    SWITCH(nBTN)
    			 {
    			 CASE BTN_VOL_UP:
    
    RELEASE:
    	  {
    	  STACK_VAR INTEGER nBTN ;
    	  
    	  devCurReleaseTP = BUTTON.INPUT.DEVICE ;
    	  nBTN = GET_LAST(nAP_BtnArry) ;
    	  if(nHold_In_Progress)
    	       {
    	       nHold_In_Progress = 0 ;
    	       if(nHold_MSG_Sent)
    		    {
    		    fnDoMSGDisplay(dvCurPushTP,'System now ready',MSG_TYPE_WARNING,AP_UNIT_0) ;
    		    nHold_MSG_Sent = 0 ;
    		    }
    	       }
    	  }
    
  • a_riot42a_riot42 Posts: 1,624
    Interesting viewpoint. I actually like the fact that get_last behavior is such that if one person is holding a button, that someone else's button press interrupts it if its the same device. I don't want two people controlling the same DVR and one holding channel up and the other holding channel down and using get_last will prevent that.

    I don't like it though if its a different device. Two touch panels controlling two different DVRs should be able to hold buttons without intereference from the other. Since I have only one channel up button event for 3 DVRs, I want three touch panels using the three DVRs to be able to hold and not interfere with each other. If two touch panels are controlling the same DVR, then I like that get_last usurps control to the last button press.

    What I will need to do is keep an external variable to determine the UI returned from get_last in the push and reference it in the hold. I will have to write a special case if the device is the same which I don't like (special cases scare me).

    I see something in your code that I unconditionally hate: "Please wait..." I have sworn to myself that I will never tell the user to "Please wait..." when they really dont't have any choice :)
    Paul
  • viningvining Posts: 4,368
    If one DVR is controlled by only one TP just make an instance of the module for each device for each TP then there won't be any issues.

    As far as the "Please wait " goes I feel it's better to keep the user informed then to have him push a button w/o anything happening. Then they just think it doesn't work properly.

    If you use the Get_Last w/o storing the value in a local or global var under the hold then some one can change the value from a different TP during that hold. If that happens the TP that is still in hold will start to execute a hold/repeat on a value that it shouldn't and may not be desirable.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote:
    If one DVR is controlled by only one TP just make an instance of the module for each device for each TP then there won't be any issues.

    That's the problem, all TPs share all DVRs so there are issues that can crop up.
    vining wrote:
    As far as the "Please wait " goes I feel it's better to keep the user informed then to have him push a button w/o anything happening. Then they just think it doesn't work properly.

    I understand that and I think most users these days understand that when they turn the TV on, it takes a second or two to warm up. It has been this way since the invention of TVs so I prefer not to insult my users intelligence and tell them to Please Wait when it is obvious what is going on. I have seen the "Please wait..." popup in many systems, and the worst ones actaully use a modal dialog so the user now can't adjust lights, HVAC or any other subsystem until the TP reliquishes control. What if they hit that button accidentally and want to immediately turn it off rather than waiting?

    What I generally do is make sure to turn the audio on first before the display so that the user gets an indication that something has happened. If that isn't possible I think that after the first few times of hitting a button and something happening they will trust that it will continue to do so without the Please Wait screen.

    I have seen users hit buttons and then repeatedly hit them over and over again because they don't see anything immediately happening. These are the same people that bang on the keyboard when they get an hourglass in Windows, or hit the already lit elevator button thinking it will make it come faster.

    Most of them quickly realize this does no good, but actually enjoy doing it anyway even after being told it can actually slow things down. What I do for those people is give them really nice sounding click sounds for the press and release and they enjoy hearing the sound as they bang on the button and it somehow soothes them and makes them feel they are doing something even though all those button presses are being ignored. Even I get some odd satisfaction from it as I am guilty of hitting the lit elevator button when I am in a hurry. Its a psychological effect to be sure, but as long as the TP repsonds with a sound they feel the system is responding to them and that is comforting to them. Usually there is a page flip after a source selection button press so the changing screen tips them off that their command was recognized.

    If the button highlights after they touch it, that is enough confirmation that something is happening and I don't feel the need to popup a warning dialog. If there is a problem one day and the system doesn't start for some reason, then the popup is telling the user erroneous information indicating that something is happening when it is not so its really a no win situation.

    No offense Vining, this is strictly my opinion and I don't expect any one else to do things this way. "Please Wait..." is just a personal pet peeve of mine :)
    Paul
  • yuriyuri Posts: 861
    nice ideas Paul.
    At the moment i'm working on a system and i was thinking about using some sort of "Please wait while audio server is updating" popup, but your 'rant' made me think twice :)
  • a_riot42a_riot42 Posts: 1,624
    yuri wrote:
    nice ideas Paul.
    At the moment i'm working on a system and i was thinking about using some sort of "Please wait while audio server is updating" popup, but your 'rant' made me think twice :)

    Well don't go by what I say because I am in the distinct minority I'm sure. There are people who like "Please wait..." so don't go by me. As well, there are times when I will use a modal popup to prevent the user from activating things. This is usually when a macro is triggered that will take some time to finish and hitting other buttons will interfere with the macro so a popup appears letting the user know that something is going on and I include a progress bar that gets updated as the macro completes so they can gauge how long it will take. But I will still not use the phrase "Please wait..." as the user has no choice in the matter since I have locked them out of control. So what I do is use a popup that says something like "Configuring your request..." and give them a progress bar. It is up to the user whether they want to "wait" or not, and I don't like telling the user what to do because in my mind it should always be the human telling the system what to do not the other way around. But that's just me :)
    Paul
  • yuriyuri Posts: 861
    a_riot42 wrote:
    Well don't go by what I say because I am in the distinct minority I'm sure. There are people who like "Please wait..." so don't go by me. As well, there are times when I will use a modal popup to prevent the user from activating things. This is usually when a macro is triggered that will take some time to finish and hitting other buttons will interfere with the macro so a popup appears letting the user know that something is going on and I include a progress bar that gets updated as the macro completes so they can gauge how long it will take. But I will still not use the phrase "Please wait..." as the user has no choice in the matter since I have locked them out of control. So what I do is use a popup that says something like "Configuring your request..." and give them a progress bar. It is up to the user whether they want to "wait" or not, and I don't like telling the user what to do because in my mind it should always be the human telling the system what to do not the other way around. But that's just me :)
    Paul

    it's not like i go by what you say. What you said made me think twice.
    Recently i've been reading up on GUI design and came across a website about Lotus Notes (and how much the GUI would suck) on this website http://lotusnotessucks.4t.com/

    Most of the things covered on the website are pretty standard, but with the possibilities given with the current G4 touchpanels, people (me) tend to get a little too excited in creating our (my) designs

    If the frame can handle information in the background, why bother your client with useless information? (Please wait while...)
    On the other hand, when a projector cools down or warms up, we use slider bars to indicate the amount of time left (usefull information)
  • mpullinmpullin Posts: 949
    yuri wrote:
    it's not like i go by what you say. What you said made me think twice.
    Recently i've been reading up on GUI design and came across a website about Lotus Notes (and how much the GUI would suck) on this website http://lotusnotessucks.4t.com/
    That website is hilarious!
  • viningvining Posts: 4,368
    Paul, I agree with most of what you say but in the context of the code example I posted I am blocking further button pushes while a hold is in progress from any other TPs for the same device so in this instance button feedback or a button clicks make no sense unless I do a boink sound, maybe. Now in all likely hood the scenario of some one holding a button for a device that will trigger the hold event on one TP while some one else pushes a button for that same device on another TP at the same time while the hold is in progress isn't all that likely but in the rare chance that it does the pop up informs them that their button push had no action and to try again when it's no longer being blocked and in use by another user.

    Now whether blocking further button pushes for the same device on other TP during a hold makes sense or not is another question. My feeling is that it will probably never happen but if it should I prefer to let the first user finish their task before allowing another user to barge in and screw things up.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote:
    Now in all likely hood the scenario of some one holding a button for a device that will trigger the hold event on one TP while some one else pushes a button for that same device on another TP at the same time while the hold is in progress isn't all that likely but in the rare chance that it does the pop up informs them that their button push had no action and to try again when it's no longer being blocked and in use by another user.

    Not as rare now that R4s are in use. I have many clients that like to have a modero 8400 and a R4 in the same room. His and hers as it were. When two people can control the same device at the same time all sorts of odd situations present themselves. Do you do page tracking for this case? I do not, but then others think you shouldn't because you should present a UI to the user that won't work. I guess its a judgement call.
    Paul
  • yuriyuri Posts: 861
    vining wrote:
    Paul, I agree with most of what you say but in the context of the code example I posted I am blocking further button pushes while a hold is in progress from any other TPs for the same device so in this instance button feedback or a button clicks make no sense unless I do a boink sound, maybe. Now in all likely hood the scenario of some one holding a button for a device that will trigger the hold event on one TP while some one else pushes a button for that same device on another TP at the same time while the hold is in progress isn't all that likely but in the rare chance that it does the pop up informs them that their button push had no action and to try again when it's no longer being blocked and in use by another user.

    Now whether blocking further button pushes for the same device on other TP during a hold makes sense or not is another question. My feeling is that it will probably never happen but if it should I prefer to let the first user finish their task before allowing another user to barge in and screw things up.


    the "your button push didn't have any action, please try again later" if offcourse a little silly...
    You present the user with a message that something didn't work out, and he has to press again, but instead, you could automagically "repush" the button when the action can be triggered.
    That's what i was trying to tell, don't 'bug' your client with "useless" information, OR, present the information, and retrigger the action...
  • viningvining Posts: 4,368
    Yuri wrote:
    you could automagically "repush" the button when the action can be triggered.
    I thought of that but a delayed action IMHO isn't all that desirable either because the user expects thing that normally occur instantly to occur instantly and when they don't they assume something didn't work regardless of button feedback and their first response is to push again. Even with multple TPs/R4 for the same device, whether they're in the same room or not this isn't going happen that frequently if at all at least for most devices since a hold is typically for ramping volume and typically a system is turned on to a preset level or the last level that is what the user normally prefers. Yes they do occasionally change the volume level and yes it is possible at that exact time some one else may decide to change channels let say and while a volume ramping hold usually only lasts a couple of seconds at best so a delayed auto repush would probably go unnoticed and with out a significant delay.

    Yuri wrote:
    the "your button push didn't have any action, please try again later" if offcourse a little silly...
    If that's what I wrote then it would be silly! The text I sent was 'Please Wait ** System Busy' and on the hold relese it would then display 'System now ready'. Which should occur in a matter of seconds unless some one falls asleep during the hold.

    Any way I agree to many informational pop ups are annoying but the infrequent pop ups they are pertinent and infromative are kinda what seprates us the other systems.
Sign In or Register to comment.