Update of /cvsroot/pure-data/externals/clr
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20032
Added Files:
clr.c makefile makefile.darwin test-clr.pd
Log Message:
checking in the external
--- NEW FILE: makefile ---
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
--- NEW FILE: test-clr.pd ---
#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;
--- NEW FILE: makefile.darwin ---
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
--- NEW FILE: clr.c ---
/*
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);
}