109 lines
2.2 KiB
GDScript
109 lines
2.2 KiB
GDScript
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)
|