Issue with project script sending OSC commands when it is not supposed to and eventually hanging up

I have a script that I have created to attempt to make my External OSC commands being sent to companion more readable. Currently it shows something along the lines of (/location/39/1/5/press), So basically the script is taking the names of the clips (DRUMS ON, TUNE C, etc.) and when it sees that name, it sends out the OSC that corresponds with it. The issues I am running into is that every 30 seconds to 5 minutes-ish it is sending the command (/location/6/0/4/press) which is triggering Waves Tune to the key of C. Also, after some time, companion appears to hang up and crash. I am currently on the latest beta and just wanted to see if anything stuck out to anyone on what could be causing the (seemingly) random firing of the one command. Thanks for any help!

let lastCues = ["", "", "", "", "", "", "", ""];



function normalizeCue(value) {

if (value == null) return null;

return String(value).trim().toUpperCase().replace(/\s+/g, " ");

}

function isCue(cue, aliases) {

return aliases.includes(cue);

}

function handleCue(rawCommand) {

const rawText = String(rawCommand ?? "").trim();

const cue = normalizeCue(rawCommand);



if (!rawText || !cue) return;



  log(`PARSE | raw: "${rawText}"`);



// LIGHTING - PAGE 39

if (isCue(cue, ["DRUM LIGHTS ON", "DRUMS ON", "DRUM ON", "DRUMS UP", "DRUM UP"])) {

    sendOsc("192.168.8.125:12321/location/39/0/8/press");

} else if (isCue(cue, ["DRUM LIGHTS OFF", "DRUMS OFF", "DRUM OFF", "DRUMS DOWN", "DRUM DOWN"])) {

    sendOsc("192.168.8.125:12321/location/39/0/9/press");

} else if (isCue(cue, ["CHOIR LIGHTS ON", "CHOIR ON", "CHOIR UP"])) {

    sendOsc("192.168.8.125:12321/location/39/0/10/press");

} else if (isCue(cue, ["CHOIR LIGHTS OFF", "CHOIR OFF", "CHOIR DOWN"])) {

    sendOsc("192.168.8.125:12321/location/39/0/11/press");

} else if (isCue(cue, ["ORCHESTRA ON", "ORCHESTRA UP", "ORCH ON", "ORCH UP"])) {

    sendOsc("192.168.8.125:12321/location/39/0/12/press");

} else if (isCue(cue, ["ORCHESTRA OFF", "ORCHESTRA DOWN", "ORCH OFF", "ORCH DOWN"])) {

    sendOsc("192.168.8.125:12321/location/39/0/13/press");



// CG1 / PRO PRESENTER - PAGE 21

} else if (isCue(cue, ["ABLESET", "AS", "CG1", "CG1/AS", "CG1 AS", "CG1 ABLESET"])) {

    sendOsc("192.168.8.125:12321/location/21/0/0/press");



// WAVES TUNE - PAGE 6 (Added "TUNE " prefix to eliminate accidental collisions)

} else if (isCue(cue, ["TUNE CHROMATIC"])) {

    sendOsc("192.168.8.125:12321/location/6/0/0/press");

} else if (isCue(cue, ["TUNE A"])) {

    sendOsc("192.168.8.125:12321/location/6/0/1/press");

} else if (isCue(cue, ["TUNE A#", "TUNE BB"])) {

    sendOsc("192.168.8.125:12321/location/6/0/2/press");

} else if (isCue(cue, ["TUNE B"])) {

    sendOsc("192.168.8.125:12321/location/6/0/3/press");

} else if (isCue(cue, ["TUNE C"])) {

    sendOsc("192.168.8.125:12321/location/6/0/4/press");

} else if (isCue(cue, ["TUNE C#", "TUNE DB"])) {

    sendOsc("192.168.8.125:12321/location/6/0/5/press");

} else if (isCue(cue, ["TUNE D"])) {

    sendOsc("192.168.8.125:12321/location/6/0/6/press");

} else if (isCue(cue, ["TUNE D#", "TUNE EB"])) {

    sendOsc("192.168.8.125:12321/location/6/0/7/press");

} else if (isCue(cue, ["TUNE E"])) {

    sendOsc("192.168.8.125:12321/location/6/1/0/press");

} else if (isCue(cue, ["TUNE F"])) {

    sendOsc("192.168.8.125:12321/location/6/1/1/press");

} else if (isCue(cue, ["TUNE F#", "TUNE GB"])) {

    sendOsc("192.168.8.125:12321/location/6/1/2/press");

} else if (isCue(cue, ["TUNE G"])) {

    sendOsc("192.168.8.125:12321/location/6/1/3/press");

} else if (isCue(cue, ["TUNE G#", "TUNE AB"])) {

    sendOsc("192.168.8.125:12321/location/6/1/4/press");



// DIRECT PAGE/ROW/COLUMN ENTRY

} else if (/^\d+\/\d+\/\d+$/.test(rawText)) {

    sendOsc(`192.168.8.125:12321/location/${rawText}/press`);



// GENERIC PAGE 39 NUMBER ENTRY

} else if (/^\d+$/.test(rawText)) {

    sendOsc(`192.168.8.125:12321/location/39/0/${rawText}/press`);

}

}



while (true) {

// Transport Lock: Safely check if Ableton is playing

let abletonIsRolling = false;

try {

if (typeof isPlaying !== 'undefined') {

      abletonIsRolling = isPlaying;

} else {

// Fallback if your specific sandbox version hides the isPlaying variable

      abletonIsRolling = true; 

}

} catch (e) {

    abletonIsRolling = true;

}

for (let i = 0; i < 8; i++) {

const key = `companionCue${i + 1}`;

const cue = String(shared(key, "") ?? "").trim();



if (cue) {

// If the cue is different from memory...

if (cue !== lastCues[i]) {

// Lock it in so we don't spam it

        lastCues[i] = cue;

// Only execute the button press if the timeline is actually moving

if (abletonIsRolling) {

          handleCue(cue);

}

}

} else {

// Clear memory if the playhead rolls off the clip

      lastCues[i] = "";
}
}
await sleep(20);
}

Hey @iamderkis,

I’d generally avoid an infinite loop even with a sleep command as there are more performant alternatives. For example, you can use onOscChange to listen to changes in OSC values. Here’s a version that uses this function:

function normalizeCue(value) {
  if (value == null) return null;

  return String(value).trim().toUpperCase().replace(/\s+/g, " ");
}

function isCue(cue, aliases) {
  return aliases.includes(cue);
}

function handleCue(rawCommand) {
  const rawText = String(rawCommand ?? "").trim();

  const cue = normalizeCue(rawCommand);

  if (!rawText || !cue) return;

  log(`PARSE | raw: "${rawText}"`);

  // LIGHTING - PAGE 39
  if (isCue(cue, ["DRUM LIGHTS ON", "DRUMS ON", "DRUM ON", "DRUMS UP", "DRUM UP"])) {
    sendOsc("192.168.8.125:12321/location/39/0/8/press");
  } else if (isCue(cue, ["DRUM LIGHTS OFF", "DRUMS OFF", "DRUM OFF", "DRUMS DOWN", "DRUM DOWN"])) {
    sendOsc("192.168.8.125:12321/location/39/0/9/press");
  } else if (isCue(cue, ["CHOIR LIGHTS ON", "CHOIR ON", "CHOIR UP"])) {
    sendOsc("192.168.8.125:12321/location/39/0/10/press");
  } else if (isCue(cue, ["CHOIR LIGHTS OFF", "CHOIR OFF", "CHOIR DOWN"])) {
    sendOsc("192.168.8.125:12321/location/39/0/11/press");
  } else if (
    isCue(cue, ["ORCHESTRA ON", "ORCHESTRA UP", "ORCH ON", "ORCH UP"])
  ) {
    sendOsc("192.168.8.125:12321/location/39/0/12/press");
  } else if (
    isCue(cue, ["ORCHESTRA OFF", "ORCHESTRA DOWN", "ORCH OFF", "ORCH DOWN"])
  ) {
    sendOsc("192.168.8.125:12321/location/39/0/13/press");

  // CG1 / PRO PRESENTER - PAGE 21
  } else if (isCue(cue, ["ABLESET", "AS", "CG1", "CG1/AS", "CG1 AS", "CG1 ABLESET"])) {
    sendOsc("192.168.8.125:12321/location/21/0/0/press");

  // WAVES TUNE - PAGE 6 (Added "TUNE " prefix to eliminate accidental collisions)
  } else if (isCue(cue, ["TUNE CHROMATIC"])) {
    sendOsc("192.168.8.125:12321/location/6/0/0/press");
  } else if (isCue(cue, ["TUNE A"])) {
    sendOsc("192.168.8.125:12321/location/6/0/1/press");
  } else if (isCue(cue, ["TUNE A#", "TUNE BB"])) {
    sendOsc("192.168.8.125:12321/location/6/0/2/press");
  } else if (isCue(cue, ["TUNE B"])) {
    sendOsc("192.168.8.125:12321/location/6/0/3/press");
  } else if (isCue(cue, ["TUNE C"])) {
    sendOsc("192.168.8.125:12321/location/6/0/4/press");
  } else if (isCue(cue, ["TUNE C#", "TUNE DB"])) {
    sendOsc("192.168.8.125:12321/location/6/0/5/press");
  } else if (isCue(cue, ["TUNE D"])) {
    sendOsc("192.168.8.125:12321/location/6/0/6/press");
  } else if (isCue(cue, ["TUNE D#", "TUNE EB"])) {
    sendOsc("192.168.8.125:12321/location/6/0/7/press");
  } else if (isCue(cue, ["TUNE E"])) {
    sendOsc("192.168.8.125:12321/location/6/1/0/press");
  } else if (isCue(cue, ["TUNE F"])) {
    sendOsc("192.168.8.125:12321/location/6/1/1/press");
  } else if (isCue(cue, ["TUNE F#", "TUNE GB"])) {
    sendOsc("192.168.8.125:12321/location/6/1/2/press");
  } else if (isCue(cue, ["TUNE G"])) {
    sendOsc("192.168.8.125:12321/location/6/1/3/press");
  } else if (isCue(cue, ["TUNE G#", "TUNE AB"])) {
    sendOsc("192.168.8.125:12321/location/6/1/4/press");

  // DIRECT PAGE/ROW/COLUMN ENTRY
  } else if (/^\d+\/\d+\/\d+$/.test(rawText)) {
    sendOsc(`192.168.8.125:12321/location/${rawText}/press`);

  // GENERIC PAGE 39 NUMBER ENTRY
  } else if (/^\d+$/.test(rawText)) {
    sendOsc(`192.168.8.125:12321/location/39/0/${rawText}/press`);
  }
}

// Set up listeners for shared 
// companionCue1...companionCue8 variables
for (let i = 0; i < 8; i++) {
  const key = `companionCue${i + 1}`;

  onOscChange(`/shared/${key}`, ([value]) => {
    const cue = String(value || "").trim();
    const isPlaying = osc("/global/isPlaying");

    if (isPlaying) {
      handleCue(cue);
    }
  });
}
1 Like

Oh great! I will give this a try! Thank you!

Tested this out today and it worked great! None of the issues I described above. Thank you!