Function to re-sync widgets?

Is there a command in GPScript to re-sync all of the external MIDI controller parameters to their widgets?

Let’s say I have a GPScript that I want to look for an incoming CC96 message, and when it sees that I want it to send out the the positions of all the widgets that are sync’d via MIDI.

When I switch between variations this happens, so that an external control surface will immediately pick up the changing positions of different widgets when changing variations. I want that same sync to happen through a script when I send the CC96 message. The CC96 detection part is easy enough. It’s sending out all the widget values I’m not sure about.

My real world application is using a BCF2000 controller. I have the faders and buttons set up such that 3 of the presets on the BCF2000 operate on 3 different MIDI channels, so I can basically use them as three different “pages” of controls. On Blue 3 I have preset 2 controlling the upper register drawbars, for example, and preset 3 controlling the lower register. On preset 1 the faders control volumes for different VSTs.

Individually these all work fine. The problem is only one preset (what I’m using as a "page) of the BCF will stay in sync. e.g., if I’m on preset 1 on the BCF and I change variations in GP, the faders and knobs will all snap to the right place. If I then switch to preset 2, the faders and knobs on the BCF will reflect whatever they were at last time I was on that preset. They don’t “hear” the updates GP sent when it changed variations, other than the updates for the preset I was on.

I’m not sure how clear that explanation is. The basic gist is I’m just wondering if there’s a way to get GP to re-send the positions of all the MIDI sync’d widgets through a script.

Try to get the actual value of the widget and set the widget value.
This could be the trick or
Try to use SetVariation to the actual variation.
The idea is that when you set a widget value it should be synced to your midi controller.
The same should happen when you set a variation via gpscript

Currently, there’s no GPScript function to do that, you’d have to get the physical position of the widget, scale it to a midi value and send a midi event out to the appropriate midi device through a midi out block.

I’ll take a look at that code and see how hard (or easy) it would be to add something like ResyncWidget that would do this

Thanks for the thoughts.

I tried the SetVariation(GetVariation()) approach, but it resets everything every time I switch pages on the controller. So let’s suppose I used the faders on page 1 (channel 1) to adjust volumes, then switch over to channel 2 so I can move upper register drawbars the SetVariation(GetVariation()) would move the faders appropriately for the drawbar positions but reset the volumes I had just adjusted.

I guess my other option is to name all my widgets for GPScripts and do a
SetWidgetValue(widget,GetWidgetValue(widget))
for every widget.

For now that would work. You should be able to create an array to hold your widgets so you can just use a FOR loop to iterate through them.

Works, but with a small hitch.

Apparently GP knows when I’ve just set the widget to the same value it already has, so it doesn’t re-sync it to the controller. I have to change the value to make it sync.

I figured I’d just add 0.00001, which works with the notable problem that 1) values obviously creep the more I do this, and 2) if the widget is already at its end I can’t increment it any further so it doesn’t update.

The easy workaround is to increment it, then decrement it. This has the downside of sending everything to the control surface twice, but it doesn’t seem to mind.

Here’s my script:

var
Fd1, Fd2, Fd3, Fd4, Fd5, Fd6, Fd7, Fd8, Fd9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20 : widget
FArray : widget array
BCF2000 : MidiInBlock

Initialization
FArray = [Fd1, Fd2, Fd3, Fd4, Fd5, Fd6, Fd7, Fd8, Fd9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20]
End

On ControlChangeEvent(m : ControlChangeMessage) matching [96…96] from BCF2000
var x : integer

Notify("Update")

For x=0 ; x<20 ; x=x+1 Do 
   SetWidgetValue(FArray[x], GetWidgetValue(FArray[x])+0.000001 )
   SetWidgetValue(FArray[x], GetWidgetValue(FArray[x])-0.000001 )
End

End

Yeah, sorry, we do try to optimize things (such as recognizing that the value of a widget hasn’t changed to avoid unnecessary work.

Glad you have found a workaround though. One suggestion. Rather than that hard coded comparison with 20 in he FOR loop, you can use Size to refer to the size of the array, making the code safer if you ever change the number of widgets in the array

It is clear that if you don’t want the MIDI sync to loop, you have to check if the value really changed or not, which is not the current behavior if the « On WidgetValueChanged » callback function.
I really would like to rename it as « On WidgetValueTouched », and add a real « On WidgetValueChanged » which is only called when the value really changed.

OK, it is not exactly the topic discussed here, but it is closely related.

Great tip, thanks.

Along those lines, is there some way to make that widget array auto-populate? I’m guessing not, but thought I’d ask. e.g., let’s say I add another widget and name it Knob1 for GPScripting. Is there a clever way to get that into my widget array without adding it by name to the Var and Initialization sections of the script?

Because this must be known at compile time, I think this is not possible.

Yes, declarations are required (it’s for your own good, trust me😇) However, I have been working on simplifying declarations a bit for a future version of GP and it will be possible to combine declaration and initialization like this

Var
foo1, foo2, foo3 : widget
MyWidgets : widget array = [foo1, foo2,foo3]

So no need for an initialization block for such things.

1 Like