Midi trigg Javascript specific song order

Hi everyone,

I’m trying to use the Project Script to send a MIDI note conditionally based on the next song in the setlist. Specifically, I want to trigger a MIDI note on an external device only when the transition is SONG A → SONG B, and not for any other transition.

Here’s the script I’m using:

(async () => {
  let previous = osc("/setlist/activeSongName");
  log("Script started, current song:", previous);

  while (true) {
    await waitForOscChange("/setlist/activeSongName");
    
    const current = osc("/setlist/activeSongName");
    log("Change detected:", previous, "->", current);

    if (previous === "SONG A" && current === "SONG B") {
      log("Condition met, sending MIDI...");
      sendMidiNote("my midi port", 1, 26, 127, 500);
    }

    previous = current;
  }
})();

The problem: looking at the debug logs, the script starts correctly (I can see the first log() output), but then the VM is immediately cleaned up before the while loop can run:

[scripting] Running project script
[scripting] Script log → "Script started, current song: SONG B"
[script-runner] Cleaning up VM

It seems like the async infinite loop is not supported in the Project Script context, or the VM lifetime is too short.

Two questions:

  1. Is waitForOscChange inside a while (true) loop supported in the Project Script?
  2. Is there a recommended way to react to song changes and send MIDI conditionally based on both the current and next song name?

Thanks!

Hey @Mousse09,

since you’re calling the anonymous async function without awaiting it, AbleSet doesn’t keep the script running. The easiest way to solve this is removing the first and last lines:

let previous = osc("/setlist/activeSongName");
log("Script started, current song:", previous);

while (true) {
  await waitForOscChange("/setlist/activeSongName");
  
  const current = osc("/setlist/activeSongName");
  log("Change detected:", previous, "->", current);

  if (previous === "SONG A" && current === "SONG B") {
    log("Condition met, sending MIDI...");
    sendMidiNote("my midi port", 1, 26, 127, 500);
  }

  previous = current;
}

However, you can implement a simpler approach using onOscChange:

let previous = osc("/setlist/activeSongName");

onOscChange("/setlist/activeSongName", ([current]) => {
  if (previous === "SONG A" && current === "SONG B") {
    log("Condition met, sending MIDI...");
    sendMidiNote("my midi port", 1, 26, 127, 500);
  }

  previous = current ?? null;
});

Let me know if this works for you :slight_smile: