From 562dcc336797951b2a8707413aa44177484c9f2a Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Sat, 28 Dec 2002 04:37:42 +0000 Subject: "" svn path=/trunk/; revision=309 --- externals/grill/flext/source/flext.cpp | 670 ++------------------------------- 1 file changed, 34 insertions(+), 636 deletions(-) (limited to 'externals/grill/flext/source/flext.cpp') diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp index f74d11c6..5ffaaae4 100644 --- a/externals/grill/flext/source/flext.cpp +++ b/externals/grill/flext/source/flext.cpp @@ -14,104 +14,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "flext.h" #include "flinternal.h" -#include -#include - - -// === proxy class for flext_base ============================ - -#if FLEXT_SYS == FLEXT_SYS_PD - -static t_class *px_class; - -struct flext_base::px_object // no virtual table! -{ - t_object obj; // MUST reside at memory offset 0 - flext_base *base; - int index; - - void init(flext_base *b,int ix) { base = b; index = ix; } - static void px_method(px_object *c,const t_symbol *s,int argc,t_atom *argv); -}; - - -void flext_base::px_object::px_method(px_object *obj,const t_symbol *s,int argc,t_atom *argv) -{ - obj->base->m_methodmain(obj->index,s,argc,argv); -} - -void flext_base::cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv) -{ - thisObject(c)->m_methodmain(0,s,argc,argv); -} - -#define DEF_IN_FT(IX) \ -void flext_base::cb_px_ft ## IX(t_class *c,float v) { \ - t_atom atom; SETFLOAT(&atom,v); \ - thisObject(c)->m_methodmain(IX,&s_float,1,&atom); \ -} - -#define ADD_IN_FT(IX) \ -add_method1(c,cb_px_ft ## IX,"ft" #IX,A_FLOAT) - -#elif FLEXT_SYS == FLEXT_SYS_MAX - -void flext_base::cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv) -{ - // check if inlet allows anything (or list) - - flext_base *o = thisObject(c); - int ci = ((flext_hdr *)o->x_obj)->curinlet; - - o->m_methodmain(ci,s,argc,argv); -} - -void flext_base::cb_px_int(t_class *c,int v) -{ - // check if inlet allows int type - t_atom atom; - SetInt(atom,v); - cb_px_anything(c,sym_int,1,&atom); -} - -void flext_base::cb_px_float(t_class *c,float v) -{ - // check if inlet allows float type - t_atom atom; - SetFloat(atom,v); - cb_px_anything(c,sym_float,1,&atom); -} - -void flext_base::cb_px_bang(t_class *c) -{ - // check if inlet allows bang - cb_px_anything(c,sym_bang,0,NULL); -} - - -#define DEF_IN_FT(IX) \ -void flext_base::cb_px_in ## IX(t_class *c,int v) { long &ci = ((flext_hdr *)thisObject(c)->x_obj)->curinlet; ci = IX; cb_px_int(c,v); ci = 0; } \ -void flext_base::cb_px_ft ## IX(t_class *c,float v) { long &ci = ((flext_hdr *)thisObject(c)->x_obj)->curinlet; ci = IX; cb_px_float(c,v); ci = 0; } - -#define ADD_IN_FT(IX) \ -add_method1(c,cb_px_in ## IX,"in" #IX,A_INT); \ -add_method1(c,cb_px_ft ## IX,"ft" #IX,A_FLOAT) - -#else -#error // Other system -#endif - - -DEF_IN_FT(1) -DEF_IN_FT(2) -DEF_IN_FT(3) -DEF_IN_FT(4) -DEF_IN_FT(5) -DEF_IN_FT(6) -DEF_IN_FT(7) -DEF_IN_FT(8) -DEF_IN_FT(9) - // === flext_base ============================================ @@ -125,15 +27,15 @@ flext_base::flext_base(): insigs(0),outsigs(0), outlets(NULL),outattr(NULL), distmsgs(false), - methhead(NULL),attrhead(NULL),attrcnt(0), + methhead(new itemarr),attrhead(new itemarr), //attrcnt(0), + clmethhead(ClMeths(thisClass())),clattrhead(ClAttrs(thisClass())), inlets(NULL) { LOG1("%s - flext logging is on",thisName()); + // message queue ticker qhead = qtail = NULL; qclk = (t_qelem *)(qelem_new(this,(t_method)QTick)); - - AddMethod(0,"getattributes",(methfun)cb_ListAttrib); } flext_base::~flext_base() @@ -142,10 +44,15 @@ flext_base::~flext_base() StopThreads(); #endif - // send remaining pending messages + // send remaining pending messages and destroy queue ticker while(qhead) QTick(this); qelem_free((t_qelem *)qclk); + // delete message lists + if(methhead) delete methhead; + if(attrhead) delete attrhead; + + // destroy inlets and outlets and their proxy objects if(inlist) delete inlist; if(outlist) delete outlist; if(outlets) delete[] outlets; @@ -153,6 +60,7 @@ flext_base::~flext_base() if(inlets) { for(int ix = 0; ix < incnt; ++ix) if(inlets[ix]) { + // release proxy object #if FLEXT_SYS == FLEXT_SYS_PD pd_free(&inlets[ix]->obj.ob_pd); #elif FLEXT_SYS == FLEXT_SYS_MAX @@ -161,258 +69,44 @@ flext_base::~flext_base() } delete[] inlets; } - + #if FLEXT_SYS == FLEXT_SYS_MAX // if(insigs) dsp_free(thisHdr()); if(insigs) dsp_freebox(thisHdr()); #endif - - if(methhead) delete methhead; - if(attrhead) delete attrhead; } -/*! This virtual function is created after the object has been created, that is, - after the constructor has been processed. It creates the inlets and outlets. +/*! This virtual function is called after the object has been created, that is, + after the constructor has been processed. + It creates the inlets and outlets and the message and attribute lists. \note You can override it in your own class, but be sure to call it, \note otherwise no inlets/outlets will be created + \mote All inlet, outlets, method and attribute declarations must be made before a call to Init! \remark Creation of inlets/outlets can't be done upon declaration, as Max/MSP needs creation \remark in reverse. */ bool flext_base::Init() { - bool ok = true; - - // ---------------------------------- - // create inlets - // ---------------------------------- - - incnt = insigs = 0; - - if(inlist) { - xlet *xi; - incnt = 0; - for(xi = inlist; xi; xi = xi->nxt) ++incnt; - xlet::type *list = new xlet::type[incnt]; - int i; - for(xi = inlist,i = 0; xi; xi = xi->nxt,++i) list[i] = xi->tp; - delete inlist; inlist = NULL; - - inlets = new px_object *[incnt]; - for(i = 0; i < incnt; ++i) inlets[i] = NULL; - - // type info is now in list array -#if FLEXT_SYS == FLEXT_SYS_PD - { - int cnt = 0; - - if(incnt >= 1) { - switch(list[0]) { - case xlet::tp_sig: - CLASS_MAINSIGNALIN(thisClass(),flext_hdr,defsig); - ++insigs; - break; - default: - // leftmost inlet is already there... - break; - } - ++cnt; - } - - for(int ix = 1; ix < incnt; ++ix,++cnt) { - switch(list[ix]) { - case xlet::tp_float: - case xlet::tp_int: { - char sym[] = "ft??"; - if(ix >= 10) { - if(compatibility) { - // Max allows max. 9 inlets - post("%s: Only 9 float/int inlets allowed in compatibility mode",thisName()); - ok = false; - } - else { - if(ix > 99) - post("%s: Inlet index > 99 not allowed for float/int inlets",thisName()); - sym[2] = '0'+ix/10,sym[3] = '0'+ix%10; - } - } - else - sym[2] = '0'+ix,sym[3] = 0; - if(ok) inlet_new(&x_obj->obj, &x_obj->obj.ob_pd, &s_float, gensym(sym)); - break; - } - case xlet::tp_sym: - (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages - inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, &s_symbol, &s_symbol); - break; - case xlet::tp_list: - (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages - inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, &s_list, &s_list); - break; - case xlet::tp_any: - (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages - inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, 0, 0); - break; - case xlet::tp_sig: - if(compatibility && list[ix-1] != xlet::tp_sig) { - post("%s: All signal inlets must be left-aligned in compatibility mode",thisName()); - ok = false; - } - else { - // pd doesn't seem to be able to handle signals and messages into the same inlet... - - inlet_new(&x_obj->obj, &x_obj->obj.ob_pd, &s_signal, &s_signal); - ++insigs; - } - break; - default: - error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)list[ix]); - ok = false; - } - } - - incnt = cnt; - } -#elif FLEXT_SYS == FLEXT_SYS_MAX - { - int ix,cnt; - // count leftmost signal inlets - while(insigs < incnt && list[insigs] == xlet::tp_sig) ++insigs; - - for(cnt = 0,ix = incnt-1; ix >= insigs; --ix,++cnt) { - if(ix == 0) { - if(list[ix] != xlet::tp_any) { - error("%s: Leftmost inlet must be of type signal or default",thisName()); - ok = false; - } - } - else { - switch(list[ix]) { - case xlet::tp_sig: - error("%s: All signal inlets must be at the left side",thisName()); - ok = false; - break; - case xlet::tp_float: - if(ix >= 10) { - post("%s: Only 9 float inlets possible",thisName()); - ok = false; - } - else - floatin(x_obj,ix); - break; - case xlet::tp_int: - if(ix >= 10) { - post("%s: Only 9 int inlets possible",thisName()); - ok = false; - } - else - intin(x_obj,ix); - break; - case xlet::tp_any: // non-leftmost - case xlet::tp_sym: - case xlet::tp_list: - inlets[ix] = (px_object *)proxy_new(x_obj,ix,&((flext_hdr *)x_obj)->curinlet); - break; - default: - error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)list[ix]); - ok = false; - } - } - } - - incnt = cnt; - - if(insigs) -// dsp_setup(thisHdr(),insigs); // signal inlets - dsp_setupbox(thisHdr(),insigs); // signal inlets - } -#else -#error -#endif + bool ok = flext_obj::Init(); - delete[] list; - } - -/* - if(outlets) { delete[] outlets; outlets = NULL; } -*/ - // ---------------------------------- - // create outlets - // ---------------------------------- + if(ok) ok = InitInlets() && InitOutlets(); - outcnt = outsigs = 0; - -#if FLEXT_SYS == FLEXT_SYS_MAX - // for Max/MSP the rightmost outlet has to be created first - if(procattr) - outattr = (outlet *)newout_anything(&x_obj->obj); -#endif - - if(outlist) { - xlet *xi; - - // count outlets - outcnt = 0; - for(xi = outlist; xi; xi = xi->nxt) ++outcnt; - - xlet::type *list = new xlet::type[outcnt]; - int i; - for(xi = outlist,i = 0; xi; xi = xi->nxt,++i) list[i] = xi->tp; - delete outlist; outlist = NULL; + if(ok) { + // initialize method lists + if(methhead) methhead->Finalize(); + if(clmethhead) clmethhead->Finalize(); - outlets = new outlet *[outcnt]; - - // type info is now in list array -#if FLEXT_SYS == FLEXT_SYS_PD - for(int ix = 0; ix < outcnt; ++ix) -#elif FLEXT_SYS == FLEXT_SYS_MAX - for(int ix = outcnt-1; ix >= 0; --ix) -#else -#error -#endif - { - switch(list[ix]) { - case xlet::tp_float: - outlets[ix] = (outlet *)newout_float(&x_obj->obj); - break; - case xlet::tp_int: - outlets[ix] = (outlet *)newout_flint(&x_obj->obj); - break; - case xlet::tp_sig: - outlets[ix] = (outlet *)newout_signal(&x_obj->obj); - ++outsigs; - break; - case xlet::tp_sym: - outlets[ix] = (outlet *)newout_symbol(&x_obj->obj); - break; - case xlet::tp_list: - outlets[ix] = (outlet *)newout_list(&x_obj->obj); - break; - case xlet::tp_any: - outlets[ix] = (outlet *)newout_anything(&x_obj->obj); - break; -#ifdef FLEXT_DEBUG - default: - ERRINTERNAL(); - ok = false; -#endif - } + if(procattr) { + // initialize attribute lists + if(attrhead) attrhead->Finalize(); + if(clattrhead) clattrhead->Finalize(); + + // initialize creation attributes + if(m_holdaargc && m_holdaargv) + ok = InitAttrib(m_holdaargc,m_holdaargv); } - - delete[] list; } - if(procattr) { -#if FLEXT_SYS == FLEXT_SYS_PD - // attribute dump outlet is the last one - outattr = (outlet *)newout_anything(&x_obj->obj); -#endif - - // initialize creation attributes - if(m_holdaargc && m_holdaargv) - ok = InitAttrib(m_holdaargc,m_holdaargv); - } - - return ok; } @@ -427,35 +121,13 @@ void flext_base::Setup(t_class *c) add_assist(c,cb_assist); #endif - // proxy for extra inlets -#if FLEXT_SYS == FLEXT_SYS_PD - add_anything(c,cb_px_anything); // for leftmost inlet - px_class = class_new(gensym("flext_base proxy"),NULL,NULL,sizeof(px_object),CLASS_PD|CLASS_NOINLET, A_NULL); - add_anything(px_class,px_object::px_method); // for other inlets -#elif FLEXT_SYS == FLEXT_SYS_MAX - add_bang(c,cb_px_bang); - add_method1(c,cb_px_int,"int",A_INT); - add_method1(c,cb_px_float,"float",A_FLOAT); - add_methodG(c,cb_px_anything,"list"); - add_anything(c,cb_px_anything); -#else -#error -#endif + if(process_attributes) + AddMethod(c,0,"getattributes",(methfun)cb_ListAttrib); - // setup non-leftmost ints and floats - ADD_IN_FT(1); - ADD_IN_FT(2); - ADD_IN_FT(3); - ADD_IN_FT(4); - ADD_IN_FT(5); - ADD_IN_FT(6); - ADD_IN_FT(7); - ADD_IN_FT(8); - ADD_IN_FT(9); + SetProxies(c); #ifdef FLEXT_THREADS thrid = GetThreadId(); - StartHelper(); #endif } @@ -473,282 +145,8 @@ void flext_base::m_help() post("%s (using flext " FLEXT_VERSTR ") - compiled on %s %s",thisName(),__DATE__,__TIME__); } -/*! \brief All the message processing - The messages of all the inlets go here and are promoted to the registered callback functions -*/ -bool flext_base::m_methodmain(int inlet,const t_symbol *s,int argc,const t_atom *argv) -{ - static bool trap = false; - bool ret = false; - - curtag = s; - - LOG3("methodmain inlet:%i args:%i symbol:%s",inlet,argc,s?s->s_name:""); - - for(const methitem *m = methhead; m && !ret; m = m->nxt) { - if(m->tag == s && (inlet == m->inlet || m->inlet < 0 )) { - // tag fits - LOG4("found method tag %s: inlet=%i, symbol=%s, argc=%i",m->tag->s_name,inlet,s->s_name,argc); - - if(m->argc == 1 && m->args[0] == a_list) { - ret = ((methfun_V)m->fun)(this,argc,const_cast(argv)); - } - else if(m->argc == 1 && m->args[0] == a_any) { - ret = ((methfun_A)m->fun)(this,s,argc,const_cast(argv)); - } - else if(argc == m->argc) { - int ix; - t_any aargs[FLEXT_MAXMETHARGS]; - bool ok = true; - for(ix = 0; ix < argc && ok; ++ix) { - switch(m->args[ix]) { - case a_float: { - if(IsFloat(argv[ix])) aargs[ix].ft = GetFloat(argv[ix]); - else if(IsInt(argv[ix])) aargs[ix].ft = (float)GetInt(argv[ix]); - else ok = false; - - if(ok) LOG2("int arg %i = %f",ix,aargs[ix].ft); - break; - } - case a_int: { - if(IsFloat(argv[ix])) aargs[ix].it = (int)GetFloat(argv[ix]); - else if(IsInt(argv[ix])) aargs[ix].it = GetInt(argv[ix]); - else ok = false; - - if(ok) LOG2("float arg %i = %i",ix,aargs[ix].it); - break; - } - case a_symbol: { - if(IsSymbol(argv[ix])) aargs[ix].st = GetSymbol(argv[ix]); - else ok = false; - - if(ok) LOG2("symbol arg %i = %s",ix,GetString(aargs[ix].st)); - break; - } -#if FLEXT_SYS == FLEXT_SYS_PD - case a_pointer: { - if(IsPointer(argv[ix])) aargs[ix].pt = GetPointer(argv[ix]); - else ok = false; - break; - } -#endif - default: - error("Argument type illegal"); - ok = false; - } - } - - if(ok && ix == argc) { - switch(argc) { - case 0: ret = ((methfun_0)m->fun)(this); break; - case 1: ret = ((methfun_1)m->fun)(this,aargs[0]); break; - case 2: ret = ((methfun_2)m->fun)(this,aargs[0],aargs[1]); break; - case 3: ret = ((methfun_3)m->fun)(this,aargs[0],aargs[1],aargs[2]); break; - case 4: ret = ((methfun_4)m->fun)(this,aargs[0],aargs[1],aargs[2],aargs[3]); break; - case 5: ret = ((methfun_5)m->fun)(this,aargs[0],aargs[1],aargs[2],aargs[3],aargs[4]); break; - } - } - } - } - else if(m->tag == sym_symbol && !argc && (inlet == m->inlet || m->inlet < 0 )) { - // symbol - LOG3("found symbol method for %s: inlet=%i, symbol=%s",m->tag->s_name,inlet,s->s_name); - - t_any sym; sym.st = const_cast(s); - ret = ((methfun_1)m->fun)(this,sym); - } - else if(m->tag == sym_anything && (inlet == m->inlet || m->inlet < 0) && m->argc == 1 && m->args[0] == a_any) { - // any - LOG4("found any method for %s: inlet=%i, symbol=%s, argc=%i",m->tag->s_name,inlet,s->s_name,argc); - - ret = ((methfun_A)m->fun)(this,s,argc,const_cast(argv)); - } - } - -#if FLEXT_SYS == FLEXT_SYS_MAX - // If float message is not explicitly handled: try int handler instead - if(!ret && argc == 1 && s == sym_float && !trap) { - t_atom fl; - SetInt(fl,GetAInt(argv[0])); - trap = true; - ret = m_methodmain(inlet,sym_int,1,&fl); - trap = false; - } - - // If int message is not explicitly handled: try float handler instead - if(!ret && argc == 1 && s == sym_int && !trap) { - t_atom fl; - SetFloat(fl,GetAFloat(argv[0])); - trap = true; - ret = m_methodmain(inlet,sym_float,1,&fl); - trap = false; - } -#endif - - // If float or int message is not explicitly handled: try list handler instead - if(!ret && !trap && argc == 1 && (s == sym_float -#if FLEXT_SYS == FLEXT_SYS_MAX - || s == sym_int -#endif - )) { - t_atom list; - if(s == sym_float) - SetFloat(list,GetFloat(argv[0])); -#if FLEXT_SYS == FLEXT_SYS_MAX - else if(s == sym_int) - SetInt(list,GetInt(argv[0])); -#endif - - trap = true; - ret = m_methodmain(inlet,sym_list,1,&list); - trap = false; - } - - // If symbol message (pure anything without args) is not explicitly handled: try list handler instead - if(!ret && !trap && argc == 0) { - t_atom list; - SetSymbol(list,s); - trap = true; - ret = m_methodmain(inlet,sym_list,1,&list); - trap = false; - } +void flext_base::m_loadbang() {} - // if distmsgs is switched on then distribute list elements over inlets (Max/MSP behavior) - if(!ret && distmsgs && !trap && inlet == 0 && s == sym_list && insigs <= 1) { - int i = incnt; - if(i > argc) i = argc; - for(--i; i >= 0; --i) { // right to left distribution - const t_symbol *sym = NULL; - if(IsFloat(argv[i])) sym = sym_float; - else if(IsInt(argv[i])) sym = sym_int; - else if(IsSymbol(argv[i])) sym = sym_symbol; -#if FLEXT_SYS == FLEXT_SYS_PD - else if(IsPointer(argv[i])) sym = sym_pointer; // can pointer atoms occur here? -#endif - if(sym) { - trap = true; - m_methodmain(i,sym,1,argv+i); - trap = false; - } - } - - ret = true; - } - - if(!ret && !trap) ret = m_method_(inlet,s,argc,argv); - - curtag = NULL; - - return ret; // true if appropriate handler was found and called -} - -bool flext_base::m_method_(int inlet,const t_symbol *s,int argc,const t_atom *argv) -{ -//#ifdef FLEXT_DEBUG - post("%s: message unhandled - inlet:%i args:%i symbol:%s",thisName(),inlet,argc,s?s->s_name:""); -//#endif - return false; -} - - -flext_base::methitem::methitem(int in,const t_symbol *t): - tag(t),inlet(in), - argc(0),args(NULL), - fun(NULL), - nxt(NULL) -{} - -flext_base::methitem::~methitem() -{ - if(nxt) delete nxt; - if(args) delete[] args; -} - -void flext_base::methitem::SetArgs(methfun _fun,int _argc,metharg *_args) -{ - fun = _fun; - if(args) delete[] args; - argc = _argc,args = _args; -} - - - -void flext_base::AddMethItem(methitem *m) -{ - if(methhead) { - methitem *mi; - for(mi = methhead; mi->nxt; mi = mi->nxt) {} - mi->nxt = m; - } - else - methhead = m; -} -/* -const flext_base::methitem *flext_base::FindMethItem(int inlet,const t_symbol *tag,const methitem *st) -{ - const methitem *mi = st?st:mlst; - if(inlet < 0) { - for(; mi; mi = mi->nxt) - if(mi->tag == tag) break; - } - else { - for(; mi; mi = mi->nxt) - if(mi->inlet == inlet && mi->tag == tag) break; - } - return mi; -} -*/ - -void flext_base::AddMethodDef(int inlet,const char *tag) -{ - AddMethItem(new methitem(inlet,tag?MakeSymbol(tag):NULL)); -} - -/*! \brief Add a method to the queue -*/ -void flext_base::AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...) -{ - methitem *mi = new methitem(inlet,MakeSymbol(tag)); - - va_list marker; - - // at first just count the arg type list (in argc) - int argc = 0; - va_start(marker,tp); - metharg *args = NULL,arg = tp; - for(; arg != a_null; ++argc) arg = (metharg)va_arg(marker,int); //metharg); - va_end(marker); - - if(argc > 0) { - if(argc > FLEXT_MAXMETHARGS) { - error("%s - method %s: only %i arguments are type-checkable: use variable argument list for more",thisName(),tag?tag:"?",FLEXT_MAXMETHARGS); - argc = FLEXT_MAXMETHARGS; - } - - args = new metharg[argc]; - - va_start(marker,tp); - metharg a = tp; - for(int ix = 0; ix < argc; ++ix) { -#ifdef FLEXT_DEBUG - if(a == a_list && ix > 0) { - ERRINTERNAL(); - } -#endif -#if FLEXT_SYS == FLEXT_SYS_PD - if(a == a_pointer && flext_base::compatibility) { - post("Pointer arguments are not allowed in compatibility mode"); - } -#endif - args[ix] = a; - a = (metharg)va_arg(marker,int); //metharg); - } - va_end(marker); - } - - mi->SetArgs(fun,argc,args); - - AddMethItem(mi); -} +void flext_base::m_assist(long /*msg*/,long /*arg*/,char * /*s*/) {} -- cgit v1.2.1