I have an OSC Out DAT that is suppose to send 5 commands. TD only sends one command, which is for tilt. Pan, x_focus, y_focus, and z_focus don’t send. If I change pan to pans, that sends. The second I route TD to OSCRouter and then route that into Protokol (the app im using to view the sent OSC), all works perfectly fine. That shouldn’t be. My OSC Out CHOP works fine and I have no issues. It’s only this DAT that’s causing me a headache. I have 5 separate CHOP Execute DAT’s with scripts to send that OSC command to my OSC Out DAT. Like I said, it works fine with OSCRouter in the mix, but without, only the tilt CHOP Execute DAT works. I dont get it. The full commands are listed below.
/eos/user/0/group/101/param/x_focus/release)
/eos/user/0/group/101/param/y_focus/release)
/eos/user/0/group/101/param/z_focus/release)
/eos/user/0/group/101/param/pan/release)
/eos/user/0/group/101/param/tilt/release)
Can you also post the scripts you are using to send the commands?
Absolutely. Here it is. After discussing with some folks, it turns out that i’m just sending raw commands and not padding it properly. After some digging and understanding how the padding process works, a little helo from chatgpt got me going. Here the before and after scripts
BEFORE:
def onOffToOn(channel, sampleIndex, val, prev):
group_chop = op('Group_select')
osc_out = op('EOS_Release_OSC_Out')
if not group_chop or not osc_out:
return
group = int(group_chop['Group'][0])
address = f"/eos/user/0/group/{group}/param/pan/release"
osc_out.send(address, [])
AFTER:
def onOffToOn(channel, sampleIndex, val, prev):
group_chop = op('Group_select')
osc_out = op('EOS_Release_OSC_Out')
if not group_chop or not osc_out:
return
if 'Group' not in [c.name for c in group_chop.chans()]:
return
try:
group_val = int(group_chop['Group'][0])
except:
return
# Create the OSC address string
address = f"/eos/user/0/group/{group_val}/param/tilt/release"
# Convert to bytes and null-terminate
address_bytes = address.encode('utf-8') + b'\x00'
# Pad to 4-byte boundary
padding = (4 - len(address_bytes) % 4) % 4
address_bytes += b'\x00' * padding
# Send as raw bytes
osc_out.sendBytes(address_bytes)
Then merged all into one CHOP Execute DAT:
def send_padded_osc(osc_out, addr):
padded = addr.encode('utf-8') + b'\x00'
padding_needed = (4 - len(padded) % 4) % 4
padded += b'\x00' * padding_needed
osc_out.sendBytes(padded)
def onOffToOn(channel, sampleIndex, val, prev):
group_chop = op('Group_select')
osc_out = op('EOS_Release_OSC_Out')
if not group_chop or not osc_out:
debug("Missing operator")
return
if 'Group' not in [c.name for c in group_chop.chans()]:
debug("'Group' channel not found")
return
try:
group_val = int(group_chop['Group'][0])
except:
debug("Invalid group")
return
addresses = [
f"/eos/user/0/group/{group_val}/param/x_focus/release",
f"/eos/user/0/group/{group_val}/param/y_focus/release",
f"/eos/user/0/group/{group_val}/param/z_focus/release",
f"/eos/user/0/group/{group_val}/param/pan/release",
f"/eos/user/0/group/{group_val}/param/tilt/release"
]
# Send each OSC message with a slight stagger
for i, addr in enumerate(addresses):
delay_frames = int(i * 0.00 * 60) # 0ms delay per message at 60fps
run(lambda a=addr: send_padded_osc(osc_out, a), delayFrames=delay_frames)
debug(f"Sent 5 OSC commands with delay for Group {group_val}")
You should be using the sendOSC() method ideally, which handles the formatting for you.