aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext/source
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-12-28 04:37:42 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-12-28 04:37:42 +0000
commit562dcc336797951b2a8707413aa44177484c9f2a (patch)
tree162adc736d99b6edf4c03e50061831006ac0f5c4 /externals/grill/flext/source
parent7b0d76e0a6c7b58f6a7a373755c46bde52ebea79 (diff)
""
svn path=/trunk/; revision=309
Diffstat (limited to 'externals/grill/flext/source')
-rw-r--r--externals/grill/flext/source/flatom.cpp80
-rwxr-xr-xexternals/grill/flext/source/flatom_app.cpp76
-rwxr-xr-xexternals/grill/flext/source/flatom_part.cpp37
-rw-r--r--externals/grill/flext/source/flattr.cpp212
-rw-r--r--externals/grill/flext/source/flbase.cpp4
-rw-r--r--externals/grill/flext/source/flbase.h7
-rw-r--r--externals/grill/flext/source/flclass.h211
-rw-r--r--externals/grill/flext/source/fldefs.h177
-rw-r--r--externals/grill/flext/source/flext.cpp670
-rw-r--r--externals/grill/flext/source/flinternal.h6
-rwxr-xr-xexternals/grill/flext/source/flitem.cpp209
-rwxr-xr-xexternals/grill/flext/source/fllib.cpp4
-rwxr-xr-xexternals/grill/flext/source/flmeth.cpp120
-rwxr-xr-xexternals/grill/flext/source/flmsg.cpp256
-rw-r--r--externals/grill/flext/source/flout.cpp357
-rwxr-xr-xexternals/grill/flext/source/flproxy.cpp132
-rwxr-xr-xexternals/grill/flext/source/flqueue.cpp167
-rw-r--r--externals/grill/flext/source/flsupport.cpp18
-rw-r--r--externals/grill/flext/source/flsupport.h18
-rw-r--r--externals/grill/flext/source/flthr.cpp6
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;