diff options
Diffstat (limited to 'externals/grill/flext/source/flout.cpp')
-rw-r--r-- | externals/grill/flext/source/flout.cpp | 357 |
1 files changed, 219 insertions, 138 deletions
diff --git a/externals/grill/flext/source/flout.cpp b/externals/grill/flext/source/flout.cpp index 9dbda7f1..e8341e9e 100644 --- a/externals/grill/flext/source/flout.cpp +++ b/externals/grill/flext/source/flout.cpp @@ -16,14 +16,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "flinternal.h" -#if FLEXT_SYS == FLEXT_SYS_MAX -#define CRITON() short state = lockout_set(1) -#define CRITOFF() lockout_set(state) -#else -#define CRITON() -#define CRITOFF() -#endif - #ifndef FLEXT_THREADS void flext_base::ToOutBang(outlet *o) const { CRITON(); outlet_bang((t_outlet *)o); CRITOFF(); } void flext_base::ToOutFloat(outlet *o,float f) const { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); } @@ -41,153 +33,242 @@ void flext_base::ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom #endif -class flext_base::qmsg +bool flext_base::InitInlets() { -public: - qmsg(): nxt(NULL),tp(tp_none) {} - ~qmsg(); - - qmsg *nxt; - - void Clear(); - - void SetBang(outlet *o) { Clear(); out = o; tp = tp_bang; } - void SetFloat(outlet *o,float f) { Clear(); out = o; tp = tp_float; _float = f; } - void SetInt(outlet *o,int i) { Clear(); out = o; tp = tp_int; _int = i; } - void SetSymbol(outlet *o,const t_symbol *s) { Clear(); out = o; tp = tp_sym; _sym = s; } - void SetList(outlet *o,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_list; _list.argc = argc,_list.argv = CopyList(argc,argv); } - void SetAny(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_any; _any.s = s,_any.argc = argc,_any.argv = CopyList(argc,argv); } - - outlet *out; - enum { tp_none,tp_bang,tp_float,tp_int,tp_sym,tp_list,tp_any } tp; - union { - float _float; - int _int; - const t_symbol *_sym; - struct { int argc; t_atom *argv; } _list; - struct { const t_symbol *s; int argc; t_atom *argv; } _any; - }; -}; - -flext_base::qmsg::~qmsg() -{ - Clear(); - if(nxt) delete nxt; -} + 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 + + delete[] list; + } -void flext_base::qmsg::Clear() -{ - if(tp == tp_list) { if(_list.argv) delete[] _list.argv; } - else if(tp == tp_any) { if(_any.argv) delete[] _any.argv; } - tp = tp_none; + return ok; } -void flext_base::QTick(flext_base *th) +bool flext_base::InitOutlets() { -// post("qtick"); -#if defined(FLEXT_THREADS) && defined(FLEXT_DEBUG) - if(!th->IsSystemThread()) { - error("flext - Queue tick called by wrong thread!"); - return; - } -#endif - -#ifdef FLEXT_THREADS - th->qmutex.Lock(); -#endif - for(;;) { - qmsg *m = th->qhead; - if(!m) break; - - CRITON(); - - switch(m->tp) { - case qmsg::tp_bang: th->ToOutBang(m->out); break; - case qmsg::tp_float: th->ToOutFloat(m->out,m->_float); break; - case qmsg::tp_int: th->ToOutInt(m->out,m->_int); break; - case qmsg::tp_sym: th->ToOutSymbol(m->out,m->_sym); break; - case qmsg::tp_list: th->ToOutList(m->out,m->_list.argc,m->_list.argv); break; - case qmsg::tp_any: th->ToOutAnything(m->out,m->_any.s,m->_any.argc,m->_any.argv); break; -#ifdef FLEXT_DEBUG - default: ERRINTERNAL(); -#endif - } + bool ok = true; - CRITOFF(); + // ---------------------------------- + // create outlets + // ---------------------------------- - th->qhead = m->nxt; - if(!th->qhead) th->qtail = NULL; - m->nxt = NULL; - delete m; - } -#ifdef FLEXT_THREADS - th->qmutex.Unlock(); + 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 -} -void flext_base::Queue(qmsg *m) -{ -// post("Queue"); + if(outlist) { + xlet *xi; -#ifdef FLEXT_THREADS - qmutex.Lock(); -#endif - if(qtail) qtail->nxt = m; - else qhead = m; - qtail = m; -#ifdef FLEXT_THREADS - qmutex.Unlock(); -#endif + // 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; + + outlets = new outlet *[outcnt]; + // type info is now in list array #if FLEXT_SYS == FLEXT_SYS_PD - clock_delay(qclk,0); + for(int ix = 0; ix < outcnt; ++ix) #elif FLEXT_SYS == FLEXT_SYS_MAX - qelem_set(qclk); + for(int ix = outcnt-1; ix >= 0; --ix) #else -#error +#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 + } + } + + delete[] list; + } -} - -void flext_base::ToQueueBang(outlet *o) const -{ - qmsg *m = new qmsg(); - m->SetBang(o); - const_cast<flext_base &>(*this).Queue(m); -} - -void flext_base::ToQueueFloat(outlet *o,float f) const -{ - qmsg *m = new qmsg; - m->SetFloat(o,f); - const_cast<flext_base &>(*this).Queue(m); -} - -void flext_base::ToQueueInt(outlet *o,int f) const -{ - qmsg *m = new qmsg; - m->SetInt(o,f); - const_cast<flext_base &>(*this).Queue(m); -} - -void flext_base::ToQueueSymbol(outlet *o,const t_symbol *s) const -{ - qmsg *m = new qmsg; - m->SetSymbol(o,s); - const_cast<flext_base &>(*this).Queue(m); -} + if(procattr) { +#if FLEXT_SYS == FLEXT_SYS_PD + // attribute dump outlet is the last one + outattr = (outlet *)newout_anything(&x_obj->obj); +#endif -void flext_base::ToQueueList(outlet *o,int argc,const t_atom *argv) const -{ - qmsg *m = new qmsg; - m->SetList(o,argc,argv); - const_cast<flext_base &>(*this).Queue(m); + } + + return ok; } -void flext_base::ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) const -{ - qmsg *m = new qmsg; - m->SetAny(o,s,argc,argv); - const_cast<flext_base &>(*this).Queue(m); -} |