SetValue() firing Notify() on init and state restore?

User avatar
Waverley Instruments
Posts: 129
Joined: Thu May 05, 2022 2:10 pm

SetValue() firing Notify() on init and state restore?

Post by Waverley Instruments »

Howdy,

Just wondering if anyone else has done a bit of tracing around SetValue() and Notify() - thoughts / comments much appreciated!

Say your UI has a button. I'm seeing two calls to Notify(Button_Changed) at startup before any UI events have occurred. I think the first is some kind of initialization, and the second on state restore. It all happens in the same AppKit thread so I can't be sure.

If these observations are correct, I guess this is by design. However...

Things start to get a little fiddly if you have logic across numerous controls where the value of one control determines the value of another and you only want to apply that logic for legitimate UI events. I don't think SetValueNoNotification() is really helpful here - it's more like I want to know where that Notify() is coming from and ignore those two pesky startup calls...

I've been messing around with a couple of hacky options using the timer (after the first tick... :roll:) to basically set a flag when the init / restore calls have probably been made (yuk...) or moving the UI specific logic into the Object_LeftButtonUp notification instead - also feels a bit hacky, but less so...

So, yeah - any thoughts or suggestions, much appreciated!

Thanks, -Rob
ColinP
Posts: 935
Joined: Mon Aug 03, 2020 7:46 pm

Re: SetValue() firing Notify() on init and state restore?

Post by ColinP »

Hi Rob,

You are not alone!

I've had all manner of problems with Notify(). It's fine for simple applications but with more complex event handling I've had to invent several hacks that I'm not really comfortable with.

One of the benefits of open source is that one can go look but as VM is opaque there's a hell of a lot of guess work involved. Like you I've done a fair amount of tracing but there's a limit to what one can uncover. Multiple threads call Notify() and when you start doing complicated stuff I think you end up with recursive calls weaving in to what's happening and who knows exactly what's going on. I've no idea what (if any) thread safety mechanisms are at play inside CA's code for instance.

The most recent problem I had a couple of days ago was wanting to open a menu (under certain circumstances) when a toggle button was pressed but on exit from the menu the toggle button's graphic was left hanging in the pressed state. I tried all kinds of things to refresh the button state but the only thing that brought it back was moving the mouse cursor over it.

The problem doesn't occur when a push button is used instead but the toggle button works as a latched radio button most of the time. So I ended up hacking it with a toggle button and a push button sharing the same space and using Z-order and SetVisible() to show and hide the push button. Very inelegant stuff.
User avatar
Aarnville
Posts: 43
Joined: Sat Jun 18, 2022 5:14 pm

Re: SetValue() firing Notify() on init and state restore?

Post by Aarnville »

Rob, I think you are correct but it depends whether the module is "new" or not.

Example:
Start with a blank project and place a knob on it.
Compile and run. The first time you do this in the debugger shell there is one notify message for that knob, setting the default value.
Second and subsequent runs will give you two notify messages. The first sets the default value and the second restores whatever value the knob held when you quit - the save state. If you clear the "Test/Debug" settings in the build menu the next time you run it you will just get the one notify again. I guess in the real VM software the Notify behaviour will be the same. A new module being added to the rack will give you a single message, subsequent loading/recalling of that rack will give you two.

So in normal use on start-up you will get two notify messages per control, with the first of the messages probably containing a "wrong" value (the default). What I don't know is how the timing of those events relates to the main ProcessSample thread starting and the first GUI update.

I think if you have a Notify message for one control that calls SetValue() on a different control you need to take great care that you don't end up with a chain reaction of controls constantly firing Notify messages at each other. I managed to do this by accident when I wanted a pair of knobs where adjusting one would adjust the other. Fortunately that was so instantly and spectacularly bad that I sussed it out quite quickly. :lol:

And the potential problem with any "hacky" solution is that it might come back to bite you on a future release of VM software. You just can't guarantee that the internal start-up stuff will stay the same. It most probably will but....
UrbanCyborg
Posts: 585
Joined: Mon Nov 15, 2021 9:23 pm

Re: SetValue() firing Notify() on init and state restore?

Post by UrbanCyborg »

I hit the same problem with controls chaining on the first module I wrote. My fix was to set a "triggered" flag for the affected control under Knob_Changed, then reset to the correct value and unset the flag under Object_LeftButtonUp.

Reid
Cyberwerks Heavy Industries -- viewforum.php?f=76
User avatar
Waverley Instruments
Posts: 129
Joined: Thu May 05, 2022 2:10 pm

Re: SetValue() firing Notify() on init and state restore?

Post by Waverley Instruments »

Thanks so much for the replies guys - nice to know I'm not the only one that's been down this road!

Good observation on the "new module" scenario - makes it all the more dangerous to base any workaround on the number of times something gets fired, etc., not that I would do such a thing :D

For now, I think I'm OK with hanging my UI-centric logic off the mouse up event instead of value changed. It sort of makes more sense, and seems to be the safest / least brittle. I hope...

Quite often with these event type architectures you might get an optional argument of "sender" - I guess that may have been handy in this context, but it really depends on the specifics of how it all works under the hood... :?

Just for a point of interest, my issue surfaced off the back of a module appearing to not restore its state properly. This was because mutex type logic was being applied during the default (first) initialization Notify() call and at the time I was assuming Notify() was "just a UI thing" :roll:

-Rob
ColinP
Posts: 935
Joined: Mon Aug 03, 2020 7:46 pm

Re: SetValue() firing Notify() on init and state restore?

Post by ColinP »

The problem with triggering things by mouse up events is that it makes a GUI appear very sluggish. It's OK as a last resort but tends to make software feel a little amateurish.

Polling user input using a timer thread has the same effect.

Also sometimes you need to handle a drag so there's no alternative but to deal with the mouse down.
User avatar
Aarnville
Posts: 43
Joined: Sat Jun 18, 2022 5:14 pm

Re: SetValue() firing Notify() on init and state restore?

Post by Aarnville »

ColinP wrote: Sun Jul 03, 2022 2:08 pm The problem with triggering things by mouse up events is that it makes a GUI appear very sluggish.
I was just about to say exactly that. People get it into their heads that the mouse response is sluggish and then guess what they do. Yep. they hold the button down for longer to give it chance to "work". They probably also tut and think rude words.
User avatar
Waverley Instruments
Posts: 129
Joined: Thu May 05, 2022 2:10 pm

Re: SetValue() firing Notify() on init and state restore?

Post by Waverley Instruments »

ColinP wrote: Sun Jul 03, 2022 2:08 pm The problem with triggering things by mouse up events is that it makes a GUI appear very sluggish.
Yep, totally get that Colin, classic example being a tap tempo button - you really want to be doing the timing calculations based on mouse down!

In my specific case though, this was relating to VM toggle buttons which (I'm pretty sure) don't get the value changed notification until mouse up anyway, then I'm also pretty sure you get the mouse up notification straight afterwards.
User avatar
Aarnville
Posts: 43
Joined: Sat Jun 18, 2022 5:14 pm

Re: SetValue() firing Notify() on init and state restore?

Post by Aarnville »

Waverley Instruments wrote: Sun Jul 03, 2022 4:13 pm classic example being a tap tempo button - you really want to be doing the timing calculations based on mouse down!
Unless you are doing reggae.... um, sorry. I'll get me coat. :oops:
ColinP
Posts: 935
Joined: Mon Aug 03, 2020 7:46 pm

Re: SetValue() firing Notify() on init and state restore?

Post by ColinP »

Waverley Instruments wrote: Sun Jul 03, 2022 4:13 pm In my specific case though, this was relating to VM toggle buttons which (I'm pretty sure) don't get the value changed notification until mouse up anyway, then I'm also pretty sure you get the mouse up notification straight afterwards.
Interesting. It looks like toggle button change events are delivered on mouse down when the button is part of a radio group but on mouse up when not.

I'll investigate further tomorrow.
Post Reply

Return to “Module Designer”