diff options
author | Thomas Grill <xovo@users.sourceforge.net> | 2002-12-28 04:37:42 +0000 |
---|---|---|
committer | Thomas Grill <xovo@users.sourceforge.net> | 2002-12-28 04:37:42 +0000 |
commit | 562dcc336797951b2a8707413aa44177484c9f2a (patch) | |
tree | 162adc736d99b6edf4c03e50061831006ac0f5c4 /externals/grill/flext/source | |
parent | 7b0d76e0a6c7b58f6a7a373755c46bde52ebea79 (diff) |
""
svn path=/trunk/; revision=309
Diffstat (limited to 'externals/grill/flext/source')
20 files changed, 1773 insertions, 994 deletions
diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp index 0efb79f4..3d5db8f2 100644 --- a/externals/grill/flext/source/flatom.cpp +++ b/externals/grill/flext/source/flatom.cpp @@ -36,6 +36,7 @@ flext::AtomList::AtomList(const AtomList &a): flext::AtomList::~AtomList() { Clear(); } + flext::AtomList &flext::AtomList::Set(int argc,const t_atom *argv,int offs,bool resize) { int ncnt = argc+offs; @@ -51,85 +52,6 @@ flext::AtomList &flext::AtomList::Set(int argc,const t_atom *argv,int offs,bool return *this; } -int flext::AtomList::Get(t_atom *argv,int mxsz) const -{ - int argc = Count(); - if(mxsz >= 0 && argc > mxsz) argc = mxsz; - - for(int i = 0; i < argc; ++i) SetAtom(argv[i],lst[i]); - - return argc; -} - - -flext::AtomList &flext::AtomList::Append(const t_atom &a) -{ - t_atom *nlst = new t_atom[cnt+1]; - for(int i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]); - SetAtom(nlst[cnt],a); - - if(lst) delete[] lst; - lst = nlst; - ++cnt; - - return *this; -} - -flext::AtomList &flext::AtomList::Append(int argc,const t_atom *argv) -{ - if(argc) { - t_atom *nlst = new t_atom[cnt+argc]; - int i; - for(i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]); - if(argv) - for(i = 0; i < argc; ++i) SetAtom(nlst[cnt+i],argv[i]); - - if(lst) delete[] lst; - lst = nlst; - cnt += argc; - } - return *this; -} - -flext::AtomList &flext::AtomList::Prepend(const t_atom &a) -{ - t_atom *nlst = new t_atom[cnt+1]; - for(int i = 0; i < cnt; ++i) SetAtom(nlst[i+1],lst[i]); - SetAtom(nlst[0],a); - - if(lst) delete[] lst; - lst = nlst; - ++cnt; - - return *this; -} - -flext::AtomList &flext::AtomList::Prepend(int argc,const t_atom *argv) -{ - if(argc) { - t_atom *nlst = new t_atom[cnt+argc]; - int i; - - if(argv) - for(i = 0; i < argc; ++i) SetAtom(nlst[i],argv[i]); - for(i = 0; i < cnt; ++i) SetAtom(nlst[argc+i],lst[i]); - - if(lst) delete[] lst; - lst = nlst; - cnt += argc; - } - return *this; -} - -flext::AtomList flext::AtomList::GetPart(int offs,int len) const -{ - if(offs+len > Count()) { - len = Count()-offs; - if(len < 0) len = 0; - } - - return AtomList(len,Atoms()+offs); -} flext::AtomAnything::AtomAnything(const t_symbol *h,int argc,const t_atom *argv): diff --git a/externals/grill/flext/source/flatom_app.cpp b/externals/grill/flext/source/flatom_app.cpp new file mode 100755 index 00000000..aedaadcd --- /dev/null +++ b/externals/grill/flext/source/flatom_app.cpp @@ -0,0 +1,76 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flatom_app.cpp + \brief Definitions for handling the t_atom type and lists thereof. +*/ + +#include "flext.h" + + +flext::AtomList &flext::AtomList::Append(const t_atom &a) +{ + t_atom *nlst = new t_atom[cnt+1]; + for(int i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]); + SetAtom(nlst[cnt],a); + + if(lst) delete[] lst; + lst = nlst; + ++cnt; + + return *this; +} + +flext::AtomList &flext::AtomList::Append(int argc,const t_atom *argv) +{ + if(argc) { + t_atom *nlst = new t_atom[cnt+argc]; + int i; + for(i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]); + if(argv) + for(i = 0; i < argc; ++i) SetAtom(nlst[cnt+i],argv[i]); + + if(lst) delete[] lst; + lst = nlst; + cnt += argc; + } + return *this; +} + +flext::AtomList &flext::AtomList::Prepend(const t_atom &a) +{ + t_atom *nlst = new t_atom[cnt+1]; + for(int i = 0; i < cnt; ++i) SetAtom(nlst[i+1],lst[i]); + SetAtom(nlst[0],a); + + if(lst) delete[] lst; + lst = nlst; + ++cnt; + + return *this; +} + +flext::AtomList &flext::AtomList::Prepend(int argc,const t_atom *argv) +{ + if(argc) { + t_atom *nlst = new t_atom[cnt+argc]; + int i; + + if(argv) + for(i = 0; i < argc; ++i) SetAtom(nlst[i],argv[i]); + for(i = 0; i < cnt; ++i) SetAtom(nlst[argc+i],lst[i]); + + if(lst) delete[] lst; + lst = nlst; + cnt += argc; + } + return *this; +} + diff --git a/externals/grill/flext/source/flatom_part.cpp b/externals/grill/flext/source/flatom_part.cpp new file mode 100755 index 00000000..b736666a --- /dev/null +++ b/externals/grill/flext/source/flatom_part.cpp @@ -0,0 +1,37 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flatom_part.cpp + \brief Definitions for handling the t_atom type and lists thereof. +*/ + +#include "flext.h" + +int flext::AtomList::Get(t_atom *argv,int mxsz) const +{ + int argc = Count(); + if(mxsz >= 0 && argc > mxsz) argc = mxsz; + + for(int i = 0; i < argc; ++i) SetAtom(argv[i],lst[i]); + + return argc; +} + + +flext::AtomList flext::AtomList::GetPart(int offs,int len) const +{ + if(offs+len > Count()) { + len = Count()-offs; + if(len < 0) len = 0; + } + + return AtomList(len,Atoms()+offs); +} + diff --git a/externals/grill/flext/source/flattr.cpp b/externals/grill/flext/source/flattr.cpp index 44dc0d28..5612ab33 100644 --- a/externals/grill/flext/source/flattr.cpp +++ b/externals/grill/flext/source/flattr.cpp @@ -21,41 +21,80 @@ WARRANTIES, see the file, "license.txt," in this distribution. #define STD #endif -flext_base::attritem::attritem(const t_symbol *t,const t_symbol *gt,metharg tp,methfun gf,methfun sf): - tag(t),gtag(gt),argtp(tp),gfun(gf),sfun(sf),nxt(NULL) -{} +flext_base::attritem::attritem(const t_symbol *t,metharg tp,methfun f,bool g): + item(t,0,NULL),argtp(tp), + fun(f),isget(g) +{ +} flext_base::attritem::~attritem() { - if(nxt) delete nxt; +// if(nxt) delete nxt; } +/* void flext_base::AddAttrItem(attritem *m) { - if(attrhead) { + int ix = m->Hash(); + post("attr index %x",ix); + attritem *&aix = attrhead[ix]; + + if(aix) { attritem *mi; - for(mi = attrhead; mi->nxt; mi = mi->nxt) {} + for(mi = aix; mi->nxt; mi = mi->nxt) {} mi->nxt = m; } else - attrhead = m; - attrcnt++; + aix = m; +// m->th->attrcnt++; } +*/ -void flext_base::AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun) +//! Add get and set attributes +void flext_base::AddAttrib(itemarr *aa,itemarr *ma,const char *attr,metharg tp,methfun gfun,methfun sfun) { - if(procattr) { - char tmp[256] = "get"; + const t_symbol *asym = MakeSymbol(attr); + +// if(sfun) // if commented out, there will be a warning at run-time (more user-friendly) + { + attritem *a = new attritem(asym,tp,sfun,false); + aa->Add(a); + + // bind attribute to a method + methitem *mi = new methitem(0,asym,a); + mi->SetArgs(sfun,1,&tp); + ma->Add(mi); + } + +// if(gfun) // if commented out, there will be a warning at run-time (more user-friendly) + { + attritem *a = new attritem(asym,tp,gfun,true); + aa->Add(a); + + static char tmp[256] = "get"; strcpy(tmp+3,attr); - AddAttrItem(new attritem(MakeSymbol(attr),MakeSymbol(tmp),tp,gfun,sfun)); - AddMethod(0,attr,(methfun)cb_SetAttrib,a_any,a_null); - AddMethod(0,tmp,(methfun)cb_GetAttrib,a_any,a_null); + // bind attribute to a method + methitem *mi = new methitem(0,MakeSymbol(tmp),a); + mi->SetArgs(gfun,0,NULL); + ma->Add(mi); } +} + +void flext_base::AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun) +{ + if(procattr) + AddAttrib(ThAttrs(),ThMeths(),attr,tp,gfun,sfun); else error("%s - attribute procession is not enabled!",thisName()); } +void flext_base::AddAttrib(t_class *c,const char *attr,metharg tp,methfun gfun,methfun sfun) +{ + AddAttrib(ClAttrs(c),ClMeths(c),attr,tp,gfun,sfun); +} + + int flext_base::CheckAttrib(int argc,const t_atom *argv) { int offs = 0; @@ -81,9 +120,19 @@ bool flext_base::InitAttrib(int argc,const t_atom *argv) bool flext_base::ListAttrib() { if(outattr) { - AtomList la(attrcnt); - attritem *a = attrhead; - for(int i = 0; i < attrcnt; ++i,a = a->nxt) SetSymbol(la[i],a->tag); + int cnt = attrhead?attrhead->Count():0; + int ccnt = clattrhead?clattrhead->Count():0; + AtomList la(ccnt+cnt); + + for(int i = 0,ix = 0; i <= 1; ++i) { + itemarr *a = i?attrhead:clattrhead; + if(a) { + for(int ai = 0; ai < a->Size(); ++ai) { + for(item *l = a->Item(ai); l; l = l->nxt) + SetSymbol(la[ix++],l->tag); + } + } + } ToOutAnything(outattr,MakeSymbol("attributes"),la.Count(),la.Atoms()); return true; @@ -94,90 +143,117 @@ bool flext_base::ListAttrib() bool flext_base::SetAttrib(const t_symbol *tag,int argc,const t_atom *argv) { - attritem *a = attrhead; - for(; a && a->tag != tag; a = a->nxt) {} + // search for matching attribute + attritem *a = (attritem *)attrhead->Find(tag); + while(a && (a->tag != tag || a->inlet != 0 || a->isget)) a = (attritem *)a->nxt; + if(!a) { + a = (attritem *)clattrhead->Find(tag); + while(a && (a->tag != tag || a->inlet != 0 || a->isget)) a = (attritem *)a->nxt; + } - if(a) { - if(a->sfun) { - bool ok = true; + if(a) + return SetAttrib(a,argc,argv); + else { + error("%s - %s: attribute not found",thisName(),GetString(tag)); + return true; + } +} - AtomList la; - t_any any; - switch(a->argtp) { - case a_float: - if(argc == 1 && CanbeFloat(argv[0])) { - any.ft = GetAFloat(argv[0]); - ((methfun_1)a->sfun)(this,any); - } - else ok = false; - break; - case a_int: - if(argc == 1 && CanbeInt(argv[0])) { - any.it = GetAInt(argv[0]); - ((methfun_1)a->sfun)(this,any); - } - else ok = false; - break; - case a_symbol: - if(argc == 1 && IsSymbol(argv[0])) { - any.st = GetSymbol(argv[0]); - ((methfun_1)a->sfun)(this,any); - } - else ok = false; - break; - case a_LIST: - any.vt = &(la(argc,argv)); - ((methfun_1)a->sfun)(this,any); - break; - default: - ERRINTERNAL(); - } +bool flext_base::SetAttrib(attritem *a,int argc,const t_atom *argv) +{ + if(a->fun) { + bool ok = true; - if(!ok) - post("%s - wrong arguments for attribute %s",thisName(),GetString(tag)); + AtomList la; + t_any any; + switch(a->argtp) { + case a_float: + if(argc == 1 && CanbeFloat(argv[0])) { + any.ft = GetAFloat(argv[0]); + ((methfun_1)a->fun)(this,any); + } + else ok = false; + break; + case a_int: + if(argc == 1 && CanbeInt(argv[0])) { + any.it = GetAInt(argv[0]); + ((methfun_1)a->fun)(this,any); + } + else ok = false; + break; + case a_symbol: + if(argc == 1 && IsSymbol(argv[0])) { + any.st = GetSymbol(argv[0]); + ((methfun_1)a->fun)(this,any); + } + else ok = false; + break; + case a_LIST: + any.vt = &(la(argc,argv)); + ((methfun_1)a->fun)(this,any); + break; + default: + ERRINTERNAL(); } - else - post("%s - attribute %s has no get method",thisName(),GetString(tag)); + + if(!ok) + post("%s - wrong arguments for attribute %s",thisName(),GetString(a->tag)); } else - error("%s - %s: attribute not found",thisName(),GetString(tag)); + post("%s - attribute %s has no get method",thisName(),GetString(a->tag)); return true; } -bool flext_base::GetAttrib(const t_symbol *tag,int argc,const t_atom *argv) +/* +bool flext_base::GetAttrib(const t_symbol *tag) { if(argc) post("%s - %s: arguments ignored",thisName(),GetString(tag)); - attritem *a = attrhead; - for(; a && a->gtag != tag; a = a->nxt) {} +#ifdef FLEXT_DEBUG + if(strncmp(GetString(tag),"get",3)) { + post("%s - %s: tag has no 'get' prefix",thisName(),GetString(tag)); + return false; + } +#endif + + const t_symbol *mtag = MakeSymbol(GetString(a->tag)+3); + // search for attribute + attritem *a = (attritem *)attrhead->Find(mtag); + if(!a) a = (attritem *)clattrhead->Find(mtag); +} +*/ + +bool flext_base::GetAttrib(attritem *a) +{ + // main attribute tag if(a) { - if(a->gfun) { + if(a->fun) { AtomList la; t_any any; switch(a->argtp) { case a_float: { - ((methfun_1)a->gfun)(this,any); + ((methfun_1)a->fun)(this,any); la(1); SetFloat(la[0],any.ft); break; } case a_int: { - ((methfun_1)a->gfun)(this,any); + ((methfun_1)a->fun)(this,any); la(1); SetInt(la[0],any.it); break; } case a_symbol: { - ((methfun_1)a->gfun)(this,any); + ((methfun_1)a->fun)(this,any); la(1); SetSymbol(la[0],any.st); break; } case a_LIST: { any.vt = &la; - ((methfun_1)a->gfun)(this,any); + ((methfun_1)a->fun)(this,any); break; } default: @@ -186,10 +262,10 @@ bool flext_base::GetAttrib(const t_symbol *tag,int argc,const t_atom *argv) ToOutAnything(outattr,a->tag,la.Count(),la.Atoms()); } else - post("%s - attribute %s has no set method",thisName(),GetString(tag)); + post("%s - attribute %s has no set method",thisName(),GetString(a->tag)); } else - error("%s - %s: attribute not found",thisName(),GetString(tag)); + error("%s - %s: attribute not found",thisName(),GetString(a->tag)); return true; } diff --git a/externals/grill/flext/source/flbase.cpp b/externals/grill/flext/source/flbase.cpp index f1791884..3b43c1fe 100644 --- a/externals/grill/flext/source/flbase.cpp +++ b/externals/grill/flext/source/flbase.cpp @@ -56,6 +56,10 @@ flext_obj :: flext_obj() flext_obj :: ~flext_obj() {} +bool flext_obj::Init() { return true; } +bool flext_obj::Finalize() { return true; } +void flext_obj::Exit() {} + void flext_obj::DefineHelp(t_class *c,const char *ref,const char *dir,bool addtilde) { #if FLEXT_SYS == FLEXT_SYS_PD diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h index 79128e53..96a89d30 100644 --- a/externals/grill/flext/source/flbase.h +++ b/externals/grill/flext/source/flbase.h @@ -117,10 +117,13 @@ class FLEXT_EXT flext_obj: //! Virtual function called at creation time (but after the constructor) // this also guarantees that there are no instances of flext_obj - virtual bool Init() = 0; + virtual bool Init(); + + //! Virtual function called after Init() has succeeded + virtual bool Finalize(); //! Virtual function called at destruction (before the destructor) - virtual void Exit() {} + virtual void Exit(); //! @} FLEXT_O_CREATION diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h index ab90667a..b0376ed3 100644 --- a/externals/grill/flext/source/flclass.h +++ b/externals/grill/flext/source/flclass.h @@ -77,10 +77,10 @@ public: virtual void m_help(); //! called on patcher load (not on mere object creation!) - virtual void m_loadbang() {} + virtual void m_loadbang(); //! quickhelp for inlets/outlets (gets called in Max/MSP only) - virtual void m_assist(long /*msg*/,long /*arg*/,char * /*s*/) {} + virtual void m_assist(long /*msg*/,long /*arg*/,char * /*s*/); /*! \brief Called for every incoming message. All method handling is done in there @@ -313,35 +313,63 @@ public: */ void AddMethodDef(int inlet,const char *tag = NULL); // call virtual function for tag && inlet - void AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...); - - void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_list,a_null); } - void AddMethod(int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_list,a_null); } - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,tag,(methfun)m,a_null); } // pure method - void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_any,a_null); } // anything - void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_any,a_null); } // anything - void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol - void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol - void AddMethod(int inlet,bool (*m)(flext_base *,float &)) { AddMethod(inlet,"float",(methfun)m,a_float,a_null); } // single float - void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_null); } // list of 2 floats - void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats + + void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_list,a_null); } + void AddMethod(int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_list,a_null); } + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_null); } // pure method + void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ThMeths(),inlet,"anything",(methfun)m,a_any,a_null); } // anything + void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,"anything",(methfun)m,a_any,a_null); } // anything + void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ThMeths(),inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol + void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ThMeths(),inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol + void AddMethod(int inlet,bool (*m)(flext_base *,float &)) { AddMethod(ThMeths(),inlet,"float",(methfun)m,a_float,a_null); } // single float + void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_float,a_float,a_null); } // list of 2 floats + void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats #if FLEXT_SYS == FLEXT_SYS_PD - void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"float",(methfun)m,a_int,a_null); } // single float + void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,"float",(methfun)m,a_int,a_null); } // single float #elif FLEXT_SYS == FLEXT_SYS_MAX - void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"int",(methfun)m,a_int,a_null); } // single float + void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,"int",(methfun)m,a_int,a_null); } // single float #else #error #endif - void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_null); } // list of 2 floats - void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_list,a_null); } // method+gimme - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_list,a_null); } // method+gimme - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_any,a_null); } // method+gimme - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_any,a_null); } // method+gimme - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(inlet,tag,(methfun)m,a_float,a_null); } // method+float - void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(inlet,tag,(methfun)m,a_int,a_null); } // method+int + void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_int,a_int,a_null); } // list of 2 floats + void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(ThMeths(),inlet,"list",(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_float,a_null); } // method+float + void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_int,a_null); } // method+int + + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_list,a_null); } + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_list,a_null); } + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_null); } // pure method + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,"anything",(methfun)m,a_any,a_null); } // anything + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,"anything",(methfun)m,a_any,a_null); } // anything + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ClMeths(c),inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ClMeths(c),inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,float &)) { AddMethod(ClMeths(c),inlet,"float",(methfun)m,a_float,a_null); } // single float + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_float,a_float,a_null); } // list of 2 floats + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats +#if FLEXT_SYS == FLEXT_SYS_PD + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,"float",(methfun)m,a_int,a_null); } // single float +#elif FLEXT_SYS == FLEXT_SYS_MAX + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,"int",(methfun)m,a_int,a_null); } // single float +#else +#error +#endif + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_int,a_int,a_null); } // list of 2 floats + static void AddMethod(t_class *c,int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(ClMeths(c),inlet,"list",(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_float,a_null); } // method+float + static void AddMethod(t_class *c,int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_int,a_null); } // method+int + //! Set Max/MSP style of distributing list elements over (message) inlets void SetDist(bool d = true) { distmsgs = d; } @@ -412,14 +440,10 @@ protected: flext_base(); virtual ~flext_base(); -// inlets and outlets - - /*! \brief Set up inlets and outlets - \ingroup FLEXT_C_INOUT - \return True on successful creation of all inlets and outlets + /*! \brief Set up inlets and outlets, method and attribute lists */ virtual bool Init(); - + //! \brief This represents either an inlet or outlet struct xlet { enum type { @@ -448,6 +472,13 @@ protected: void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(attr,a_LIST,(methfun)get,(methfun)set); } void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(attr,a_ANY,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(c,attr,a_float,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(c,attr,a_int,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(c,attr,a_symbol,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,t_symbol *&),bool (*set)(flext_base *,t_symbol *&)) { AddAttrib(c,attr,a_symbol,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(c,attr,a_LIST,(methfun)get,(methfun)set); } + static void AddAttrib(t_class *c,const char *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(c,attr,a_ANY,(methfun)get,(methfun)set); } + //! @} FLEXT_C_ATTR /*! \addtogroup FLEXT_C_INOUT @@ -483,38 +514,84 @@ protected: // method handling - //! \brief This represents an item of the method list - class methitem { public: - methitem(int inlet,const t_symbol *t); - ~methitem(); - void SetArgs(methfun fun,int argc,metharg *args); + class attritem; + + class item { + public: + item(const t_symbol *t,int inl,attritem *a); + ~item(); + + bool IsAttr() const { return attr != NULL; } const t_symbol *tag; int inlet; + attritem *attr; + item *nxt; + }; + + class itemarr { + public: + itemarr(); + ~itemarr(); + + void Add(item *it); + item *Find(const t_symbol *tag,int inlet = 0) const; + void Finalize(); + + bool Ready() const { return bits >= 0; } + int Count() const { return cnt; } + int Size() const { return bits?1<<bits:0; } + item *Item(int ix) { return arr[ix]; } + + protected: + static int Hash(const t_symbol *,int inlet,int bits); + + item **arr; + int cnt,bits; + }; + + //! \brief This represents an item of the method list + class methitem: + public item { + public: + methitem(int inlet,const t_symbol *tg,attritem *conn = NULL); + ~methitem(); + + void SetArgs(methfun fun,int argc,metharg *args); + int argc; metharg *args; methfun fun; - - methitem *nxt; }; //! \brief This represents an item of the attribute list - class attritem { + class attritem: + public item { public: - attritem(const t_symbol *tag,const t_symbol *gtag,metharg tp,methfun gfun,methfun sfun); + attritem(const t_symbol *tag,metharg tp,methfun fun,bool get); ~attritem(); - const t_symbol *tag,*gtag; + bool isget; metharg argtp; - methfun gfun,sfun; - - attritem *nxt; + methfun fun; }; //! @} FLEXT_CLASS + itemarr *ThMeths() { return methhead; } + static itemarr *ClMeths(t_class *c) { return GetClassArr(c,0); } + + static void AddMethod(itemarr *ma,int inlet,const char *tag,methfun fun,metharg tp,...); + + itemarr *ThAttrs() { return attrhead; } + static itemarr *ClAttrs(t_class *c) { return GetClassArr(c,1); } + + static void AddAttrib(itemarr *aa,itemarr *ma,const char *attr,metharg tp,methfun gfun,methfun sfun); + void AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun); + static void AddAttrib(t_class *c,const char *attr,metharg tp,methfun gfun,methfun sfun); + private: static void Setup(t_class *c); @@ -546,27 +623,31 @@ private: typedef bool (*methfun_3)(flext_base *c,t_any &,t_any &,t_any &); typedef bool (*methfun_4)(flext_base *c,t_any &,t_any &,t_any &,t_any &); typedef bool (*methfun_5)(flext_base *c,t_any &,t_any &,t_any &,t_any &,t_any &); - - methitem *methhead; - void AddMethItem(methitem *m); - attritem *attrhead; - int attrcnt; - void AddAttrItem(attritem *m); + static itemarr *GetClassArr(t_class *c,int ix); - void AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun); + itemarr *methhead,*clmethhead; + + bool CallMeth(const methitem &m,int argc,const t_atom *argv); + bool FindMeth(int inlet,const t_symbol *s,int argc,const t_atom *argv); + bool TryMethTag(const methitem *m,int inlet,const t_symbol *t,int argc,const t_atom *argv); + bool TryMethSym(const methitem *m,int inlet,const t_symbol *t,const t_symbol *s); + bool TryMethAny(const methitem *m,int inlet,const t_symbol *t,const t_symbol *s,int argc,const t_atom *argv); + + itemarr *attrhead,*clattrhead; static int CheckAttrib(int argc,const t_atom *argv); bool InitAttrib(int argc,const t_atom *argv); bool ListAttrib(); - bool GetAttrib(const t_symbol *s,int argc,const t_atom *argv); +// bool GetAttrib(const t_symbol *s); + bool GetAttrib(attritem *a); bool SetAttrib(const t_symbol *s,int argc,const t_atom *argv); + bool SetAttrib(attritem *a,int argc,const t_atom *argv); static bool cb_ListAttrib(flext_base *c) { return c->ListAttrib(); } - static bool cb_GetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->GetAttrib(s,argc,argv); } - static bool cb_SetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->SetAttrib(s,argc,argv); } - +// static bool cb_GetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->GetAttrib(s,argc,argv); } +// static bool cb_SetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->SetAttrib(s,argc,argv); } // queue stuff @@ -582,7 +663,18 @@ private: #if FLEXT_SYS == FLEXT_SYS_PD // proxy object (for additional inlets) stuff - struct px_object; + static t_class *px_class; + + struct 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); + }; + friend struct px_object; #elif FLEXT_SYS == FLEXT_SYS_MAX typedef object px_object; @@ -616,6 +708,11 @@ private: px_object **inlets; + static void SetProxies(t_class *c); + + bool InitInlets(); + bool InitOutlets(); + // callback functions static void cb_help(t_class *c); diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h index 353752f7..49f44366 100644 --- a/externals/grill/flext/source/fldefs.h +++ b/externals/grill/flext/source/fldefs.h @@ -251,6 +251,9 @@ REAL_NEW_3(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2, TYPE3) // deprecated stuff +/*! \defgroup FLEXT_D_DEPRECATED Deprecated definitions + @{ + #define FLEXT_NEW_G FLEXT_NEW_V #define FLEXT_NEW_TILDE FLEXT_NEW_DSP @@ -268,6 +271,10 @@ REAL_NEW_3(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2, TYPE3) #define FLEXT_LIB_TILDE_3 FLEXT_LIB_DSP_3 +#define FLEXT_TILDE_SETUP FLEXT_DSP_SETUP + +//! @} FLEXT_D_DEPRECATED + /*! \defgroup FLEXT_D_LIBRARY Definitions for library objects @{ @@ -288,9 +295,6 @@ REAL_NEW_3(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2, TYPE3) */ #define FLEXT_DSP_SETUP(cl) REAL_SETUP(cl,1) -//! \deprecated -#define FLEXT_TILDE_SETUP FLEXT_DSP_SETUP - //! @} FLEXT_D_LIBRARY @@ -657,10 +661,109 @@ FLEXT_THREAD_1(M_FUN,t_symptr) // ==================================================================================== +/*! \defgroup FLEXT_D_CADDMETHOD Add flext methods within class scope + \note These can only be used at class construction time + @{ +*/ + +//! Add a method handler for bang +#define FLEXT_CADDBANG(CL,IX,M_FUN) \ +\ +AddMethod(CL,IX,"bang",FLEXT_CALL_PRE(M_FUN)) + +//! Add a handler for a method with no arguments +#define FLEXT_CADDMETHOD(CL,IX,M_FUN) \ +AddMethod(CL,IX,FLEXT_CALL_PRE(M_FUN)) + +//! Add a handler for a method with a (variable argument) list +#define FLEXT_CADDMETHOD_V(CL,IX,M_FUN) \ +\ +AddMethod(CL,IX,FLEXT_CALL_PRE(M_FUN)) + +//! Add a handler for a method with an anything argument +#define FLEXT_CADDMETHOD_A(CL,IX,M_FUN) \ +\ +AddMethod(CL,IX,FLEXT_CALL_PRE(M_FUN)) + +//! Add a a handler for a method with implicit arguments +#define FLEXT_CADDMETHOD_(CL,IX,M_TAG,M_FUN) \ +\ +AddMethod(CL,IX,M_TAG,FLEXT_CALL_PRE(M_FUN)) + +//! Add a handler for a method with 1 enum type argument +#define FLEXT_CADDMETHOD_E(CL,IX,M_TAG,M_FUN) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),a_int,a_null) + +//! Add a handler for a method with 1 argument +#define FLEXT_CADDMETHOD_1(CL,IX,M_TAG,M_FUN,TP1) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),a_null) + +//! Add a handler for a method with 2 arguments +#define FLEXT_CADDMETHOD_2(CL,IX,M_TAG,M_FUN,TP1,TP2) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),a_null) + +//! Add a handler for a method with 3 arguments +#define FLEXT_CADDMETHOD_3(CL,IX,M_TAG,M_FUN,TP1,TP2,TP3) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),a_null) + +//! Add a handler for a method with 4 arguments +#define FLEXT_CADDMETHOD_4(CL,IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),a_null) + +//! Add a handler for a method with 5 arguments +#define FLEXT_CADDMETHOD_5(CL,IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4,TP5) \ +\ +AddMethod(ClMeths(CL),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),FLEXTARG(TP5),a_null) + + +// Shortcuts + +//! Add a handler for a method with a boolean argument +#define FLEXT_CADDMETHOD_B(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_1(CL,IX,M_TAG,M_FUN,bool) + +//! Add a handler for a method with 1 float argument +#define FLEXT_CADDMETHOD_F(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_1(CL,IX,M_TAG,M_FUN,float) + +//! Add a handler for a method with 2 float arguments +#define FLEXT_CADDMETHOD_FF(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_2(CL,IX,M_TAG,M_FUN,float,float) + +//! Add a handler for a method with 3 float arguments +#define FLEXT_CADDMETHOD_FFF(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_3(CL,IX,M_TAG,M_FUN,float,float,float) + +//! Add a handler for a method with 1 integer argument +#define FLEXT_CADDMETHOD_I(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_1(CL,IX,M_TAG,M_FUN,int) + +//! Add a handler for a method with 2 integer arguments +#define FLEXT_CADDMETHOD_II(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_2(CL,IX,M_TAG,M_FUN,int,int) + +//! Add a handler for a method with 3 integer arguments +#define FLEXT_CADDMETHOD_III(CL,IX,M_TAG,M_FUN) \ +\ +FLEXT_CADDMETHOD_3(CL,IX,M_TAG,M_FUN,int,int,int) + +//! @} FLEXT_D_CADDMETHOD /*! \defgroup FLEXT_D_ADDMETHOD Add flext methods - \note These can only be used at class construction time + \note These can only be used at object construction time + \note (in constructor or in Init() function before call to parent's Init()) @{ */ @@ -696,32 +799,32 @@ AddMethod(IX,M_TAG,FLEXT_CALL_PRE(M_FUN)) //! Add a handler for a method with 1 enum type argument #define FLEXT_ADDMETHOD_E(IX,M_TAG,M_FUN) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),a_int,a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),a_int,a_null) //! Add a handler for a method with 1 argument #define FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,TP1) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),a_null) //! Add a handler for a method with 2 arguments #define FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,TP1,TP2) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),a_null) //! Add a handler for a method with 3 arguments #define FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,TP1,TP2,TP3) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),a_null) //! Add a handler for a method with 4 arguments #define FLEXT_ADDMETHOD_4(IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),a_null) //! Add a handler for a method with 5 arguments #define FLEXT_ADDMETHOD_5(IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4,TP5) \ \ -AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),FLEXTARG(TP5),a_null) +AddMethod(ThMeths(),IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),FLEXTARG(TP5),a_null) // Shortcuts @@ -761,8 +864,8 @@ FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,int,int) \ FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,int,int,int) -//! @} FLEXT_D_ADDMETHOD +//! @} FLEXT_D_ADDMETHOD /*! \defgroup FLEXT_D_CALLMETHOD Call flext methods manually @@ -1082,12 +1185,62 @@ FLEXT_ATTRGET_V(VAR) FLEXT_ATTRSET_V(VAR) //! @} FLEXT_DA_ATTRVAR -/*! \defgroup FLEXT_D_ADDATTR Announce object attributes +/*! \defgroup FLEXT_D_CADDATTR Announce object attributes at class scope \note These can only be used at class construction time @{ */ //! Add handler for a gettable attribute +#define FLEXT_CADDATTR_GET(CL,NAME,GFUN) \ +\ +AddAttrib(CL,NAME,(FLEXT_GET_PRE(GFUN)),NULL) + +//! Add handler for a settable attribute +#define FLEXT_CADDATTR_SET(CL,NAME,SFUN) \ +\ +AddAttrib(CL,NAME,NULL,(FLEXT_SET_PRE(SFUN))) + +//! Add handlers for a both get- and settable attribute +#define FLEXT_CADDATTR_VAR(CL,NAME,GFUN,SFUN) \ +\ +AddAttrib(CL,NAME,(FLEXT_GET_PRE(GFUN)),(FLEXT_SET_PRE(SFUN))) + +//! Add handlers for a both get- and settable attribute +#define FLEXT_CADDATTR_VAR1(CL,NAME,FUN) \ +\ +AddAttrib(CL,NAME,(FLEXT_GET_PRE(FUN)),(FLEXT_SET_PRE(FUN))) + + +//! Add handler for a gettable enum attribute +#define FLEXT_CADDATTR_GET_E(CL,NAME,GFUN) \ +\ +AddAttrib(CL,NAME,(bool (*)(flext_base *,int &))(FLEXT_GET_PRE(GFUN)),NULL) + +//! Add handler for a settable enum attribute +#define FLEXT_CADDATTR_SET_E(CL,NAME,SFUN) \ +\ +AddAttrib(CL,NAME,NULL,(bool (*)(flext_base *,int &))(FLEXT_SET_PRE(SFUN))) + +//! Add handlers for a both get- and settable enum attribute +#define FLEXT_CADDATTR_VAR_E(CL,NAME,GFUN,SFUN) \ +\ +AddAttrib(CL,NAME,(bool (*)(flext_base *,int &))(FLEXT_GET_PRE(GFUN)),(bool (*)(flext_base *,int &))(FLEXT_SET_PRE(SFUN))) + +//! Add handlers for a both get- and settable enum attribute +#define FLEXT_CADDATTR_VAR1_E(CL,NAME,FUN) \ +\ +AddAttrib(CL,NAME,(bool (*)(flext_base *,int &))(FLEXT_GET_PRE(FUN)),(bool (*)(flext_base *,int &))(FLEXT_SET_PRE(FUN))) + +//! @} FLEXT_D_CADDATTR + + +/*! \defgroup FLEXT_D_ADDATTR Announce object attributes + \note These can only be used at object construction time + \note (in constructor or in Init() function before call to parent's Init()) + @{ +*/ + +//! Add handler for a gettable attribute #define FLEXT_ADDATTR_GET(NAME,GFUN) \ \ AddAttrib(NAME,(FLEXT_GET_PRE(GFUN)),NULL) 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 <string.h> -#include <stdarg.h> - - -// === 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<t_atom *>(argv)); - } - else if(m->argc == 1 && m->args[0] == a_any) { - ret = ((methfun_A)m->fun)(this,s,argc,const_cast<t_atom *>(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<t_symbol *>(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<t_atom *>(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*/) {} diff --git a/externals/grill/flext/source/flinternal.h b/externals/grill/flext/source/flinternal.h index 09b8cbd1..87f04882 100644 --- a/externals/grill/flext/source/flinternal.h +++ b/externals/grill/flext/source/flinternal.h @@ -62,6 +62,9 @@ typedef t_perfroutine t_dspmethod; #define qelem_set clock_set #define qelem_unset clock_unset +#define CRITON() +#define CRITOFF() + #elif FLEXT_SYS == FLEXT_SYS_MAX @@ -106,6 +109,9 @@ typedef void t_outlet; typedef t_perfroutine t_dspmethod; +#define CRITON() short state = lockout_set(1) +#define CRITOFF() lockout_set(state) + #endif diff --git a/externals/grill/flext/source/flitem.cpp b/externals/grill/flext/source/flitem.cpp new file mode 100755 index 00000000..cd5aed9e --- /dev/null +++ b/externals/grill/flext/source/flitem.cpp @@ -0,0 +1,209 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flitem.cpp + \brief Processing of method and attribute lists. +*/ + +#include "flext.h" +#include <string.h> + + +flext_base::item::item(const t_symbol *t,int inl,attritem *a): + inlet(inl),tag(t),attr(a),nxt(NULL) +{} + +flext_base::item::~item() +{ + if(nxt) delete nxt; +} + + +flext_base::itemarr::itemarr(): + arr(new item *[2]),cnt(0),bits(-1) +{ + arr[0] = arr[1] = NULL; +} + +flext_base::itemarr::~itemarr() +{ + int c = Ready()?Size():2; + + for(int i = 0; i < c; ++i) + if(arr[i]) delete arr[i]; + delete[] arr; +} + +void flext_base::itemarr::Add(item *it) +{ + if(Ready()) { + // retrieve array index + int ix = Hash(it->tag,it->inlet,bits); + + // add to array slot + if(arr[ix]) { + item *a = arr[ix]; + while(a->nxt) a = a->nxt; + a->nxt = it; + } + else arr[ix] = it; + } + else { +// post("ADD %i,%s",it->inlet,GetString(it->tag)); + + if(arr[0]) arr[1] = arr[1]->nxt = it; + else arr[0] = arr[1] = it; + ++cnt; + } +} + +void flext_base::itemarr::Finalize() +{ + if(!Ready()) + { + bits = Int2Bits(cnt); // at least enough bits to hold all items + + int sz = Size(); + + // save stored item list + item *lst = arr[0]; + + delete[] arr; + arr = new item *[sz]; + memset(arr,0,sz*sizeof(*arr)); + + while(lst) { + item *l = lst; + lst = lst->nxt; + l->nxt = NULL; + + Add(l); +/* + // retrieve array index + int ix = Hash(l->tag,l->inlet,bits); + +// post("ADD %i,%s -> index %i",l->inlet,GetString(l->tag),ix); + + // add to array slot + if(arr[ix]) { + item *a = arr[ix]; + while(a->nxt) a = a->nxt; + a->nxt = l; + } + else arr[ix] = l; +*/ + } + +#if 0 + post("count=%i, bit=%i size=%i",Count(),bits,sz); + + if(Count()) { + static char usage[1024]; + int c = 0,i; + for(i = 0; i < sz; ++i) { + usage[i] = arr[i]?'x':'.'; + if(arr[i]) ++c; + } + usage[i] = 0; + post("USAGE %i/%i - sparse=%i%% %s",c,Count(),(int)((float)c/Count()*100.),usage); + } +#endif + } +} + +flext_base::item *flext_base::itemarr::Find(const t_symbol *tag,int inlet) const +{ + item *a; + if(!Ready()) + a = arr[0]; + else if(Count()) { + int ix = Hash(tag,inlet,bits); + a = arr[ix]; + } + else + a = NULL; + + // Search first matching entry + while(a && (a->tag != tag || a->inlet != inlet)) a = a->nxt; + return a; +} + +int flext_base::itemarr::Hash(const t_symbol *tag,int inlet,int bits) +{ + unsigned long h = ((reinterpret_cast<unsigned long>(tag)&~7L)<<1)+inlet; + return FoldBits(h,bits); +} + +// --- class item lists (methods and attributes) ---------------- + +class _itemarr +{ +public: + enum { HASHBITS=7, HASHSIZE=1<<HASHBITS }; + + _itemarr(t_class *c,int i); + ~_itemarr(); // will never be called + + static int Hash(t_class *c,int ix); + + int Hash() const { return Hash(cl,ix); } + void Add(_itemarr *a); + + t_class *cl; + int ix; + flext_base::itemarr *arr; + + _itemarr *nxt; +}; + +_itemarr::_itemarr(t_class *c,int i): + cl(c),ix(i), + arr(new flext_base::itemarr), + nxt(NULL) +{} + +void _itemarr::Add(_itemarr *a) +{ + if(nxt) nxt->Add(a); + else nxt = a; +} + +int _itemarr::Hash(t_class *c,int ix) +{ + unsigned long h = (reinterpret_cast<unsigned long>(c)&~3L)+ix; + return flext::FoldBits(h,HASHBITS); +} + +static _itemarr **_arrs = NULL; + +flext_base::itemarr *flext_base::GetClassArr(t_class *c,int ix) +{ + if(!_arrs) { + _arrs = new _itemarr *[_itemarr::HASHSIZE]; + memset(_arrs,0,_itemarr::HASHSIZE*sizeof(*_arrs)); + } + + int hash = _itemarr::Hash(c,ix); + _itemarr *a = _arrs[hash]; + _itemarr *pa = NULL; + while(a && (a->cl != c || a->ix != ix)) pa = a,a = a->nxt; + + if(!a) { + a = new _itemarr(c,ix); + if(pa) + // previous entry... extend + a->nxt = pa->nxt,pa->nxt = a; + else + // new singular entry + _arrs[hash] = a; + } + + return a->arr; +} diff --git a/externals/grill/flext/source/fllib.cpp b/externals/grill/flext/source/fllib.cpp index 77f85dbc..4c66d0b5 100755 --- a/externals/grill/flext/source/fllib.cpp +++ b/externals/grill/flext/source/fllib.cpp @@ -354,8 +354,12 @@ flext_hdr *flext_obj::obj_new(const t_symbol *s,int _argc_,t_atom *argv) flext_obj::m_holdaargv = argv+argc; // call virtual init function + // here, inlets, outlets, methods and attributes can be set up ok = obj->data->Init(); + // call another virtual init function + if(ok) ok = obj->data->Finalize(); + flext_obj::m_holdaargc = 0; flext_obj::m_holdaargv = NULL; } diff --git a/externals/grill/flext/source/flmeth.cpp b/externals/grill/flext/source/flmeth.cpp new file mode 100755 index 00000000..c5b4499b --- /dev/null +++ b/externals/grill/flext/source/flmeth.cpp @@ -0,0 +1,120 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flmeth.cpp + \brief Method processing of flext base class. +*/ + +#include "flext.h" +#include <string.h> +#include <stdarg.h> + +flext_base::methitem::methitem(int in,const t_symbol *tg,attritem *conn): + item(tg,in,conn), + argc(0),args(NULL) + ,fun(NULL) +{} + +flext_base::methitem::~methitem() +{ + 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) +{ + int ix = m->Hash(); + post("method index %x",ix); + methitem *&mix = methhead[ix]; + + if(mix) { + methitem *mi; + for(mi = mix; mi->nxt; mi = mi->nxt) {} + mi->nxt = m; + } + else + mix = 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) +{ + methhead->Add(new methitem(inlet,tag?MakeSymbol(tag):NULL)); +} + +/*! \brief Add a method to the queue +*/ +void flext_base::AddMethod(itemarr *ma,int inlet,const char *tag,methfun fun,metharg tp,...) +{ + 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("flext - method %s: only %i arguments are type-checkable: use variable argument list for more",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); + } + + methitem *mi = new methitem(inlet,MakeSymbol(tag)); + + mi->SetArgs(fun,argc,args); + + ma->Add(mi); +} + diff --git a/externals/grill/flext/source/flmsg.cpp b/externals/grill/flext/source/flmsg.cpp new file mode 100755 index 00000000..a1c049d2 --- /dev/null +++ b/externals/grill/flext/source/flmsg.cpp @@ -0,0 +1,256 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flmsg.cpp + \brief Message processing of flext base class. +*/ + +#include "flext.h" + +bool flext_base::CallMeth(const methitem &m,int argc,const t_atom *argv) +{ + bool ret = false; + 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; + } + } + + return ret; +} + +bool flext_base::TryMethTag(const methitem *m,int inlet,const t_symbol *t,int argc,const t_atom *argv) +{ + do { + if(m->inlet == inlet && m->tag == t) { + LOG3("found method tag %s: inlet=%i, argc=%i",GetString(m->tag),m->inlet,argc); + + if(m->attr) { + // attributes are treated differently + + if(m->attr->isget) + return GetAttrib(m->attr); + else + return SetAttrib(m->attr,argc,argv); + } + else { + if(m->argc == 1) { + // try list + if(m->args[0] == a_list && ((methfun_V)m->fun)(this,argc,const_cast<t_atom *>(argv))) return true; + + // try anything + if(m->args[0] == a_any && ((methfun_A)m->fun)(this,m->tag,argc,const_cast<t_atom *>(argv))) return true; + } + + // try matching number of args + if(argc == m->argc && CallMeth(*m,argc,argv)) return true; + } + } + } while((m = (const methitem *)m->nxt) != NULL); + return false; +} + +bool flext_base::TryMethSym(const methitem *m,int inlet,const t_symbol *t,const t_symbol *s) +{ + do { + if(!m->IsAttr() && m->inlet == inlet && m->tag == t) { + LOG3("found symbol method for %s: inlet=%i, symbol=%s",GetString(m->tag),m->inlet,GetString(s)); + + t_any sym; sym.st = const_cast<t_symbol *>(s); + if(((methfun_1)m->fun)(this,sym)) return true; + } + } while((m = (const methitem *)m->nxt) != NULL); + return false; +} + +bool flext_base::TryMethAny(const methitem *m,int inlet,const t_symbol *t,const t_symbol *s,int argc,const t_atom *argv) +{ + do { + if(!m->IsAttr() && m->inlet == inlet && m->tag == t) { + LOG4("found any method for %s: inlet=%i, symbol=%s, argc=%i",GetString(m->tag),m->inlet,GetString(s),argc); + + if(((methfun_A)m->fun)(this,s,argc,const_cast<t_atom *>(argv))) return true; + } + } while((m = (const methitem *)m->nxt) != NULL); + return false; +} + +bool flext_base::FindMeth(int inlet,const t_symbol *s,int argc,const t_atom *argv) +{ + methitem *m; + + // search for exactly matching tag + if((m = (methitem *)methhead->Find(s,inlet)) != NULL && TryMethTag(m,inlet,s,argc,argv)) return true; + if((m = (methitem *)clmethhead->Find(s,inlet)) != NULL && TryMethTag(m,inlet,s,argc,argv)) return true; + + // if no list args, then search for pure symbol + if(!argc) { + if((m = (methitem *)methhead->Find(sym_symbol,inlet)) != NULL && TryMethSym(m,inlet,sym_symbol,s)) return true; + if((m = (methitem *)clmethhead->Find(sym_symbol,inlet)) != NULL && TryMethSym(m,inlet,sym_symbol,s)) return true; + } + + // otherwise search for anything + if((m = (methitem *)methhead->Find(sym_anything,inlet)) != NULL && m->argc == 1 && m->args[0] == a_any && TryMethAny(m,inlet,sym_anything,s,argc,argv)) return true; + if((m = (methitem *)clmethhead->Find(sym_anything,inlet)) != NULL && m->argc == 1 && m->args[0] == a_any && TryMethAny(m,inlet,sym_anything,s,argc,argv)) return true; + + // if nothing found try any inlet + return inlet >= 0 && FindMeth(-1,s,argc,argv); +} + +/*! \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; + + curtag = s; + + LOG3("methodmain inlet:%i args:%i symbol:%s",inlet,argc,s?GetString(s):""); + + bool ret = FindMeth(inlet,s,argc,argv); + if(ret) goto end; + +#if FLEXT_SYS == FLEXT_SYS_MAX + // If float message is not explicitly handled: try int handler instead + if(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(ret) goto end; + + // If int message is not explicitly handled: try float handler instead + if(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; + } + if(ret) goto end; +#endif + + // If float or int message is not explicitly handled: try list handler instead + if(!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(ret) goto end; + + // If symbol message (pure anything without args) is not explicitly handled: try list handler instead + if(!trap && argc == 0) { + t_atom list; + SetSymbol(list,s); + trap = true; + ret = m_methodmain(inlet,sym_list,1,&list); + trap = false; + } + if(ret) goto end; + + // if distmsgs is switched on then distribute list elements over inlets (Max/MSP behavior) + if(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); + +end: + 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?GetString(s):""); +//#endif + return false; +} + 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); -} diff --git a/externals/grill/flext/source/flproxy.cpp b/externals/grill/flext/source/flproxy.cpp new file mode 100755 index 00000000..c1a6930c --- /dev/null +++ b/externals/grill/flext/source/flproxy.cpp @@ -0,0 +1,132 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flproxy.cpp + \brief Proxy classes for the flext base class. +*/ + +#include "flext.h" +#include "flinternal.h" + + +// === proxy class for flext_base ============================ + +#if FLEXT_SYS == FLEXT_SYS_PD + +t_class *flext_base::px_class = NULL; + +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) + + +void flext_base::SetProxies(t_class *c) +{ + // 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 + + // 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); +} + + diff --git a/externals/grill/flext/source/flqueue.cpp b/externals/grill/flext/source/flqueue.cpp new file mode 100755 index 00000000..537101bc --- /dev/null +++ b/externals/grill/flext/source/flqueue.cpp @@ -0,0 +1,167 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flqueue.cpp + \brief Implementation of the flext message queuing functionality. +*/ + +#include "flext.h" +#include "flinternal.h" + +class flext_base::qmsg +{ +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; +} + +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; +} + +void flext_base::QTick(flext_base *th) +{ +// 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 + } + + CRITOFF(); + + th->qhead = m->nxt; + if(!th->qhead) th->qtail = NULL; + m->nxt = NULL; + delete m; + } +#ifdef FLEXT_THREADS + th->qmutex.Unlock(); +#endif +} + +void flext_base::Queue(qmsg *m) +{ +// post("Queue"); + +#ifdef FLEXT_THREADS + qmutex.Lock(); +#endif + if(qtail) qtail->nxt = m; + else qhead = m; + qtail = m; +#ifdef FLEXT_THREADS + qmutex.Unlock(); +#endif + +#if FLEXT_SYS == FLEXT_SYS_PD + clock_delay(qclk,0); +#elif FLEXT_SYS == FLEXT_SYS_MAX + qelem_set(qclk); +#else +#error +#endif + +} + +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); +} + +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); +} + +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); +} + diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp index 85ebae79..cd57dfd8 100644 --- a/externals/grill/flext/source/flsupport.cpp +++ b/externals/grill/flext/source/flsupport.cpp @@ -58,3 +58,21 @@ void flext::GetAString(const t_atom &a,char *buf,int szbuf) else if(IsInt(a)) sprintf(buf,"%i",GetInt(a)); #endif } + +int flext::FoldBits(unsigned long h,int bits) +{ + if(!bits) return 0; + const int hmax = (1<<bits)-1; + int ret = 0; + for(int i = 0; i < sizeof(h)*8; i += bits) + ret = ret^((h>>i)&hmax); + return ret; +} + +int flext::Int2Bits(unsigned long n) +{ + int b; + for(b = 0; n; ++b) n >>= 1; + return b; +} + diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index ad7158f9..6eef5bd5 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -373,6 +373,24 @@ public: //! @} FLEXT_S_ATOM + +// --- utilities ------------------------------------------------ + + /*! \defgroup FLEXT_S_UTIL Flext utility functions + @{ + */ + + /*! \brief Fold value to a number of bits + \remark Good for hash generation + */ + static int FoldBits(unsigned long h,int bits); + + //! \brief How many bits are necessary to represent n + static int Int2Bits(unsigned long n); + +//! @} FLEXT_S_UTIL + + // --- clock stuff ------------------------------------------------ diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp index e8834b76..a9a68471 100644 --- a/externals/grill/flext/source/flthr.cpp +++ b/externals/grill/flext/source/flthr.cpp @@ -20,10 +20,10 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include <errno.h> //! Thread id of system thread -flext::thrid_t flext::thrid; +flext::thrid_t flext::thrid = 0; //! Thread id of helper thread -flext::thrid_t flext::thrhelpid; +flext::thrid_t flext::thrhelpid = 0; /* flext::thr_entry *flext::thrhead = NULL,*flext::thrtail = NULL; @@ -42,6 +42,8 @@ static flext::ThrCond *thrhelpcond = NULL; //! Start helper thread bool flext::StartHelper() { + if(thrhelpid) return true; + bool ok = false; #if FLEXT_THREADS == FLEXT_THR_POSIX pthread_attr_t attr; |