Add one more Feature to the \setlist\GO OSC

In addition to the current OSC \setlist\GO features, I would like to see one more LOOP functionality. Currently….

    • When playing in a loop, hitting \setlist\GO escapes the loop

Essentially, it does a \loop\escape OSC command.

But I would rather like to see it perform a \loop\toggle OSC command.

In other words, while in a section that is LOOPING, and upon hitting \setlist\GO to escape the loop, I would like to, change my mind, and again hit the \setlist\GO OSC command, and STAY in the loop. In other words, the GO OSC would never do \loop\escape, rather the GO OSC would always do \loop\toggle

One conflict I see (and I have a proposed solution) is that, currently the \setlist\GO OSC has 2 behaviors while “playing”. The first is \loop\escape, and the 2nd is…

  • When playing while a song or section is queued, instantly jumps to it

But while in a loop, is use (as an example) a “/setlist/jumpToSection J4 true” OSC , and (I seem to remember, I hope) that if the song is currently looping, at the end of the current loop, if I already sent this \setlist\jumpTO OSC, AS goes to that section without requiring me to ever send a \loop\escape OSC command.

Thus, I am thinking maybe I don’t know the whole picture here, or, perhaps there is not a need for the 2nd \setlist\go “playing” behavior.

My point: Can this 2nd behavior go away, and be replaced instead with \loop\toggle ??

As always, thanks for considering this!

Hey @nevillewhitemusic,

You can achieve what you described by using a MIDI Mapping → Custom Script instead of mapping directly to /setlist/go.

This script would make the GO button behave like this:

  1. If currently looping → toggle the loop OFF and arm a short “return” window
  2. If you press GO again within that window → toggle the loop back ON
  3. Otherwise → behave like normal /setlist/go

Paste this into a MIDI Mapping set to Custom Script:

const RETURN_WINDOW_MS = 2500;

const now = Date.now();
const armed = local("go_loop_return_armed", false);
const armedAt = local("go_loop_return_armed_at", 0);

const isLooping = !!osc("/setlist/loopEnabled");

if (isLooping) {
  sendOsc("/loop/toggle"); // leave loop by toggling (not escape)
  setLocal("go_loop_return_armed", true);
  setLocal("go_loop_return_armed_at", now);
  return;
}

if (armed && (now - armedAt) < RETURN_WINDOW_MS) {
  sendOsc("/loop/toggle"); // return to loop
  setLocal("go_loop_return_armed", false);
  setLocal("go_loop_return_armed_at", 0);
  return;
}

// default GO behavior
sendOsc("/setlist/go");

You can adjust RETURN_WINDOW_MS if you want a longer or shorter “change your mind” time :sweat_smile:

Would that work for your use case?
I’m looking forward to your reply!

BOOM! Amazing. Terrific QUICK reply. thanks.

1 Like