extends Node class_name OSCSender @export var default_address:String = "0.0.0.0" @export var default_port: int = 9001 @export var debug: bool = false var _address: String var _port: int var socket = PacketPeerUDP.new() func _init(): _address = default_address _port = default_port func _debug(msg): if debug: print(msg) func set_destination(dest): if dest is int: socket.set_dest_address(_address, dest) _port = dest elif dest is String: socket.set_dest_address(dest, _port) _address = dest elif dest is Array: socket.set_dest_address(dest[0], dest[1]) _address = dest[0] _port = dest[1] func send_osc(dest, oscaddress: String, argtypes: String, values: Array): assert(oscaddress.begins_with("/")) var buf = StreamPeerBuffer.new() buf.set_big_endian(true) _pack_string(buf, oscaddress) _pack_string(buf, "," + argtypes) var vidx: int = 0 for i in argtypes.length(): var typetag = argtypes[i] var inc_vidx = true match typetag: "i": buf.put_32(values[vidx]) "h": buf.put_64(values[vidx]) "f": buf.put_float(values[vidx]) "d": buf.put_double(values[vidx]) "c": buf.put_32(values[vidx]) "s", "S": _pack_string(buf, values[vidx]) "b": _pack_blob(buf, values[vidx]) "t": assert(values[i].size() == 8) buf.put_data(values[vidx]) "m", "r": assert(values[vidx].size() == 4) buf.put_data(PackedByteArray(values[vidx])) "TFI": inc_vidx = false # no argument value sent _: _debug("Argument type '%s' not supported." % typetag) return FAILED if inc_vidx: vidx += 1 if dest != null: set_destination(dest) socket.put_packet(buf.get_data_array()) return OK func _pack_string(buf: StreamPeerBuffer, s: String): ## Pack a string into a binary OSC buffer buf.put_data(s.to_ascii_buffer()) # pad to next 32-bit offset while buf.get_position() % 4: buf.put_u8(0) func _pack_blob(buf, blob): ## Pack a PackedByteArray, Array or String into a binary OSC buffer if blob is String: blob = blob.to_utf8_buffer() elif blob is Array: blob = PackedByteArray(blob) assert(blob.size() < 2 ** 31) # blob size per spec is _signed_ 32-bit int buf.put_32(blob.size()) buf.put_data(blob) # pad to next 32-bit offset while buf.get_position() % 4: buf.put_u8(0)