aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xclr.c529
-rwxr-xr-xmakefile32
-rwxr-xr-xmakefile.darwin40
-rwxr-xr-xtest-clr.pd38
4 files changed, 639 insertions, 0 deletions
diff --git a/clr.c b/clr.c
new file mode 100755
index 0000000..fc7b20b
--- /dev/null
+++ b/clr.c
@@ -0,0 +1,529 @@
+/*
+just a dummy clr patch
+
+*/
+
+#include "m_pd.h"
+
+#include <time.h>
+#include <math.h>
+#include <stdlib.h>
+
+// mono
+#include <mono/jit/jit.h>
+#include <mono/metadata/object.h>
+#include <mono/metadata/environment.h>
+#include <mono/metadata/assembly.h>
+#include <mono/metadata/debug-helpers.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define MAX_SELECTORS 256
+#define MAX_OUTLETS 32
+
+void *clr_new(t_symbol *s, int argc, t_atom *argv);
+
+// list of mono methods
+typedef struct selectorList selectorList;
+typedef struct selectorList
+{
+ char *sel; // the selector
+ MonoMethod *func; // the function
+ int type;
+// selectorList *next; // next element of the list
+};
+
+// list of outlets
+typedef struct outletList outletList;
+typedef struct outletList
+{
+ t_outlet *outlet_pointer;
+// selectorList *next; // next element of the list
+};
+
+static t_class *clr_class;
+
+typedef struct _clr
+{
+ t_object x_obj; // myself
+ t_outlet *l_out;
+ // mono stuff
+ MonoDomain *domain;
+ MonoAssembly *assembly;
+ MonoObject *obj;
+ MonoMethod *method, *setUp;
+ MonoClass *klass;
+ int n;
+
+ selectorList selectors[MAX_SELECTORS];
+ outletList outlets[MAX_OUTLETS];
+
+} t_clr;
+
+
+// mono functions
+
+static void mono_clean(t_clr *x)
+{
+ // clean up stuff
+ mono_jit_cleanup (x->domain);
+
+}
+
+void registerMonoMethod(void *x, MonoString *selectorString, MonoString *methodString, int type);
+void createInlet(void *x1, MonoString *selectorString, int type);
+void createOutlet(void *x1, int type);
+void out2outlet(void *x, int outlet, int type, unsigned char *val /* TODO */);
+void post2pd(MonoString *mesString);
+void error2pd(MonoString *mesString);
+
+// load the variables and init mono
+static void mono_load(t_clr *x)
+{
+// const char *file="D:\\Davide\\cygwin\\home\\Davide\\externalTest1.dll";
+ const char *file="PureData.dll";
+ MonoImage *image;
+ MonoMethod *m = NULL, *ctor = NULL, *fail = NULL, *mvalues;
+ gpointer iter;
+ gpointer args [1];
+ int val;
+ int i;
+ double rnd;
+ int random_name_int;
+ char random_name_str[256];
+ srand( (unsigned)time( NULL ) );
+ rnd = rand()/((double)RAND_MAX + 1);
+ random_name_int =(int) (rnd * RAND_MAX);
+ sprintf(random_name_str, "%s-%i",file, random_name_int);
+
+ // prepare the selectors list
+ for (i=0; i<MAX_SELECTORS; i++)
+ {
+ x->selectors[i].sel = 0;
+ x->selectors[i].func = 0;
+ }
+ // and the outlets list
+ for (i=0; i<MAX_OUTLETS; i++)
+ {
+ x->outlets[i].outlet_pointer = 0;
+ }
+
+printf("will load %s, random_name %s\n", file, random_name_str);
+
+ x->domain = mono_jit_init (random_name_str);
+
+ // add mono to C hooks
+ mono_add_internal_call ("PureData.pd::RegisterSelector", registerMonoMethod);
+ mono_add_internal_call ("PureData.pd::ToOutlet", out2outlet);
+ mono_add_internal_call ("PureData.pd::PostMessage", post2pd);
+ mono_add_internal_call ("PureData.pd::ErrorMessage", error2pd);
+ mono_add_internal_call ("PureData.pd::CreateOutlet", createOutlet);
+ mono_add_internal_call ("PureData.pd::CreateInlet", createInlet);
+
+ x->assembly = mono_domain_assembly_open (x->domain, file);
+ if (!x->assembly)
+ {
+ error("clr: assembly not found!");
+ }
+
+ image = mono_assembly_get_image (x->assembly);
+
+
+ x->klass = mono_class_from_name (image, "PureData", "External");
+ if (!x->klass) {
+ error("Can't find MyType in assembly %s\n", mono_image_get_filename (image));
+ //exit (1);
+ }
+ x->obj = mono_object_new (x->domain, x->klass);
+ mono_runtime_object_init (x->obj);
+
+ /* retrieve all the methods we need */
+ iter = NULL;
+ while ((m = mono_class_get_methods (x->klass, &iter))) {
+ if (strcmp (mono_method_get_name (m), "test") == 0) {
+ x->method = m;
+ } else if (strcmp (mono_method_get_name (m), "SetUp") == 0) {
+ x->setUp = m;
+ } else if (strcmp (mono_method_get_name (m), "Fail") == 0) {
+ fail = m;
+ } else if (strcmp (mono_method_get_name (m), "Values") == 0) {
+ mvalues = m;
+ } else if (strcmp (mono_method_get_name (m), ".ctor") == 0) {
+ /* Check it's the ctor that takes two args:
+ * as you see a contrsuctor is a method like any other.
+ */
+ MonoMethodSignature * sig = mono_method_signature (m);
+ if (mono_signature_get_param_count (sig) == 2) {
+ ctor = m;
+ }
+ }
+ }
+
+ // call the base functions
+ if (x->setUp)
+ {
+ val = x;
+ args [0] = &val;
+ mono_runtime_invoke (x->setUp, x->obj, args, NULL);
+ post("SetUp() invoked");
+
+ } else
+ {
+ error("clr: the provided assembly is not valid! the SetUp function is missing");
+ }
+
+
+}
+
+/*
+// call the method
+static void clr_bang(t_clr *x) {
+
+ gpointer args [2];
+ int val;
+ MonoObject *result;
+
+ val = x->n;
+ args [0] = &val;
+
+ if (x->method)
+ {
+ result = mono_runtime_invoke (x->method, x->obj, args, NULL);
+ val = *(int*)mono_object_unbox (result);
+ x->n = val;
+ // outlet_float(x->l_out, (float) x->n);
+ }
+
+
+}
+*/
+
+// finds a method from its name
+void findMonoMethod( MonoClass *klass, char *function_name, MonoMethod **met)
+{
+ int trovato;
+ MonoMethod *m = NULL;
+ gpointer iter;
+ iter = NULL;
+ while (m = mono_class_get_methods (klass, &iter))
+ {
+ if (strcmp (mono_method_get_name (m), function_name) == 0)
+ {
+ *met = m;
+//printf("%s trovata\n", function_name);
+ return;
+ }
+ }
+}
+
+void clr_free(t_clr *x)
+{
+ mono_clean(x);
+}
+
+// here i look for the selector and call the right mono method
+void clr_manage_list(t_clr *x, t_symbol *sl, int argc, t_atom *argv)
+{
+ gpointer args [2];
+ int valInt;
+ float valFloat;
+
+ int i;
+ // first i extract the first atom which should be a symbol
+ //post("clr_manage_list, got symbol = %s", sl->s_name);
+
+ for (i=0; i<MAX_SELECTORS; i++)
+ {
+ if (strcmp(x->selectors[i].sel, sl->s_name) == 0)
+ {
+ // I've found the selector!
+printf("selector %s, func %s\n", sl->s_name, x->selectors[i].sel);
+ if (x->selectors[i].func)
+ {
+ // ParametersType {None = 0, Float=1, Symbol=2, List=3};
+ switch (x->selectors[i].type)
+ {
+ case 0:
+ mono_runtime_invoke (x->selectors[i].func, x->obj, NULL, NULL);
+ break;
+ case 1:
+ {
+ gpointer args [1];
+ float val = atom_getfloat(argv);
+ args[0] = &val;
+ mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
+ break;
+ }
+ case 2:
+ {
+ gpointer args [1];
+ t_symbol *strsymbol;
+ MonoString *strmono;
+ strsymbol = atom_getsymbol(argv);
+ strmono = mono_string_new (x->domain, strsymbol->s_name);
+ args[0] = &strmono;
+ mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
+ // memory leak ?
+ break;
+ }
+ case 3:
+ {
+ gpointer args [1];
+ MonoString *strmono;
+ t_symbol *strsymbol;
+ char *str;
+ MonoArray * arystr;
+ int j;
+printf("preparo l'array\n");
+
+ arystr = mono_array_new (x->domain, mono_get_string_class (), argc);
+ for (j=0; j<argc; j++)
+ {
+ int * ftmp = malloc(sizeof(int));
+ *ftmp = j;
+ strsymbol = atom_getsymbol(argv+j);
+ MonoString *arg = mono_string_new (x->domain, strsymbol->s_name);
+ mono_array_set (arystr, MonoString *, j, arg);
+ // gpointer
+ //mono_array_set (arystr, gint32 , j, ftmp);
+
+
+ }
+ args[0] = arystr;
+
+ //args[0] = strings;
+printf("mando a mono\n");
+ mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
+printf("ho mandatao a mono\n");
+ break;
+ }
+ }
+
+ //result = mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
+ //val = *(int*)mono_object_unbox (result);
+ //x->n = val;
+ return;
+ }
+ }
+ if (x->selectors[i].func == 0)
+ i = MAX_SELECTORS;
+ }
+
+ error("clr: selector not recognized");
+
+}
+
+// this function is called by mono when it wants to register a selector callback
+void registerMonoMethod(void *x1, MonoString *selectorString, MonoString *methodString, int type)
+{
+
+ char *selCstring, *metCstring;
+ MonoMethod *met;
+ t_clr *x;
+ int this_selector, i;
+ //int ret;
+
+
+ selCstring = mono_string_to_utf8 (selectorString);
+ metCstring = mono_string_to_utf8 (methodString);
+
+ x = (t_clr *)x1;
+
+ //ret = 0;
+ met = 0;
+ findMonoMethod( x->klass, metCstring, &met);
+
+ if (!met)
+ {
+ error("method not found!");
+ return;
+ }
+
+ post("registerMonoMethod: associating %s to %s", selCstring, metCstring);
+
+ this_selector = MAX_SELECTORS;
+ for (i = 0; i < MAX_SELECTORS; i++)
+ {
+ if (x->selectors[i].func == 0)
+ {
+ // i found the first empty space
+ this_selector = i;
+ i = MAX_SELECTORS;
+ }
+
+ }
+ if (this_selector == MAX_SELECTORS)
+ {
+ error("not enough space for selectors! MAX_SELECTORS = %i", MAX_SELECTORS);
+ return;
+ }
+
+ x->selectors[this_selector].sel = selCstring;
+ x->selectors[this_selector].func = met;
+ x->selectors[this_selector].type = type;
+
+ class_addmethod(clr_class, (t_method)clr_manage_list, gensym(selCstring), A_GIMME, 0);
+
+
+}
+
+// this function is called by mono when it wants to create a new inlet
+void createInlet(void *x1, MonoString *selectorString, int type)
+{
+ // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5};
+ char *selCstring;
+ char typeString[256];
+ t_clr *x;
+
+ selCstring = mono_string_to_utf8 (selectorString);
+ x = (t_clr *)x1;
+
+ switch (type)
+ {
+ case 1:
+ sprintf(typeString, "float");
+ break;
+ case 2:
+ sprintf(typeString, "symbol");
+ break;
+ case 3:
+ sprintf(typeString, "list");
+ break;
+ case 4:
+ sprintf(typeString, "bang");
+ break;
+ default:
+ sprintf(typeString, "");
+ break;
+ }
+ // create the inlet
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym(typeString), gensym(selCstring));
+}
+
+// this function is called by mono when it wants to create a new outlet
+void createOutlet(void *x1, int type)
+{
+ t_clr *x;
+ int i = 0;
+ char typeString[256];
+ x = (t_clr *)x1;
+
+ // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5};
+ switch (type)
+ {
+ case 1:
+ sprintf(typeString, "float");
+ break;
+ case 2:
+ sprintf(typeString, "symbol");
+ break;
+ case 3:
+ sprintf(typeString, "list");
+ break;
+ case 4:
+ sprintf(typeString, "bang");
+ break;
+ default:
+ sprintf(typeString, "");
+ break;
+ }
+
+ while (i < MAX_OUTLETS)
+ {
+ if (x->outlets[i].outlet_pointer == 0)
+ {
+ // empty space found!
+ x->outlets[i].outlet_pointer = outlet_new(&x->x_obj, gensym(typeString));
+ return;
+ }
+ i++;
+ }
+ error("the maximum number of outlets has been reached (%i)", MAX_OUTLETS);
+
+}
+
+// out to outlet
+void out2outlet(void *x1, int outlet, int type, unsigned char *val /* TODO */)
+{
+ t_clr *x;
+ x = (t_clr *)x1;
+ t_atom *lista;
+
+ if ((outlet>MAX_OUTLETS) || (outlet<0))
+ {
+ error("outlet number out of range, max is %i", MAX_OUTLETS);
+ return;
+ }
+ if (x->outlets[outlet].outlet_pointer == 0)
+ {
+ error("outlet %i not registered", outlet);
+ return;
+ }
+printf("ricevuto %i %i\n", val[0], val[1]);
+if (val[0]==0x01)
+ printf("val[0]==0x00");
+
+ lista = (t_atom *) malloc(sizeof(t_atom) * 2);
+ SETFLOAT(lista, (float) val[0]);
+ SETFLOAT(lista+1, (float) val[1]);
+ outlet_anything(x->outlets[outlet].outlet_pointer,
+ gensym("list") ,
+ 2,
+ lista);
+ free(lista);
+}
+
+// this function is called by mono when it wants post messages to pd
+void post2pd(MonoString *mesString)
+{
+
+ char *mesCstring;
+ mesCstring = mono_string_to_utf8 (mesString);
+ post(mesCstring);
+
+}
+
+// this function is called by mono when it wants to post errors to pd
+void error2pd(MonoString *mesString)
+{
+
+ char *mesCstring;
+ mesCstring = mono_string_to_utf8 (mesString);
+ error(mesCstring);
+}
+/*
+//void ext_class_addbang(const char *funcName)
+void ext_class_addbang(t_method funcName)
+{
+// class_addbang(clr_class, (t_method)clr_bang);
+ class_addbang(clr_class, funcName);
+}*/
+
+void *clr_new(t_symbol *s, int argc, t_atom *argv)
+{
+
+ int i;
+ time_t a;
+ t_clr *x = (t_clr *)pd_new(clr_class);
+// x->l_out = outlet_new(&x->x_obj, &s_list);
+// x->l_out = outlet_new(&x->x_obj, gensym("float"));
+
+
+
+ x->n = 0;
+ // load mono, init the needed vars
+ mono_load(x);
+
+ return (x);
+}
+
+void clr_setup(void)
+{
+ clr_class = class_new(gensym("clr"), (t_newmethod)clr_new,
+ (t_method)clr_free, sizeof(t_clr), CLASS_DEFAULT, A_GIMME, 0);
+ //class_addbang(clr_class, (t_method)clr_bang);
+// ext_class_addbang((t_method) clr_bang);
+
+ class_addlist(clr_class, (t_method)clr_manage_list);
+
+}
diff --git a/makefile b/makefile
new file mode 100755
index 0000000..5ec27fe
--- /dev/null
+++ b/makefile
@@ -0,0 +1,32 @@
+current: cygwin
+
+clean: ; rm -f *.dll *.o
+
+
+cygwin: clr.dll
+
+.SUFFIXES: .dll
+
+
+# where are the PD header files?
+# leave it blank if it is a system directory (like /usr/local/include),
+# since gcc 3.2 complains about it
+PDPATH=/home/Davide
+
+LINUXCFLAGS = -DPD -O2 -mno-cygwin
+#LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \
+# -Wall -W -Wshadow -Wstrict-prototypes -Werror \
+# -Wno-unused -Wno-parentheses -Wno-switch
+
+LINUXINCLUDE = -I../../src -I$PDPATH
+
+MONOSRC = -ID:/Davide/cygwin/tmp/build_deps/include -ID:/Davide/cygwin/tmp/build_deps/include/glib-2.0 -ID:/Davide/cygwin/tmp/build_deps/lib/glib-2.0/include -ID:/Davide/cygwin/home/Davide/mono/include
+MONOLIB = -LD:/Davide/cygwin/tmp/build_deps/lib -LD:/Davide/cygwin/home/Davide/mono/lib -lmono -lm -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv
+
+.c.dll:
+# gcc $(LINUXCFLAGS) $(LINUXINCLUDE) `pkg-config --cflags --libs mono` -lm -ID:/Davide/cygwin/home/Davide/mono/include -LD:/Davide/cygwin/home/Davide/mono/lib $*.c
+ gcc $(LINUXCFLAGS) $(LINUXINCLUDE) $(MONOSRC) -o $*.o -c $*.c
+ gcc -export_dynamic -shared -mno-cygwin $(MONOLIB) -o $*.dll $*.o -lm pd.dll libmono.dll.a
+# ld -export_dynamic $(MONOLIB) -o $*.dll $*.o -lm pd.dll
+# strip --strip-unneeded $*.pd_linux
+# rm $*.o
diff --git a/makefile.darwin b/makefile.darwin
new file mode 100755
index 0000000..54a8a01
--- /dev/null
+++ b/makefile.darwin
@@ -0,0 +1,40 @@
+current: pd_darwin
+
+clean: ; rm -f *.pd_linux *.o *.pd_darwin
+
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: clr.pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+
+# where are the PD header files?
+# leave it blank if it is a system directory (like /usr/local/include),
+# since gcc 3.2 complains about it
+#PDPATH=/usr/local/src/pd/src
+PDPATH=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/src/
+
+# where is the PD executable?
+#PD=/usr/local/bin/pd
+PD=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/bin/pd
+#PD=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/src/
+
+CFLAGS=`pkg-config --cflags mono`
+#LDFLAGS=`pkg-config --libs mono`
+LDFLAGS=-L/sw/lib -L/sw/lib/pkgconfig/../../lib -lmono -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv
+
+DARWININCLUDE = -I../../src -I$(PDPATH)
+
+#DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+# -Wno-unused -Wno-parentheses -Wno-switch
+
+DARWINCFLAGS = -DPD -O2
+
+.c.pd_darwin:
+ cc $(DARWINCFLAGS) $(DARWININCLUDE) $(CFLAGS) -o $*.o -c $*.c
+# cc -bundle -bundle_loader $(PD) -multiply_defined supress $(LDFLAGS) -o $*.pd_darwin *.o
+ cc -bundle -bundle_loader $(PD) -flat_namespace $(LDFLAGS) -o $*.pd_darwin *.o
+# cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $(FANNLIB) *.o
+# rm -f $*.o
diff --git a/test-clr.pd b/test-clr.pd
new file mode 100755
index 0000000..91f24dd
--- /dev/null
+++ b/test-clr.pd
@@ -0,0 +1,38 @@
+#N canvas 0 0 726 474 12;
+#X obj 97 383 clr;
+#X obj 105 80 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X msg 239 110 1 2 3;
+#X msg 238 136 sel3 a b c;
+#X msg 236 176 selFloat 0.5;
+#X msg 247 221 selString ciao;
+#X msg 247 263 selList 1 2 3;
+#X msg 344 161 selFloat \$1;
+#X obj 344 121 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X floatatom 360 142 5 0 0 0 - - -;
+#X msg 242 59 sel1;
+#X msg 240 87 sel2;
+#X obj 428 260 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144
+-1 -1 0 1;
+#X text 424 239 2nd inlet mapped to selFloat;
+#X obj 71 429 print a;
+#X msg 239 297 selStringList abba baab caac dede;
+#X msg 248 360 selFloatList 1 2 3 4;
+#X msg 240 319 selStringList ego filose;
+#X connect 0 0 14 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 7 0;
+#X connect 8 0 9 0;
+#X connect 10 0 0 0;
+#X connect 11 0 0 0;
+#X connect 12 0 0 1;
+#X connect 15 0 0 0;
+#X connect 16 0 0 0;
+#X connect 17 0 0 0;