Compare commits

..

No commits in common. "b7ef9bc01b862339d64cc95710d1faa31ed4dcdb" and "91ce62f680e6969fe58f3941f0c9159c8457e259" have entirely different histories.

10 changed files with 67 additions and 222 deletions

View File

@ -1,7 +1,5 @@
extends Node extends Node
class_name OSCReceiver
@export var default_address:String = "0.0.0.0" @export var default_address:String = "0.0.0.0"
@export var default_port: int = 9001 @export var default_port: int = 9001
@ -53,11 +51,6 @@ func stop_server():
_server.stop() _server.stop()
func _debug(msg):
if debug:
print(msg)
func _poll(): func _poll():
if not _server.is_listening(): if not _server.is_listening():
return return
@ -81,24 +74,24 @@ func _poll():
_debug("OSC arg types: %s" % types) _debug("OSC arg types: %s" % types)
if _observers.has([address, types]): if _observers.has([address, types]):
var values = _parse_osc_values(packet.slice(offset), types) var values = _parse_osc_values(packet, types, offset)
if values == null: if values == null:
_debug("Invalid/Unsupported OSC message.") _debug("Invalid/Unsupported OSC message.")
elif values.size() != types.length(): elif values.size() != types.length():
_debug("Mismatch between expected / received number of OSC arguments.") _debug("Mismatch between expected / received number of OSC arguments.")
else: else:
var msg_info = { values.append({
"ip": sender_ip, "ip": sender_ip,
"port": sender_port, "port": sender_port,
"address": address, "address": address,
"types": types "types": types
} })
for callback in _observers[[address, types]]: for callback in _observers[[address, types]]:
callback.call(msg_info, values) callback.callv(values)
func _parse_osc_addr_and_types(packet: PackedByteArray): func _parse_osc_addr_and_types(packet):
var asep = packet.find(0) var asep = packet.find(0)
var address = packet.slice(0, asep).get_string_from_ascii() var address = packet.slice(0, asep).get_string_from_ascii()
@ -110,11 +103,10 @@ func _parse_osc_addr_and_types(packet: PackedByteArray):
return [address, types, tsep + (4 - tsep % 4)] return [address, types, tsep + (4 - tsep % 4)]
func _parse_osc_values(packet: PackedByteArray, types: String): func _parse_osc_values(packet, types, offset):
var result
var values = [] var values = []
var stream = StreamPeerBuffer.new() var stream = StreamPeerBuffer.new()
stream.set_data_array(packet) stream.set_data_array(packet.slice(offset))
stream.set_big_endian(true) stream.set_big_endian(true)
for type_id in types: for type_id in types:
@ -134,7 +126,7 @@ func _parse_osc_values(packet: PackedByteArray, types: String):
var null_found = false var null_found = false
while not null_found: while not null_found:
for _dummy in range(4): for _i in range(4):
var ch = stream.get_u8() var ch = stream.get_u8()
if not null_found and ch != 0: if not null_found and ch != 0:
value.append(char(ch)) value.append(char(ch))
@ -144,24 +136,12 @@ func _parse_osc_values(packet: PackedByteArray, types: String):
values.append("".join(value)) values.append("".join(value))
"b": "b":
var count = stream.get_u32() var count = stream.get_u32()
result = stream.get_data(count) values.append(stream.get_data(count))
if result[0] == OK:
values.append(result[1])
if count % 4: if count % 4:
stream.seek(stream.get_position() + (4 - count % 4)) stream.seek(stream.get_position() + (count % 4))
else:
_debug("Could not read OSC blob argument.")
return
"t": "t":
result = stream.get_data(8) values.append(stream.get_data(8))
if result[0] == OK:
values.append(result[1])
else:
_debug("Could not read OSC timetag argument.")
return
"m", "r": "m", "r":
values.append([ values.append([
stream.get_u8(), stream.get_u8(),
@ -176,7 +156,12 @@ func _parse_osc_values(packet: PackedByteArray, types: String):
"I", "N": "I", "N":
values.append(null) values.append(null)
_: _:
_debug("Argument type '%s' not supported." % type_id) _debug("Argument type '%s' not yet supported." % type_id)
return return
return values return values
func _debug(msg):
if debug:
print(msg)

View File

@ -1,9 +1,9 @@
extends VSlider extends VSlider
func recv_osc(msg_info, values): func recv_osc(val, msg_info):
print("Sender IP: %s" % msg_info["ip"]) print("Sender IP: %s" % msg_info["ip"])
print("Sender Port: %d" % msg_info["port"]) print("Sender Port: %d" % msg_info["port"])
print("Address: %s" % msg_info["address"]) print("Adress: %s" % msg_info["address"])
print("Types: %s" % msg_info["types"]) print("Types: %s" % msg_info["types"])
set_value_no_signal(clampf(values[0], 0.0, 1.0)) set_value(clampf(val, 0.0, 1.0))

View File

@ -1,9 +1,9 @@
extends Button extends Button
func recv_osc(msg_info, values): func recv_osc(val, msg_info):
print("Sender IP: %s" % msg_info["ip"]) print("Sender IP: %s" % msg_info["ip"])
print("Sender Port: %d" % msg_info["port"]) print("Sender Port: %d" % msg_info["port"])
print("Address: %s" % msg_info["address"]) print("Adress: %s" % msg_info["address"])
print("Types: %s" % msg_info["types"]) print("Types: %s" % msg_info["types"])
set_pressed_no_signal(bool(values[0])) set_pressed_no_signal(bool(val))

23
UI.gd Normal file
View File

@ -0,0 +1,23 @@
extends Control
func _ready():
var scene = preload("res://osc_receiver.tscn")
var osc_server = scene.instantiate()
add_child(osc_server)
# configure all sensors
for i in range(4):
var nodename = "VSlider%d" % (i + 1)
var osc_addr = "/slider/%d/set" % i
var slider_node = find_child(nodename)
osc_server.register_callback(osc_addr, "f", slider_node.recv_osc)
for i in range(4):
var nodename = "Button%d" % (i + 1)
var osc_addr = "/button/%d/set" % i
var button_node = find_child(nodename)
osc_server.register_callback(osc_addr, "i", button_node.recv_osc)
# start listening for osc messages
osc_server.start_server()

24
UI.tscn
View File

@ -1,8 +1,8 @@
[gd_scene load_steps=8 format=3 uid="uid://8xyprd3yldfg"] [gd_scene load_steps=8 format=3 uid="uid://8xyprd3yldfg"]
[ext_resource type="Script" path="res://ui.gd" id="1_28t32"] [ext_resource type="Script" path="res://UI.gd" id="1_ft657"]
[ext_resource type="Script" path="res://slider.gd" id="2_7hpi4"] [ext_resource type="Script" path="res://Slider.gd" id="2_310mb"]
[ext_resource type="Script" path="res://toggle_button.gd" id="3_ch7hh"] [ext_resource type="Script" path="res://ToggleButton.gd" id="3_ct66k"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_y0b18"] [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_y0b18"]
bg_color = Color(1, 0, 0, 1) bg_color = Color(1, 0, 0, 1)
@ -23,7 +23,7 @@ anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("1_28t32") script = ExtResource("1_ft657")
[node name="MarginContainer" type="MarginContainer" parent="."] [node name="MarginContainer" type="MarginContainer" parent="."]
layout_mode = 1 layout_mode = 1
@ -52,7 +52,7 @@ max_value = 1.0
step = 0.01 step = 0.01
tick_count = 11 tick_count = 11
ticks_on_borders = true ticks_on_borders = true
script = ExtResource("2_7hpi4") script = ExtResource("2_310mb")
[node name="VSlider2" type="VSlider" parent="MarginContainer/GridContainer"] [node name="VSlider2" type="VSlider" parent="MarginContainer/GridContainer"]
custom_minimum_size = Vector2(50, 300) custom_minimum_size = Vector2(50, 300)
@ -63,7 +63,7 @@ max_value = 1.0
step = 0.01 step = 0.01
tick_count = 11 tick_count = 11
ticks_on_borders = true ticks_on_borders = true
script = ExtResource("2_7hpi4") script = ExtResource("2_310mb")
[node name="VSlider3" type="VSlider" parent="MarginContainer/GridContainer"] [node name="VSlider3" type="VSlider" parent="MarginContainer/GridContainer"]
custom_minimum_size = Vector2(50, 300) custom_minimum_size = Vector2(50, 300)
@ -74,7 +74,7 @@ max_value = 1.0
step = 0.01 step = 0.01
tick_count = 11 tick_count = 11
ticks_on_borders = true ticks_on_borders = true
script = ExtResource("2_7hpi4") script = ExtResource("2_310mb")
[node name="VSlider4" type="VSlider" parent="MarginContainer/GridContainer"] [node name="VSlider4" type="VSlider" parent="MarginContainer/GridContainer"]
custom_minimum_size = Vector2(50, 300) custom_minimum_size = Vector2(50, 300)
@ -85,32 +85,32 @@ max_value = 1.0
step = 0.01 step = 0.01
tick_count = 11 tick_count = 11
ticks_on_borders = true ticks_on_borders = true
script = ExtResource("2_7hpi4") script = ExtResource("2_310mb")
[node name="Button1" type="Button" parent="MarginContainer/GridContainer"] [node name="Button1" type="Button" parent="MarginContainer/GridContainer"]
layout_mode = 2 layout_mode = 2
theme_override_styles/pressed = SubResource("StyleBoxFlat_y0b18") theme_override_styles/pressed = SubResource("StyleBoxFlat_y0b18")
toggle_mode = true toggle_mode = true
text = "1" text = "1"
script = ExtResource("3_ch7hh") script = ExtResource("3_ct66k")
[node name="Button2" type="Button" parent="MarginContainer/GridContainer"] [node name="Button2" type="Button" parent="MarginContainer/GridContainer"]
layout_mode = 2 layout_mode = 2
theme_override_styles/pressed = SubResource("StyleBoxFlat_iu8u7") theme_override_styles/pressed = SubResource("StyleBoxFlat_iu8u7")
toggle_mode = true toggle_mode = true
text = "2" text = "2"
script = ExtResource("3_ch7hh") script = ExtResource("3_ct66k")
[node name="Button3" type="Button" parent="MarginContainer/GridContainer"] [node name="Button3" type="Button" parent="MarginContainer/GridContainer"]
layout_mode = 2 layout_mode = 2
theme_override_styles/pressed = SubResource("StyleBoxFlat_7e33t") theme_override_styles/pressed = SubResource("StyleBoxFlat_7e33t")
toggle_mode = true toggle_mode = true
text = "3" text = "3"
script = ExtResource("3_ch7hh") script = ExtResource("3_ct66k")
[node name="Button4" type="Button" parent="MarginContainer/GridContainer"] [node name="Button4" type="Button" parent="MarginContainer/GridContainer"]
layout_mode = 2 layout_mode = 2
theme_override_styles/pressed = SubResource("StyleBoxFlat_eeife") theme_override_styles/pressed = SubResource("StyleBoxFlat_eeife")
toggle_mode = true toggle_mode = true
text = "4 " text = "4 "
script = ExtResource("3_ch7hh") script = ExtResource("3_ct66k")

7
osc_receiver.tscn Normal file
View File

@ -0,0 +1,7 @@
[gd_scene load_steps=2 format=3 uid="uid://bqci5bw1h0lh7"]
[ext_resource type="Script" path="res://OSCReceiver.gd" id="1_ujyu5"]
[node name="OSCReceiver" type="Node"]
script = ExtResource("1_ujyu5")
debug = true

View File

@ -1,108 +0,0 @@
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)

View File

@ -10,7 +10,7 @@ config_version=5
[application] [application]
config/name="OSC Demo" config/name="OSCReceiver Demo"
run/main_scene="res://UI.tscn" run/main_scene="res://UI.tscn"
config/features=PackedStringArray("4.1") config/features=PackedStringArray("4.1")

View File

@ -1,13 +0,0 @@
HOST=localhost
PORT=9001
for ctrl in 0 1 2 3; do
for value in `LC_ALL=C seq 0.1 0.1 1.0`; do
oscsend $HOST $PORT /slider/$ctrl/set f $value
sleep 0.1
done
oscsend $HOST $PORT /button/$ctrl/set i 1
sleep 1
oscsend $HOST $PORT /button/$ctrl/set i 0
done

49
ui.gd
View File

@ -1,49 +0,0 @@
extends Control
const OSCReceiver = preload("res://osc_receiver.gd")
var osc_server: OSCReceiver
const OSCSender = preload("res://osc_sender.gd")
var osc_client: OSCSender
func _ready():
osc_client = OSCSender.new()
osc_server = OSCReceiver.new()
add_child(osc_server)
var button_callback = Callable(self, "_button_pressed")
var slider_callback = Callable(self, "_slider_moved")
# configure all sensors
for i in range(4):
var nodename = "VSlider%d" % (i + 1)
var osc_addr = "/slider/%d/set" % i
var slider_node = find_child(nodename)
osc_server.register_callback(osc_addr, "f", slider_node.recv_osc)
slider_node.value_changed.connect(slider_callback.bind(i))
for i in range(4):
var nodename = "Button%d" % (i + 1)
var osc_addr = "/button/%d/set" % i
var button_node = find_child(nodename)
osc_server.register_callback(osc_addr, "i", button_node.recv_osc)
button_node.pressed.connect(button_callback.bind(button_node, i))
# start listening for osc messages
osc_server.start_server()
func _button_pressed(btn: Button, idx: int):
print("Button %s pressed: state = %s" % [idx, btn.button_pressed])
osc_client.send_osc(9000, "/button/%d" % idx, "i", [1 if btn.button_pressed else 0])
func _slider_moved(value: float, idx: int):
print("Slider %d moved: value = %f" % [idx, value])
osc_client.send_osc(9000, "/slider/%d" % idx, "f", [value])
func recv_osc(msg_info, values):
print("Sender IP: %s" % msg_info["ip"])
print("Sender Port: %d" % msg_info["port"])
print("Address: %s" % msg_info["address"])
print("Types: %s" % msg_info["types"])
print("Values:", values)