godot_osc_demo/osc_sender.gd

109 lines
2.2 KiB
GDScript3
Raw Normal View History

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)