From 0028a036b1823c364b8a3984bd6b836a15ab7b6f Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Wed, 8 Mar 2006 16:48:29 +0000 Subject: added inlet and outlet functions added send functions practically ready to work with! svn path=/trunk/externals/clr/; revision=4658 --- Counter/Counter.cs | 22 ++++++- PureData/PureData.cs | 115 +++++++++++++++++++++++++++++++++++ clr.cpp | 169 +++++++++++++++++++++++++++++++++++++++++++++++---- test-clr.pd | 27 ++++++-- 4 files changed, 314 insertions(+), 19 deletions(-) diff --git a/Counter/Counter.cs b/Counter/Counter.cs index 9cb4801..b59945e 100755 --- a/Counter/Counter.cs +++ b/Counter/Counter.cs @@ -8,6 +8,8 @@ public class Counter: { PureData.Atom[] args; + float farg; + public Counter(PureData.AtomList args) { Post("Count.ctor "+args.ToString()); @@ -15,8 +17,9 @@ public class Counter: // that's the way to store args (don't just copy an AtomList instance!!) this.args = (PureData.Atom[])args; -// pd.AddInlet(x, "init", ParametersType.Float); -// pd.AddOutlet(x, ParametersType.Float); + AddInlet(s_list,new PureData.Symbol("list2")); + AddInlet(ref farg); + AddOutletBang(); } // this function MUST exist @@ -27,6 +30,7 @@ public class Counter: Add(new MethodSymbol(obj.MySymbol)); Add(new MethodList(obj.MyList)); Add("set",new MethodList(obj.MySet)); + Add("send",new MethodList(obj.MySend)); Add(new MethodAnything(obj.MyAnything)); Post("Count.Main"); @@ -34,32 +38,44 @@ public class Counter: protected virtual void MyBang() { - Post("Count-BANG"); + Post("Count-BANG "+farg.ToString()); + Outlet(0); } protected virtual void MyFloat(float f) { Post("Count-FLOAT "+f.ToString()); + Outlet(0,f); } protected virtual void MySymbol(PureData.Symbol s) { Post("Count-SYMBOL "+s.ToString()); + Outlet(0,s); } protected virtual void MyList(PureData.AtomList l) { Post("Count-LIST "+l.ToString()); + Outlet(0,l); } protected virtual void MySet(PureData.AtomList l) { Post("Count-SET "+l.ToString()); + Outlet(0,new PureData.Symbol("set"),l); + } + + protected virtual void MySend(PureData.AtomList l) + { + Send(new PureData.Symbol("receiver"),l); + Send(new PureData.Symbol("receiver2"),(PureData.Atom[])l); } protected virtual void MyAnything(PureData.Symbol s,PureData.AtomList l) { Post("Count-("+s.ToString()+") "+l.ToString()); + Outlet(0,s,l); } /* public void SendOut() diff --git a/PureData/PureData.cs b/PureData/PureData.cs index 6e55693..ebbc319 100644 --- a/PureData/PureData.cs +++ b/PureData/PureData.cs @@ -12,6 +12,57 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static string SymEval(void *sym); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddInlet(void *obj,Symbol sel,Symbol to_sel); + + // map to data member + // \NOTE don't know if this is really safe since f must stay at its place (but it should, no?) + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddInlet(void *obj,ref float f); + + // map to data member + // \NOTE don't know if this is really safe since s must stay at its place (but it should, no?) + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddInlet(void *obj,ref Symbol s); + + // map to data member + // \NOTE don't know if this is really safe since s must stay at its place (but it should, no?) +// [MethodImplAttribute (MethodImplOptions.InternalCall)] +// internal extern static void AddInlet(void *obj,ref Pointer f); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddInlet(void *obj); // create proxy inlet + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddOutlet(void *obj,Symbol type); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,float f); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,Symbol s); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,Pointer p); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,Atom a); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,Symbol s,AtomList l); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Outlet(void *obj,int n,Symbol s,Atom[] l); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Bind(void *obj,Symbol dst); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void Unbind(void *obj,Symbol dst); } // This is the base class for a PD/CLR external @@ -22,6 +73,16 @@ namespace PureData // -------------------------------------------------------------------------- + protected readonly static Symbol s__ = new Symbol(""); + protected readonly static Symbol s_bang = new Symbol("bang"); + protected readonly static Symbol s_float = new Symbol("float"); + protected readonly static Symbol s_symbol = new Symbol("symbol"); + protected readonly static Symbol s_pointer = new Symbol("pointer"); + protected readonly static Symbol s_list = new Symbol("list"); + protected readonly static Symbol s_anything = new Symbol("anything"); + + // -------------------------------------------------------------------------- + [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Post(string message); @@ -65,5 +126,59 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Add(MethodAnything m); + + // -------------------------------------------------------------------------- + + protected void AddInlet(Symbol sel,Symbol to_sel) { Internal.AddInlet(ptr,sel,to_sel); } + protected void AddInlet(ref float f) { Internal.AddInlet(ptr,ref f); } + protected void AddInlet(ref Symbol s) { Internal.AddInlet(ptr,ref s); } +// protected void AddInlet(ref Pointer p) { Internal.AddInlet(ptr,ref p); } // map to data member + protected void AddInlet() { Internal.AddInlet(ptr); } // create proxy inlet + + // -------------------------------------------------------------------------- + + protected void AddOutlet(Symbol type) { Internal.AddOutlet(ptr,type); } + + protected void AddOutletBang() { AddOutlet(s_bang); } + protected void AddOutletFloat() { AddOutlet(s_float); } + protected void AddOutletSymbol() { AddOutlet(s_symbol); } + protected void AddOutletPointer() { AddOutlet(s_pointer); } + protected void AddOutletList() { AddOutlet(s_list); } + protected void AddOutletAnything() { AddOutlet(s_anything); } + + // -------------------------------------------------------------------------- + + protected void Outlet(int n) { Internal.Outlet(ptr,n); } + protected void Outlet(int n,float f) { Internal.Outlet(ptr,n,f); } + protected void Outlet(int n,Symbol s) { Internal.Outlet(ptr,n,s); } + protected void Outlet(int n,Pointer p) { Internal.Outlet(ptr,n,p); } + protected void Outlet(int n,Atom a) { Internal.Outlet(ptr,n,a); } + protected void Outlet(int n,AtomList l) { Internal.Outlet(ptr,n,s_list,l); } + protected void Outlet(int n,Atom[] l) { Internal.Outlet(ptr,n,s_list,l); } + protected void Outlet(int n,Symbol s,AtomList l) { Internal.Outlet(ptr,n,s,l); } + protected void Outlet(int n,Symbol s,Atom[] l) { Internal.Outlet(ptr,n,s,l); } + + // -------------------------------------------------------------------------- + + // bind to symbol + protected void Bind(Symbol sym) { Internal.Bind(ptr,sym); } + protected void Unbind(Symbol sym) { Internal.Unbind(ptr,sym); } + + // send to receiver symbol + [MethodImplAttribute (MethodImplOptions.InternalCall)] + protected extern static void Send(Symbol sym,Atom a); + + protected static void Send(Symbol sym) { Send(sym,s_bang,null); } + protected static void Send(Symbol sym,float f) { Send(sym,new Atom(f)); } + protected static void Send(Symbol sym,Symbol s) { Send(sym,new Atom(s)); } + protected static void Send(Symbol sym,Pointer p) { Send(sym,new Atom(p)); } + protected static void Send(Symbol sym,AtomList l) { Send(sym,s_list,l); } + protected static void Send(Symbol sym,Atom[] l) { Send(sym,s_list,l); } + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + protected extern static void Send(Symbol sym,Symbol s,AtomList l); + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + protected extern static void Send(Symbol sym,Symbol s,Atom[] l); } } diff --git a/clr.cpp b/clr.cpp index e8aed95..7a5af73 100755 --- a/clr.cpp +++ b/clr.cpp @@ -26,6 +26,7 @@ extern "C" { #endif #include +#include #define CORELIB "PureData" #define DLLEXT "dll" @@ -39,7 +40,6 @@ static MonoMethodDesc *clr_desc_tostring,*clr_desc_ctor; static MonoMethod *clr_meth_invoke; static MonoProperty *clr_prop_method; - struct AtomList { int argc; @@ -78,8 +78,8 @@ struct t_clr_class { t_class *pd_class; MonoClass *mono_class; - MonoClassField *mono_obj_field; MonoMethod *mono_ctor; + MonoClassField *obj_field; // ptr field in PureData.External t_symbol *name; Delegate method_bang,method_float,method_symbol,method_pointer,method_list,method_anything; ClrMethodMap *methods; // explicit method selectors @@ -89,6 +89,8 @@ typedef std::map ClrMap; // this holds the class name to class structure association static ClrMap clr_map; +typedef std::vector OutletArr; + // this is the class to be setup (while we are in the CLR static Main method) static t_clr_class *clr_setup_class = NULL; @@ -98,6 +100,7 @@ struct t_clr t_object pd_obj; // myself t_clr_class *clr_clss; // pointer to our class structure MonoObject *mono_obj; // the mono class instance + OutletArr *outlets; }; @@ -176,7 +179,6 @@ static void clr_method_pointer(t_clr *x,t_gpointer *p) if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } - static void clr_method_list(t_clr *x,t_symbol *l, int argc, t_atom *argv) { assert(x && x->clr_clss); @@ -330,6 +332,127 @@ static void PD_AddAnything(MonoObject *method) } +static void PD_AddInlet(t_clr *obj,t_symbol *sel,t_symbol *to_sel) +{ + assert(obj); + t_inlet *in = inlet_new(&obj->pd_obj,&obj->pd_obj.ob_pd,sel,to_sel); + assert(in); +} + +static void PD_AddInletFloat(t_clr *obj,float *f) +{ + assert(obj); + t_inlet *in = floatinlet_new(&obj->pd_obj,f); + assert(in); +} + +static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) +{ + assert(obj); + t_inlet *in = symbolinlet_new(&obj->pd_obj,s); + assert(in); +} + +/* +static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) +{ + assert(obj); + t_inlet *in = pointerinlet_new(&obj->pd_obj,p); + assert(in); +} +*/ + +static void PD_AddInletProxy(t_clr *obj) +{ + assert(obj); + // TODO implement +} + +static void PD_AddOutlet(t_clr *obj,t_symbol *type) +{ + assert(obj); + t_outlet *out = outlet_new(&obj->pd_obj,type); + assert(out); + if(!obj->outlets) obj->outlets = new OutletArr; + obj->outlets->push_back(out); +} + +static void PD_OutletBang(t_clr *obj,int n) +{ + assert(obj); + assert(obj->outlets); + outlet_bang((*obj->outlets)[n]); +} + +static void PD_OutletFloat(t_clr *obj,int n,float f) +{ + assert(obj); + assert(obj->outlets); + outlet_float((*obj->outlets)[n],f); +} + +static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) +{ + assert(obj); + assert(obj->outlets); + outlet_symbol((*obj->outlets)[n],s); +} + +static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) +{ + assert(obj); + assert(obj->outlets); + outlet_pointer((*obj->outlets)[n],p); +} + +static void PD_OutletAtom(t_clr *obj,int n,t_atom l) +{ + assert(obj); + assert(obj->outlets); + t_outlet *out = (*obj->outlets)[n]; + switch(l.a_type) { + case A_FLOAT: outlet_float(out,l.a_w.w_float); break; + case A_SYMBOL: outlet_symbol(out,l.a_w.w_symbol); break; + case A_POINTER: outlet_pointer(out,l.a_w.w_gpointer); break; + default: + error("CLR - internal error in file " __FILE__ ", line %i",__LINE__); + } +} + +static void PD_OutletAnything(t_clr *obj,int n,t_symbol *s,AtomList l) +{ + assert(obj); + assert(obj->outlets); + outlet_anything((*obj->outlets)[n],s,l.argc,l.argv); +} + +static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) +{ + assert(obj); + assert(obj->outlets); +// assert(mono_object_get_class(&l->obj) == clr_atom); + outlet_anything((*obj->outlets)[n],s,mono_array_length(l),mono_array_addr(l,t_atom,0)); +} + +static void PD_SendAtom(t_symbol *dst,t_atom a) +{ + void *cl = dst->s_thing; + if(cl) pd_forwardmess((t_class **)cl,1,&a); +} + +static void PD_SendAnything(t_symbol *dst,t_symbol *s,AtomList l) +{ + void *cl = dst->s_thing; + if(cl) pd_typedmess((t_class **)cl,s,l.argc,l.argv); +} + +static void PD_SendAnything2(t_symbol *dst,t_symbol *s,MonoArray *l) +{ + void *cl = dst->s_thing; +// assert(mono_object_get_class(&l->obj) == clr_atom); + if(cl) pd_typedmess((t_class **)cl,s,mono_array_length(l),mono_array_addr(l,t_atom,0)); +} + void *clr_new(t_symbol *classname, int argc, t_atom *argv) { // find class name in map @@ -355,7 +478,9 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) x->clr_clss->name = classname; // store our object pointer in External::ptr member - mono_field_set_value(x->mono_obj,clss->mono_obj_field,&x); + mono_field_set_value(x->mono_obj,clss->obj_field,x); + + x->outlets = NULL; // ok, we have an object - look for constructor if(clss->mono_ctor) { @@ -381,6 +506,7 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) void clr_free(t_clr *x) { + if(x->outlets) delete x->outlets; } static int classloader(char *dirname, char *classname) @@ -402,10 +528,9 @@ static int classloader(char *dirname, char *classname) close(fd); clr_class = (t_clr_class *)getbytes(sizeof(t_clr_class)); + // set all struct members to 0 memset(clr_class,0,sizeof(*clr_class)); -// clr_class->methods = NULL; - // try to load assembly strcat(dirbuf,"/"); strcat(dirbuf,classname); @@ -428,13 +553,13 @@ static int classloader(char *dirname, char *classname) goto bailout; } - clr_class->mono_obj_field = mono_class_get_field_from_name(clr_class->mono_class,"ptr"); - assert(clr_class->mono_obj_field); - // make new class (with classname) classsym = gensym(classname); clr_class->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_clr), CLASS_DEFAULT, A_GIMME, 0); + clr_class->obj_field = mono_class_get_field_from_name(clr_class->mono_class,"ptr"); + assert(clr_class->obj_field); + // find static Main method MonoMethodDesc *clr_desc_main = mono_method_desc_new("::Setup",FALSE); @@ -449,8 +574,7 @@ static int classloader(char *dirname, char *classname) } // store NULL in External::ptr member - void *x = NULL; - mono_field_set_value(obj,clr_class->mono_obj_field,&x); + mono_field_set_value(obj,clr_class->obj_field,NULL); // set current class clr_setup_class = clr_class; @@ -570,6 +694,29 @@ void clr_setup(void) mono_add_internal_call("PureData.External::Add(PureData.Symbol,PureData.External/MethodList)", (const void *)PD_AddSelector); mono_add_internal_call("PureData.External::Add(PureData.External/MethodAnything)", (const void *)PD_AddAnything); + mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInlet); + mono_add_internal_call("PureData.Internal::AddInlet(void*,single&)", (const void *)PD_AddInletFloat); + mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol&)", (const void *)PD_AddInletSymbol); +// mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Pointer&)", (const void *)PD_AddInletPointer); + mono_add_internal_call("PureData.Internal::AddInlet(void*)", (const void *)PD_AddInletProxy); + + mono_add_internal_call("PureData.Internal::AddOutlet(void*,PureData.Symbol)", (const void *)PD_AddOutlet); + + mono_add_internal_call("PureData.Internal::Outlet(void*,int)", (const void *)PD_OutletBang); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,single)", (const void *)PD_OutletFloat); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol)", (const void *)PD_OutletSymbol); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Pointer)", (const void *)PD_OutletPointer); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Atom)", (const void *)PD_OutletAtom); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.AtomList)", (const void *)PD_OutletAnything); + mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.Atom[])", (const void *)PD_OutletAnything2); + +// mono_add_internal_call("PureData.Internal::Bind(void*,PureData.Symbol)", (const void *)PD_Bind); +// mono_add_internal_call("PureData.Internal::Unbind(void*,PureData.Symbol)", (const void *)PD_Unbind); + + mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Atom)", (const void *)PD_SendAtom); + mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.AtomList)", (const void *)PD_SendAnything); + mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.Atom[])", (const void *)PD_SendAnything2); + // load important classes clr_symbol = mono_class_from_name(image,"PureData","Symbol"); assert(clr_symbol); diff --git a/test-clr.pd b/test-clr.pd index fc1e7b7..75721bc 100755 --- a/test-clr.pd +++ b/test-clr.pd @@ -1,8 +1,8 @@ -#N canvas 603 10 798 320 12; +#N canvas 617 153 818 585 12; #X floatatom 125 51 5 0 0 0 - - -; #X symbolatom 320 81 10 0 0 0 - - -; #X msg 536 45 msg one 2 three; -#X obj 240 276 Counter a b 5; +#X obj 151 443 Counter a b 5; #X obj 22 24 loadbang; #X floatatom 213 26 5 0 0 0 - - -; #X msg 213 52 1 \$1 3; @@ -11,12 +11,23 @@ #X obj 21 54 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X msg 535 82 set 1 7 8; -#X msg 541 167 list; -#X msg 540 196 list 1; -#X msg 541 225 list abc; +#X msg 533 135 list; +#X msg 532 164 list 1; +#X msg 533 193 list abc; +#X msg 528 251 list s e c o n d; +#X obj 152 495 print OUT; +#X floatatom 530 321 5 0 0 0 - - -; +#X floatatom 229 112 5 0 0 0 - - -; +#X msg 228 136 send \$1 b c; +#X obj 407 497 print RECV1; +#X obj 406 463 r receiver; +#X obj 554 465 r receiver2; +#X obj 555 499 print RECV2; +#X text 585 318 bang to see; #X connect 0 0 3 0; #X connect 1 0 3 0; #X connect 2 0 3 0; +#X connect 3 0 15 0; #X connect 4 0 9 0; #X connect 5 0 6 0; #X connect 6 0 3 0; @@ -27,3 +38,9 @@ #X connect 11 0 3 0; #X connect 12 0 3 0; #X connect 13 0 3 0; +#X connect 14 0 3 1; +#X connect 16 0 3 2; +#X connect 17 0 18 0; +#X connect 18 0 3 0; +#X connect 20 0 19 0; +#X connect 21 0 22 0; -- cgit v1.2.1