How to NOT use a script for a currently scripted behavior?

I develop a custom plugin that requires two GPScript functions to work properly in GP. I’m trying to think if there’s any way to make the plugin’s GP widgets behave correctly WITHOUT these scripts.

It’s a looper, and has an internal state machine that not only takes input from the buttons, but changes its buttons’ states automatically in a few cases. The plugin’s UI works perfectly since I can control all its internal workings, but I’m not sure the best way to get GP widgets to mirror that behavior.

The Boomerang plugin UI

The Boomerang GP panel

The looper does a lot with only six buttons. These are two scenarios that illustrate the issue: in each, only the GP widgets are pressed, not the plugin UI.

Case 1: REC → PLAY → STOP

One button controls the state of another.

They’re not directly linked per se; the state machine updates the states based on its transitions.

From an IDLE state of ALL LEDS OFF:

  1. Press RECORD to start a recording → REC LED ON
  2. Press RECORD again to stop recording and start playback immediately → REC OFF, PLAY ON
  3. Press RECORD again to stop playback and start a new recording → REC ON, PLAY OFF
  4. Press PLAY/STOP → RECORD STOP
  5. IDLE

Case 2: PLAY → ONCE

The ONCE button makes the device STOP PLAYBACK when the loop currently being played ends.

If the ONCE button is pressed before playback ends, the loop restarts at the beginning and continues playing. This can create a “stutter” effect when pressed repeatedly.

From an IDLE state:

  1. Press RECORD to start a recording → REC LED ON
  2. Press RECORD again to stop recording and start playback immediately → REC OFF, PLAY ON
  3. Press ONCE → ONCE ON (PLAY remains ON)
  4. At end of loop, automatically STOP PLAYBACK → PLAY OFF, ONCE OFF
  5. IDLE

I haven’t written it out this way before, I don’t think. The OEM instructions are accurate but a bit wordy. I think this is clearer.

Before getting into the GPScript below, I should add that the plugin currently has an output MIDI message: ONCE_STATE, which represents whether the device is in ONCE mode.

BOOM_PLAY and BOOM_ONCE are the widgets directly linked to the PLAY/STOP and ONCE buttons, respectively.

Edit mode
Note the Hidden ONCE_STATE (the big square one) and PLAY_STOP widgets.

Anyway, I’ve scripted it like this:

// Sync the PLAY LED, which is updated by the plugin's internal state changes, with the widget
// Turns it ON automatically when RECORD pressed the second time (ending a recording and automatically starting playback)
On WidgetValueChanged(newValue : double) from BOOM_PLAY_OUT
    //Print("The new value is " + newValue)
    SetWidgetValue(BOOM_PLAY, newValue )
End

// Sync ONCE with the plugin's internal state
// Which is really just turning it OFF automatically
On WidgetValueChanged(newValue : double) from BOOM_ONCE_STATE
    SetWidgetValue(BOOM_ONCE, newValue)
End

I believe I went this route because I found it not possible to link a widget to more than one plugin parameter. If I’m thinking about this right, the ability to map a widget to more than one parameter might make external-state-based plugins, like loopers, easier to map to GP.

To put it in different words: I am looking for a way to control a GP widget’s state with the plugin’s internal state, represented by two outgoing parameters, mapped to the PLAY and ONCE states being true. Those two parameters are mapped to widgets that are not the actual button widgets; they are hidden on the panel. The GP script creates the relationship between each button pair.

At last, here’s the question: Is there a better way to do this?

Am I missing an obvious (or not so obvious) feature that would make the scripts obsolete? There is clearly two-way communication between plugins and widgets, since one always updates the other, so why is it so hard to create a similiar behavior to buttons/LEDs that change their state without being pressed?

I did think about stacking the buttons and an approach of hiding/unhiding them based on state, but that felt more complicated, and if I did ever try it, I didn’t get very far. And started thinking about this write-up.

If there truly is no better way, but one-to-many mapping of plugins to widgets would make this more straightforward, then perhaps it is a new feature request? What do I not know that would clarify things?

Thanks!!
Max

I’m sorry I haven’t tried your plugin yet. I’m also struggling a bit to follow the outcome you’re seeking.

The only thing I wanted to ask was whether you could have additional parameters in your plugin (that weren’t part of the UI) that you could use to help? Particularly when I saw the script was just updating the value of one widget based on another.

Yeah, I have those two output parameters already, and they work. What I’m looking for is if there’s a way to do this without the scripts. Is there an option or trick I’m not thinking of that would do this? I think the limitation is the 1:1 mapping of widget to plugin parameter. If that could be made 1-to-many, I think that would simplify a lot of this.

You can use multiple widgets and map each of them to different plugin parameters
and then use them same widget link for this widgets.
And you can hide widgets you do not want to be visible,

Ah yes! I have the auxiliary widget hidden, but for some reason hadn’t thought of widget linking, I use it all over the place elsewhere! That might be it! Let me try it!

I got it; ultimately a simpler, all-plugin solution. No scripts needed! Stay tuned!

The solution was to use the outputs for PLAY_STATE and ONCE_STATE more effectively, and to change the button mechanics in the plugin to expect a momentary-type signal, instead of a toggle.

I created shape widgets and shaped them to sit right over the LED component of the LED Button-style widget used for the main panel interface buttons. These shape widgets and the *_STATE outputs are mapped to each other.

TL, DR: In GP, set the PLAY/STOP and ONCE buttons to Momentary mode. Add two new LED widgets, one linked to PLAY_STATE (new in v2.1.0-beta.1), the other linked to ONCE_STATE. Lock those widgets - they are purely reactive to internal state. You can then design the panel as you wish. I’ve tried to make mine look kinda like the original with the design options in GP, but I also have ideas for cool creative panels that are totally removed from the original design.


I tried to get the color and shape to match well with the button’s LED graphic; I’m not happy with it yet but it serves the purpose and can be refined in the future. This part of the experience opens the door to revisiting the existing feature request (not mine, but I support it) for more control/options in the widget department. In this instance specifically, it’d be amazing to be able to set an LED Button and its LED as two separate widgets. Pretty obscure request, I suppose, but there it is.

Another option is to let go of the idea of the button and LED being so tightly coupled. I finally cracked this when I realized that the original device’s buttons don’t have LEDS. The Buttons trigger transitions, and the LEDs represent the state. So using a normal LED Widget for the state, visible on the panel, is a lower-effort way forward, too. I plan on creating panels with these various approaches.