From 624684c477f8218e1b9eebcb89c36081c1f05f84 Mon Sep 17 00:00:00 2001
From: Florent Berthaut <florent.berthaut@univ-lille.fr>
Date: Mon, 6 Jan 2025 23:48:19 +0100
Subject: [PATCH] Fix osc sending/receiving

---
 SConstruct             |   7 +-
 demo/Main.tscn         | 159 +++++++++++----------------
 demo/patches/patch1.pd | Bin 813 -> 908 bytes
 patches/gdpd.pd        | Bin 1814 -> 2266 bytes
 src/gdpd.cpp           | 242 ++++++++++++++++++++++++++++++-----------
 src/gdpd.h             |  45 ++++----
 6 files changed, 274 insertions(+), 179 deletions(-)

diff --git a/SConstruct b/SConstruct
index ba31074..5326d1c 100644
--- a/SConstruct
+++ b/SConstruct
@@ -112,7 +112,7 @@ env.Append(CPPDEFINES=[ 'LO_SO_VERSION={11,1,4}',
                         'PRINTF_LL=""'])
 
 if env["platform"] == "linux":
-	env.Append(CPPDEFINES=['__UNIX_JACK__', 'HAVE_LIBDL'])
+	env.Append(CPPDEFINES=['__UNIX_JACK__', 'HAVE_LIBDL', 'HAVE_POLL=1'])
 	env.Append(LIBS=['jack', 'pthread'])
 	env.Append(LDPATH=['/usr/lib/x86_64-linux-gnu'])
 	env.Append(CFLAGS=['-Wno-int-to-pointer-cast', '-Wno-pointer-to-int-cast',
@@ -129,7 +129,8 @@ elif env["platform"] == "android":
 						'-fomit-frame-pointer'])
 	env.Append(CXXFLAGS=['-std=c++17'])
 elif env["platform"] == "windows": 
-	env.Append(CPPDEFINES=['NOMINMAX', '__WINDOWS_DS__', 'PD_INTERNAL'])
+	env.Append(CPPDEFINES=['NOMINMAX', '__WINDOWS_DS__',
+                            'PD_INTERNAL', 'HAVE_SELECT=1'])
 elif env["platform"] == "macos": 
 	env.Append(CPPDEFINES=['NOMINMAX', '__MACOSX_CORE__', 'PD_INTERNAL'])
 
@@ -146,4 +147,6 @@ else:
 		source=sources,
 	)
 
+# Copy pd patches
+
 Default(library)
diff --git a/demo/Main.tscn b/demo/Main.tscn
index 83f3d8a..a9b4740 100644
--- a/demo/Main.tscn
+++ b/demo/Main.tscn
@@ -3,102 +3,59 @@
 [sub_resource type="GDScript" id="1"]
 script/source = "extends Control
 
-@onready var _gdpd = GdPd.new()
+@onready var _gdpd = $GdPd
 
 func _ready():
-	add_child(_gdpd)
+	pass
 
 func _process(delta):
 	# Get messages from the patch
-	while _gdpd.has_message() :
-		var msg = _gdpd.get_next()
-		print(\"got message from pd \", msg)
-	
-func _load_patch(pd_patch : String) :
-	
-	
-	var fullpath = \"\"
-	if OS.has_feature(\"editor\"):
-		fullpath = ProjectSettings.globalize_path(pd_patch)
-	else:
-		var file = pd_patch.split(\"/\")[-1]
-		var path = pd_patch.trim_suffix(file)
-		# Copy files from the patches folder from res to user
-		if OS.get_name() == \"Android\" :
-			fullpath = \"/sdcard/Android/data/com.example.gdpd/files/\"
-		else :
-			fullpath = OS.get_user_data_dir()
-		var dir = DirAccess.open(\"res://\")
-		fullpath = fullpath.path_join(file)
-		# FIXME do that in C++, and for all .pd and .wav files of the project, on start
-		dir.copy(\"res://\"+path+\"/\"+file, fullpath)
-		
-	
-	print(\"fullpath = \", fullpath)
-	
-	# separate file name from directory
-	var patch_name = fullpath.split(\"/\")[-1]
-	var patch_dir = fullpath.trim_suffix(patch_name)
-
-	# load patch
-	_gdpd.openfile(patch_name, patch_dir)
-
-func _on_Start_pressed() :	
-	# retrieve the list of available input and outputs
-	var inps = _gdpd.get_available_input_devices()
-	var outs = _gdpd.get_available_output_devices()
-	
-	# initialise the first ones
-	_gdpd.init_devices(inps[0], outs[0])
-	
-	# the patch path should be absolute
-	_load_patch(\"patches/patch1.pd\")
-	_load_patch(\"patches/patch2.pd\")
-	
-	# send message to [receive from_godot] with one symbol
-	_gdpd.start_message(1)
-	_gdpd.add_symbol(\"hello\")
-	_gdpd.finish_list(\"from_godot\")
-	
-	# listen to messages sent with [send to_godot]
-	_gdpd.subscribe(\"to_godot\")
-
-
-func _on_start_non_rt_pressed():
-	# initialise without realtime
-	_gdpd.init_nort()
-	
-	# the patch path should be absolute
-	_load_patch(\"patches/patch1.pd\")
-	_load_patch(\"patches/patch2.pd\")
-	
-	# send message to [receive from_godot] with one symbol
-	_gdpd.start_message(1)
-	_gdpd.add_symbol(\"hello\")
-	_gdpd.finish_list(\"from_godot\")
-	
-	# listen to messages sent with [send to_godot]
-	_gdpd.subscribe(\"to_godot\")
-	
+	#while $GdPd.has_message() :
+	#	var msg = _gdpd.get_next()
+	#	print(\"got message from pd \", msg)
+	pass
+
 func _on_Stop_pressed():
-	_gdpd.closefile(\"patches/patch1.pd\")
-	_gdpd.closefile(\"patches/patch2.pd\")
+	_gdpd.close_patch(\"patches/patch1.pd\")
+	#_gdpd.close_patch(\"patches/patch2.pd\")
 	_gdpd.stop()
 
 func _on_HSlider_value_changed(value):
+	_gdpd.send(\"patch1\", [\"pitch\", value])
 	# send message to [receive from_godot] with three elements
-	_gdpd.start_message(3)
-	_gdpd.add_symbol(\"patch1\")
-	_gdpd.add_symbol(\"pitch\")
-	_gdpd.add_float(value)
-	_gdpd.finish_list(\"from_godot\")
+	#_gdpd.start_message(3)
+	#_gdpd.add_symbol(\"patch1\")
+	#_gdpd.add_symbol(\"pitch\")
+	#_gdpd.add_float(value)
+	#_gdpd.finish_list(\"from_godot\")
+	pass
 
 func _on_HSlider2_value_changed(value):
-	_gdpd.start_message(3)
-	_gdpd.add_symbol(\"patch2\")
-	_gdpd.add_symbol(\"pitch\")
-	_gdpd.add_float(value)
-	_gdpd.finish_list(\"from_godot\")
+	#_gdpd.start_message(3)
+	#_gdpd.add_symbol(\"patch2\")
+	#_gdpd.add_symbol(\"pitch\")
+	#_gdpd.add_float(value)
+	#_gdpd.finish_list(\"from_godot\")
+	pass
+
+func _on_gd_pd_got_message(address: String, arguments: Array) -> void:
+	print(\"got message \", address, arguments)
+
+func _on_start_osc_pressed() -> void:
+	_gdpd.set_mode(0)
+	_gdpd.start()
+
+func _on_start_audio_no_rt_pressed() -> void:
+	_gdpd.set_mode(1)
+	_gdpd.open_patch(\"patches/patch1.pd\")
+	#_load_patch(\"patches/patch2.pd\")
+	_gdpd.start()
+
+func _on_start_audio_rt_pressed() -> void:
+	_gdpd.set_mode(2)
+	_gdpd.open_patch(\"patches/patch1.pd\")
+	#_load_patch(\"patches/patch2.pd\")
+	_gdpd.start()
 "
 
 [node name="Control" type="Control"]
@@ -110,29 +67,37 @@ grow_horizontal = 2
 grow_vertical = 2
 script = SubResource("1")
 
-[node name="Start" type="Button" parent="."]
+[node name="StartOSC" type="Button" parent="."]
 layout_mode = 0
 offset_left = 72.0
 offset_top = 80.0
 offset_right = 176.0
 offset_bottom = 128.0
-text = "Start"
+text = "Start OSC"
 
-[node name="Stop" type="Button" parent="."]
+[node name="StartAudioNoRT" type="Button" parent="."]
+layout_mode = 0
+offset_left = 184.0
+offset_top = 80.0
+offset_right = 288.0
+offset_bottom = 128.0
+text = "Start Audio"
+
+[node name="StartAudioRT" type="Button" parent="."]
 layout_mode = 0
 offset_left = 296.0
 offset_top = 80.0
-offset_right = 399.0
+offset_right = 402.0
 offset_bottom = 128.0
-text = "Stop"
+text = "Start Audio RT"
 
-[node name="StartNonRT" type="Button" parent="."]
+[node name="Stop" type="Button" parent="."]
 layout_mode = 0
-offset_left = 184.0
+offset_left = 424.0
 offset_top = 80.0
-offset_right = 290.0
+offset_right = 527.0
 offset_bottom = 128.0
-text = "Start Non RT"
+text = "Stop"
 
 [node name="HSlider" type="HSlider" parent="."]
 layout_mode = 0
@@ -166,8 +131,12 @@ offset_right = 204.0
 offset_bottom = 260.0
 text = "Send pitch to patch2"
 
-[connection signal="pressed" from="Start" to="." method="_on_Start_pressed"]
+[node name="GdPd" type="GdPd" parent="."]
+
+[connection signal="pressed" from="StartOSC" to="." method="_on_start_osc_pressed"]
+[connection signal="pressed" from="StartAudioNoRT" to="." method="_on_start_audio_no_rt_pressed"]
+[connection signal="pressed" from="StartAudioRT" to="." method="_on_start_audio_rt_pressed"]
 [connection signal="pressed" from="Stop" to="." method="_on_Stop_pressed"]
-[connection signal="pressed" from="StartNonRT" to="." method="_on_start_non_rt_pressed"]
 [connection signal="value_changed" from="HSlider" to="." method="_on_HSlider_value_changed"]
 [connection signal="value_changed" from="HSlider2" to="." method="_on_HSlider2_value_changed"]
+[connection signal="got_message" from="GdPd" to="." method="_on_gd_pd_got_message"]
diff --git a/demo/patches/patch1.pd b/demo/patches/patch1.pd
index bee8fcfdb3037ab223c4eb996dfd8858c0f2d870..f1d010c8f321d83c238049dde8fe6d065bccbc77 100644
GIT binary patch
delta 278
zcmZ3>*26x*Svn;(IVZ6wRYA8Pu_Qx5PfuS@Pro3sBsn9sc%p3(lab-XiOrJ@8H-rW
z6pTy_C$C_1G&NT+H&DQ%Pv4qLIYJ>nDNDi3&_cn|QXxI1AZ4-;lg8xlj4H|?F+(F0
zg@U5Yyb`d=+~RZvBXb2qBMXI$)SR4r#mS~jr9y_53I<^5<ovw6)Z`Kc^T`*OL?)kS
lVvROLlQA?@Fi<c@7c^BcP%yMW7d2BbP{0th1Stg@000B`O!oi)

delta 209
zcmeBSU&}VZd18tWlY#lfP0bRy#pw!0<_d;J777K4CCM3v3K^+6Ir)l{4H(N=%@vGH
zEhn#GbmX*9Ft=1lPbo;5?8>A$S({0I@-(J`dP@ZZYcAyoh2;Faywv0p1#<-h1w&&r
mK?{(e5t^VSNYD&T(9lT10AvP=nIQ8NOwd(=Y_ebhi2?v8tv8(j

diff --git a/patches/gdpd.pd b/patches/gdpd.pd
index 952c2b7a6e0b70d2284d1c748246add79a565407..8d7aefbadbc8185576f6f091f5a2c131fae9377b 100644
GIT binary patch
literal 2266
zcmY%PQ%FwCD@!a^urxDJFf}z+urxJOFflVzFf_8}QjSo_Ps&m-G%-^!GBZ`kOD!o%
zO-{`$OI6S<RnSdBRbXVGkdvR7l9ZU2jw)ekppajjT##5)oQfi0Y-p;GlUZD%P*Rkc
ziz;Jcpiq=wT9T@eo>GtkmohUpRxq+O!L-KM(m=t~T%jN(IX|zYC_e|RBeytR0VH8;
ztdLlgUaVjM76thSBx+#*u{$R<FTErKMas|!(*_fBGX+CaONA1JBoKtFH!?9%Fto5x
zD6Y&+%Fj`VQ89!|fow4}Fjgo|%}GrzQ7}+2R6qo&k*TGEv56@*eW1`bF)~xgFD=PQ
zEkPJ(u3%(os8FPkR+OI`pPrwRkB|dt0a;g~kf@Ld*I{H}qyRFg7^($1D9sJb6ikd1
ziWExn<59xc#L`m1$iM*IVW7YS`PInK5FBo)c_6<kSQ;5ZJPeWtYc(=fNY2m81Nk^c
z#So+b;b{wFBL$G7iov$ReE`yHYGS5fY6gyOkil?2n1I69*bpP!LF$c-&|L|NT#$?*
zC@q3gRzXo}L26!#LNQW6g1l~SqJSD!AYB$9YmfsF9IR%h(4<(9SdxrLDCWi%3WkQz
zL<F-26p{)Ebs&$Km?{_<LzJcFLDL{e+}y}i!N|f=AtkdI8eVWeo0*v_7#V^yO<I0Y
zZej@}SP<rdylG-!p<rZYp^#CWqhM%mpkQPGN?}Ik3LrW)x1gj_0h!b_QqVO7Nf{a`
zD5oWZpn|di7{F-*1xQ?ij5js6P%ySIQz%K#ff$W!7=&#=yon$Wg96jY1d`)Z^FRs1
zP{GL9QqRcHK+nj~P|pZj;DFSEGP<#$B|IgesRL<-q$-eNa|06vV^f4;LnCuN13d#h
zw8RJYk*Oi55Gw{H3DgqI#K1_w*w7GEP+<>qXe5Dy*9aPqFfl^~0|jF<G(jVfAexx5
zf`NhwnwW`#fr61GnxH92vpJfenSz0W1)3NrzR_*A0H*{rg_a5i3g`wx5`-a|N<&ad
zWr*$~Ly#vyi42@f;XXG~FjO!!MmNDo!AQXf-J>97AfG}K8QcW0SJ4dsdDRfZ05gzf
z7@h!m7nJT%9R~8R5xUnv?gzynic*j&1!Hvo8iC@<2tBw#p2GC6kqO9Q256ozG698x
zDY_`gzaYa=-2n2iF?u+He5HU*)KI|~!!~d*peF?*3k9%R)G!AnHw8m<wICxEjL_4z
zF(}^AEi(ouZuB4nxfC-XjX??A1j7W7hcN^}sTm_Cj6pub6a_`FF?#5N?14G~0E2K!
Av;Y7A

literal 1814
zcmY%PQ%FwCD@!a^urxDJFf}z+urxJOFflVzFf_8}QjSo_Ps&m-G%-^!GBZ`kOD!o%
zO-{`$OI6S<RnSdBRbXVGkdvR7l9ZU24wlF*PKW3;F;&RPEG|jSQ!p~N)H5<P&@(bL
z)H5<PQm`~KGz6;!*<xyLp<rxk2(qO(H7^C56_y4H`NhcviABY!aBU#R85=^ZP$((N
z%te(kF;FPVFD*$`NKYw9flHYg8!H%DnqWE@Bw=i5sgRtXmzSDcg3ZN<a51(tP%t%D
zC`d`p&nqd)&jA|`@-|4q*jOR4D7{$004xgfAV}2002~$yIjMQ+B^fAEhDNB)0ckNY
zH&ZY)wNxlkNCH8)dQ&3>Lo;)Q;>z5l{2YZC6+|e4EHN}NRwz!*0lD8m!B7F=U~pKO
znL<M(H!(90ZlaN?rGl}EDK;ZPx=f7B6!J?;a#Bm+I*iQ~j4TZmiWJg{@^j<U^HcH>
zav&`rmy{?ZDkQ>n7#SETfD9^zYC(<>a|1I46C;Hpg_8Vu)TlBuS1>XJM|@g-QEno_
z5)(^H1tS9kbSHx%02Dr!kf2V@1BDMFsez=yI*p9su^gjf2vUFuD05Rwu%*Rd=b(7a
z+}J|F&=6v_LP1e#0Vu74T&w^OPmmR+CT0qzX5dr@vL7A>CMG5dhQ@}NF=}F_U~Gi$
z7f>1inPdpcT$#lsa0`o(A_5e2<|YcLVGYt{0kQ@b0k9NppkSb20!@`LF+&9d1tT;u
zBL$F3Na}^DGf^;5Fhx^ms$igCh9+jFV4z@#E@-Y`pkRTf&_cmL!5B@<5~SG>P0$eJ
z7)x|Pkh=}h9b^b{IY>P?%wbM9GzJ-q;c;V7{=g6g`O^r)TvG)@1w(UmH<&6IDHt1|
zi-JPH2tyPU1cqh`klYG)8OX!vmVxvt7@`N45jZ=ehm8@)!^Y^rXaw>wh9KBy=rIHG
zDk!#50?Y{H1q}V52s1(t10#?RjL}086eyVCWeoBHC^AqiGX|wUV|0&!1QbAqqpAgY
i7vwusQIL1Bi5e;xp$8+#si4e;nz)TkKxx4O6gvR>E7iLI

diff --git a/src/gdpd.cpp b/src/gdpd.cpp
index fd6f6fa..4a470d8 100644
--- a/src/gdpd.cpp
+++ b/src/gdpd.cpp
@@ -37,16 +37,34 @@ const int PCM_BUFFER_SIZE = 4096 * 4;
 void GdPd::_bind_methods() {
 	ADD_GROUP("GdPd", "gdpd_");
 
+    /*
+    ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_RANGE, "0,2"), 
+                    "set_mode", "get_mode");
+*/
+    /*
+    ClassDB::add_property(get_class_static(), PropertyInfo(Variant::INT, "mode", 
+                PROPERTY_HINT_ENUM, "OSC, AUDIO, AUDIO_RT", 
+                PROPERTY_USAGE_DEFAULT), "set_mode", "get_mode");
+                */
+
 	ClassDB::bind_method(D_METHOD("get_available_input_devices"),
 					&GdPd::get_available_input_devices);
     ClassDB::bind_method(D_METHOD("get_available_output_devices"),
 					&GdPd::get_available_output_devices);
-    ClassDB::bind_method(D_METHOD("init_devices"), &GdPd::init_devices);
-    ClassDB::bind_method(D_METHOD("init_parameters"), &GdPd::init_parameters);
-    ClassDB::bind_method(D_METHOD("init_nort"), &GdPd::init_nort);
+    ClassDB::bind_method(D_METHOD("set_rt_devices"), &GdPd::set_rt_devices);
+    ClassDB::bind_method(D_METHOD("set_rt_parameters"), &GdPd::set_rt_parameters);
+    ClassDB::bind_method(D_METHOD("set_rt_defaults"), &GdPd::set_rt_defaults);
+    ClassDB::bind_method(D_METHOD("start"), &GdPd::start);
     ClassDB::bind_method(D_METHOD("stop"), &GdPd::stop);
-    ClassDB::bind_method(D_METHOD("openfile"), &GdPd::openfile);
-    ClassDB::bind_method(D_METHOD("closefile"), &GdPd::closefile);
+    ClassDB::bind_method(D_METHOD("open_patch"), &GdPd::open_patch);
+    ClassDB::bind_method(D_METHOD("close_patch"), &GdPd::close_patch);
+
+    ClassDB::bind_method(D_METHOD("set_mode", "p_mode"), &GdPd::set_mode);
+    ClassDB::bind_method(D_METHOD("get_mode"), &GdPd::get_mode);
+
+    ClassDB::bind_method(D_METHOD("send"), &GdPd::send);
+
+    /*
     ClassDB::bind_method(D_METHOD("subscribe"), &GdPd::subscribe);
     ClassDB::bind_method(D_METHOD("has_message"), &GdPd::has_message);
     ClassDB::bind_method(D_METHOD("get_next"), &GdPd::get_next);
@@ -55,11 +73,22 @@ void GdPd::_bind_methods() {
     ClassDB::bind_method(D_METHOD("add_float"), &GdPd::add_float);
     ClassDB::bind_method(D_METHOD("finish_list"), &GdPd::finish_list);
     ClassDB::bind_method(D_METHOD("set_volume"), &GdPd::set_volume);
+    */
+
+    ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", 
+                    PROPERTY_HINT_ENUM, "OSC, AUDIO, AUDIO_RT", 
+                    PROPERTY_USAGE_DEFAULT), 
+                 "set_mode", "get_mode");
 
+	ADD_SIGNAL(MethodInfo("got_message", 
+                PropertyInfo(Variant::STRING, "address"), 
+                PropertyInfo(Variant::ARRAY, "arguments")));
 }
 
-GdPd::GdPd() : m_vol(1) {
-	//create message array
+GdPd::GdPd() {
+    mode = 0;
+    m_receiver = NULL;
+    //m_sender = NULL;
 	m_messages = new Array();
 	m_init=false;
 }
@@ -67,6 +96,14 @@ GdPd::GdPd() : m_vol(1) {
 GdPd::~GdPd() {}
 
 
+void GdPd::set_mode(const int p_mode) {
+    std::cout<<"mode "<<p_mode<<std::endl;
+    mode = p_mode;
+}
+
+int GdPd::get_mode() const {
+    return mode;
+}
 
 int GdPd::audioCallback(void *outputBuffer, void *inputBuffer, 
 					    unsigned int nBufferFrames, double streamTime, 
@@ -79,26 +116,29 @@ int GdPd::audioCallback(void *outputBuffer, void *inputBuffer,
 
 Array GdPd::get_available_input_devices() {
 	Array gdlist;
+    /*
 	for(int d=0; d<m_audio.getDeviceCount(); d++) {
 		if(m_audio.getDeviceInfo(d).inputChannels>0) {
 			gdlist.push_back(m_audio.getDeviceInfo(d).name.c_str());
 		}
-	}
+	}*/
 	return gdlist;
 }
 
 Array GdPd::get_available_output_devices() {
 	Array gdlist;
+    /*
 	for(int d=0; d<m_audio.getDeviceCount(); d++) {
 		if(m_audio.getDeviceInfo(d).outputChannels>0) {
 			gdlist.push_back(m_audio.getDeviceInfo(d).name.c_str());
 		}
-	}
+	}*/
 	return gdlist;
 }
 
 
-void GdPd::init_devices(String inputDevice, String outputDevice) {
+void GdPd::set_rt_devices(String inputDevice, String outputDevice) {
+    /*
 	std::string inpStr(inputDevice.utf8().get_data());
 	std::string outStr(outputDevice.utf8().get_data());
 
@@ -118,11 +158,12 @@ void GdPd::init_devices(String inputDevice, String outputDevice) {
 	m_nbOutputs = outInfo.outputChannels;
 	m_sampleRate = outInfo.preferredSampleRate;
 	m_bufferFrames = 128;
-
-    m_realtime=true;
+    */
 }
 
-void GdPd::init_parameters(int nbInputs, int nbOutputs, int sampleRate, int bufferSize) {
+void GdPd::set_rt_parameters(int nbInputs, int nbOutputs, 
+                             int sampleRate, int bufferSize) {
+    /*
 	m_inputDevice = m_audio.getDefaultInputDevice();
 	m_outputDevice = m_audio.getDefaultOutputDevice();
 	RtAudio::DeviceInfo inpInfo = m_audio.getDeviceInfo(m_inputDevice);
@@ -131,11 +172,15 @@ void GdPd::init_parameters(int nbInputs, int nbOutputs, int sampleRate, int buff
 	m_nbOutputs = std::min<int>(nbOutputs, outInfo.outputChannels);
 	m_sampleRate = sampleRate;
 	m_bufferFrames = std::max<int>(64, bufferSize);
+    */
+}
+
+void GdPd::set_rt_defaults() {
 
-    m_realtime=true;
 }
 
-int GdPd::init_nort() {
+/*
+int GdPd::start() {
     m_nbInputs=0;
     m_nbOutputs=2;
     m_sampleRate=44100;
@@ -152,45 +197,44 @@ int GdPd::init_nort() {
 	m_pd.setReceiver(this);
 	m_init=true;
 
-    // Create stream player
-	AudioStreamPlayer* p = memnew(AudioStreamPlayer());
-    add_child(p);
-
-    Ref<GdPdStream> s = memnew(GdPdStream());
-    s->setGdPd(this);
-
-    p->set_stream(s);
-    p->play();
 
 	print("Initialized");
 
 	return 0;
-}
+}*/
 
 int GdPd::start() {
+    print("Starting with mode "+std::to_string(mode));
 
-    if(m_mode==OSC) {
-
-        //Create OSC sender
-        m_sender = NULL;
+    if(mode==OSC) {//OSC MODE
+        //Create OSC sender and receiver (multicast if no address has been set)
+        /*
         m_sender = lo_server_new_multicast(
-                            MULTICAST_ADDRESS.c_str(), SENDER_PORT, NULL);
-        m_receiver = NULL;
+                            MULTICAST_ADDRESS.c_str(), 
+                            std::to_string(SENDER_PORT).c_str(), 
+                            errorHandler);
+                            */
+        m_destination = lo_address_new(MULTICAST_ADDRESS.c_str(),
+                                        std::to_string(SENDER_PORT).c_str());
         m_receiver = lo_server_new_multicast(
-                            MULTICAST_ADDRESS.c_str(), RECEIVER_PORT, NULL);
+                            MULTICAST_ADDRESS.c_str(), 
+                            std::to_string(RECEIVER_PORT).c_str(),
+                            errorHandler);
         /*
-        m_sender = lo_server_new_with_proto(
-                            to_string(UDP_SERVER_PORT).c_str(), 
+        m_receiver = lo_server_new_with_proto(
+                            std::to_string(RECEIVER_PORT).c_str(),
                             LO_UDP, NULL);
-        */
+                            */
         if(m_receiver!=NULL) {
             lo_server_add_method(m_receiver, NULL, NULL, oscHandler, this);
+            m_init = true;
         }
         else {
-            cout<<"GdPd : Could not create UDP connection"<<endl;
+            print("Could not create UDP connection");
         }
     }
-    else {
+    /*
+    else { //AUDIO MODE
         RtAudio::StreamParameters outParams, inpParams;
         inpParams.deviceId = m_inputDevice;
         inpParams.nChannels = m_nbInputs;
@@ -209,7 +253,7 @@ int GdPd::start() {
         //start dsp
         m_pd.computeAudio(true);
 
-        if(m_mode==AUDIO_RT) {
+        if(mode==AUDIO_RT) {
             //intialize rtaudio
             if(m_audio.getDeviceCount()==0){
                 UtilityFunctions::print("There are no available sound devices.");
@@ -234,44 +278,91 @@ int GdPd::start() {
             }
         }
         else {
+            // Create stream player
+            AudioStreamPlayer* p = memnew(AudioStreamPlayer());
+            add_child(p);
+
+            Ref<GdPdStream> s = memnew(GdPdStream());
+            s->setGdPd(this);
+
+            p->set_stream(s);
+            p->play();
         }
 
         //create message hook
-        m_pd.subscribe("to_gdpd");
+        m_pd.subscribe("to_godot");
         m_pd.setReceiver(this);
         m_init=true;
     }
 
 	print("Initialized");
+    */
 
 	return 0;
 }
 
 void GdPd::stop() {
 	m_init=false;
-    if(m_realtime) {
-        m_audio.stopStream();
-        m_audio.closeStream();
+    if(mode==OSC) {
+        lo_server_del_method(m_receiver, NULL, NULL);
+        lo_server_free(m_receiver);
+        lo_address_free(m_destination);
     }
+    /*
     else {
+        if(mode==AUDIO_RT) {
+            m_audio.stopStream();
+            m_audio.closeStream();
+        }
+        else {
+        }
+        m_pd.computeAudio(false);
     }
-	m_pd.computeAudio(false);
+    */
 	print("Stopped");
 }
 
-void GdPd::process(float delta) {
+void GdPd::send(String address, Array arguments) {
+    if(mode==OSC) {
+        lo_message msg = lo_message_new();
+        lo_message_add_int32(msg, 10);
+        std::string addrStr(address.utf8().get_data());
+        addrStr = std::string("/gdpd/patch/")+addrStr;
+        lo_send_message(m_destination, addrStr.c_str(), msg);
+    }
+}
+
+void GdPd::_process(double delta) {
+    if(!m_init) {
+        return;
+    }
+
+    if(mode==OSC) {
+        if(m_receiver!=NULL) {
+            int res = lo_server_recv_noblock(m_receiver, 1);
+            //print("received "+std::to_string(res));
+        }
+    }
     /*
-    if(m_udpServer!=NULL) {
-        lo_server_recv_noblock(m_udpServer, 10);
-    }*/
+    else {
+        m_pd.receiveMessages();
+
+        //FIXME for each message, call signal with address and arguments
+        emit_signal("got_message", "blup");
+    }
+    */
 }
 
 void GdPd::handleOSC(const char* path, const char* types, 
-                                lo_arg** argv, int argc, lo_message msg) {
+                     lo_arg** argv, int argc, lo_message msg) {
+    print(path);
+    //FIXME call signal with address and arguments
+    emit_signal("got_message", "blup");
 }
 
 void GdPd::processAudio(void *outputBuffer, void *inputBuffer, 
 						unsigned int nBufferFrames) {
+    /*
 	int ticks = nBufferFrames / libpd_blocksize();
 
 	m_pd.processFloat(ticks, (float*)inputBuffer, (float*)outputBuffer);
@@ -280,9 +371,32 @@ void GdPd::processAudio(void *outputBuffer, void *inputBuffer,
 	for(int b=0; b<nBufferFrames*m_nbOutputs; ++b) {
 		((float*)outputBuffer)[b]*=m_vol;
 	}
+    */
 }
 
-bool GdPd::openfile(godot::String baseStr, godot::String dirStr) {
+bool GdPd::open_patch(godot::String patch) {
+    std::string patchStr(patch.utf8().get_data());
+
+    /*
+    	var fullpath = ""
+	if OS.has_feature("editor"):
+		fullpath = ProjectSettings.globalize_path(pd_patch)
+	else:
+		var file = pd_patch.split("/")[-1]
+		var path = pd_patch.trim_suffix(file)
+		# Copy files from the patches folder from res to user
+		if OS.get_name() == "Android" :
+			fullpath = "/sdcard/Android/data/com.example.gdpd/files/"
+		else :
+			fullpath = OS.get_user_data_dir()
+		var dir = DirAccess.open("res://")
+		fullpath = fullpath.path_join(file)
+		# FIXME do that in C++, and for all .pd and .wav files of the project, on start
+		dir.copy("res://"+path+"/"+file, fullpath)
+        	var patch_name = fullpath.split("/")[-1]
+	var patch_dir = fullpath.trim_suffix(patch_name)
+*/
+    /*
 	std::string baseS(baseStr.utf8().get_data());
 	std::string dirS(dirStr.utf8().get_data());
 
@@ -299,24 +413,27 @@ bool GdPd::openfile(godot::String baseStr, godot::String dirStr) {
 	else {
 		print("Opened patch "+baseS);
 		m_patchsMap[baseS] = p1;
-	}
+	}*/
     return true;
 }
 
-void GdPd::closefile(godot::String baseStr) {
-	std::string baseS(baseStr.utf8().get_data());
-	if(m_patchsMap.find(baseS)!=m_patchsMap.end()) {
-		m_pd.closePatch(m_patchsMap[baseS]);
-		m_patchsMap.erase(baseS);
-		print("Closed patch "+baseS);
-	}
+void GdPd::close_patch(godot::String patch) {
+	std::string patchStr(patch.utf8().get_data());
+    /*
+	if(m_patchsMap.find(patchStr)!=m_patchsMap.end()) {
+		m_pd.closePatch(m_patchsMap[patchStr]);
+		m_patchsMap.erase(patchStr);
+		print("Closed patch "+patchStr);
+	}*/
 }
 
+/*
 void GdPd::subscribe(String symbStr) {
 	std::string symbS(symbStr.utf8().get_data());
 	m_pd.subscribe(symbS.c_str());
-}
+}*/
 
+/*
 bool GdPd::has_message() {
 	if(m_init) {
 		//receive new messages
@@ -357,9 +474,10 @@ int GdPd::finish_list(String destStr) {
     int res = libpd_finish_list(destS.c_str());
     return res;
 }
+*/
 
 void GdPd::print(const std::string& message) {
-	UtilityFunctions::print((std::string("GDPD : ")+message).c_str());
+	UtilityFunctions::print((std::string("GdPd : ")+message).c_str());
 }
 
 void GdPd::receiveList(const std::string& dest, const pd::List& list) {
@@ -378,10 +496,6 @@ void GdPd::receiveList(const std::string& dest, const pd::List& list) {
 	m_messages->push_back(gdlist);
 }
 
-void GdPd::set_volume(float vol) {
-	m_vol=vol;
-}
-
 /* GdPdStream */
 GdPdStream::GdPdStream() {
 
@@ -423,3 +537,5 @@ int32_t GdPdStreamPlayback::_mix_resampled(AudioFrame *buffer,
 float GdPdStreamPlayback::_get_stream_sampling_rate() const {
     return AudioServer::get_singleton()->get_mix_rate();
 }
+
+
diff --git a/src/gdpd.h b/src/gdpd.h
index b092b32..f41ff85 100644
--- a/src/gdpd.h
+++ b/src/gdpd.h
@@ -58,14 +58,15 @@ protected:
                             lo_arg ** argv,
                             int argc, lo_message msg, void *user_data) {
         GdPd* gdpd = (GdPd*)user_data; 
+        std::cout<<"got osc message"<<std::endl;
         gdpd->handleOSC(path, types, argv, argc, msg);
         return 0;
     }
     static void errorHandler(int num, const char *msg, const char *path){
         std::cout<<"GdPd Error : "<<msg<<" "<<path<<std::endl;
     }
-    virtual void handleOSC(const char* path, const char* types, 
-                            lo_arg** argv, int argc, lo_message msg){};
+    void handleOSC(const char* path, const char* types, 
+                    lo_arg** argv, int argc, lo_message msg);
 
 private:
     bool m_realtime;
@@ -87,33 +88,42 @@ private:
 	bool m_init;
 
     enum Mode {OSC, AUDIO, AUDIO_RT};
-    int m_mode;
+    int mode;
 
     const int SENDER_PORT = 9211;
     const int RECEIVER_PORT = 9212;
     const std::string MULTICAST_ADDRESS = "239.210.211.212";
-    lo_server m_sender;
+    //lo_server m_sender;
     lo_server m_receiver;
+    lo_address m_destination;
     int m_senderPort;
     int m_receiverPort;
 
-private:
-	int start();
-
 public:
 
 	GdPd();
 	virtual ~GdPd();
 
-	//libpd functions
+    void set_mode(const int p_mode);
+    int get_mode() const;
+
 	Array get_available_input_devices();
 	Array get_available_output_devices();
-    int init_nort();
-	int init_devices(String inputDevice, String outputDevice);
-	int init_parameters(int nbInputs, int nbOutputs, int sampleRate, int bufferSize);
+	void set_rt_devices(String inputDevice, String outputDevice);
+	void set_rt_parameters(int nbInputs, int nbOutputs, int sampleRate, int bufferSize);
+    void set_rt_defaults();
+
+	int start();
 	void stop();
-	bool openfile(String basename, String dirname);
-	void closefile(String basename);
+
+    void _process(double delta) override;
+
+	bool open_patch(String basename);
+	void close_patch(String basename);
+
+    void send(String destination, Array arguments);
+
+    /*
 	bool has_message();
 	Array get_next();
 	int blocksize();
@@ -122,15 +132,12 @@ public:
 	void add_symbol(String symbStr);
 	void add_float(float val);
 	int finish_list(String destStr);
+    */
 
-	//libpd hooks
 	virtual void print(const std::string& message);
-	void receiveList(const std::string& dest, const pd::List& list);
-
-	//godot functions
-	void set_volume(float vol);
-	inline const float& get_volume(){return m_vol;}
 
+	//libpd hooks
+	void receiveList(const std::string& dest, const pd::List& list);
 
 	//rtaudio
 	static int audioCallback(void *outputBuffer, void *inputBuffer, 
-- 
GitLab