aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext/source
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/flext/source')
-rw-r--r--externals/grill/flext/source/flatom.cpp139
-rw-r--r--externals/grill/flext/source/flattr.cpp190
-rw-r--r--externals/grill/flext/source/flbase.cpp118
-rw-r--r--externals/grill/flext/source/flbase.h426
-rw-r--r--externals/grill/flext/source/flbuf.cpp255
-rw-r--r--externals/grill/flext/source/flclass.h599
-rwxr-xr-xexternals/grill/flext/source/flcwmax-thr.h20
-rw-r--r--externals/grill/flext/source/flcwmax.h26
-rw-r--r--externals/grill/flext/source/fldefs.h912
-rw-r--r--externals/grill/flext/source/fldoxygen.h22
-rw-r--r--externals/grill/flext/source/fldsp.cpp119
-rw-r--r--externals/grill/flext/source/fldsp.h140
-rw-r--r--externals/grill/flext/source/flext.cpp748
-rw-r--r--externals/grill/flext/source/flext.h45
-rw-r--r--externals/grill/flext/source/flinternal.h111
-rwxr-xr-xexternals/grill/flext/source/fllib.cpp386
-rwxr-xr-xexternals/grill/flext/source/flmspbuffer.h83
-rw-r--r--externals/grill/flext/source/flout.cpp201
-rw-r--r--externals/grill/flext/source/flsndobj.cpp107
-rw-r--r--externals/grill/flext/source/flsndobj.h83
-rw-r--r--externals/grill/flext/source/flstdc.h163
-rw-r--r--externals/grill/flext/source/flsupport.cpp58
-rw-r--r--externals/grill/flext/source/flsupport.h438
-rw-r--r--externals/grill/flext/source/flthr.cpp237
-rw-r--r--externals/grill/flext/source/flutil.cpp68
-rwxr-xr-xexternals/grill/flext/source/flxlet.cpp88
26 files changed, 5782 insertions, 0 deletions
diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp
new file mode 100644
index 00000000..705fc9e6
--- /dev/null
+++ b/externals/grill/flext/source/flatom.cpp
@@ -0,0 +1,139 @@
+/*
+
+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.cpp
+ \brief Definitions for handling the t_atom type and lists thereof.
+*/
+
+#include "flext.h"
+
+//namespace flext {
+
+flext::AtomList::AtomList(int argc,const t_atom *argv):
+ lst(NULL),cnt(0)
+{
+ operator()(argc,argv);
+}
+
+flext::AtomList::AtomList(const AtomList &a):
+ lst(NULL),cnt(0)
+{
+ operator =(a);
+}
+
+flext::AtomList::~AtomList() { Clear(); }
+
+flext::AtomList &flext::AtomList::operator()(int argc,const t_atom *argv)
+{
+ if(lst && cnt != argc) { delete[] lst; lst = NULL; cnt = 0; }
+
+ if(argc) {
+ cnt = argc;
+ lst = new t_atom[cnt];
+
+ if(argv) {
+ for(int i = 0; i < argc; ++i) SetAtom(lst[i],argv[i]);
+/*
+ {
+ switch(lst[i].a_type = argv[i].a_type) {
+ case A_FLOAT:
+ lst[i].a_w.w_float = argv[i].a_w.w_float;
+ break;
+#ifdef MAXMSP
+ case A_LONG:
+ lst[i].a_w.w_int = argv[i].a_w.w_int;
+ break;
+#endif
+ case A_SYMBOL:
+ lst[i].a_w.w_symbol = argv[i].a_w.w_symbol;
+ break;
+#ifdef PD
+ case A_POINTER:
+ lst[i].a_w.w_gpointer = argv[i].a_w.w_gpointer;
+ break;
+#endif
+ default:
+ post("AtomList - atom type (%i) not supported",lst[i].a_type);
+ lst[i].a_type = A_NULL;
+ break;
+ }
+ }
+*/
+ }
+ }
+ return *this;
+}
+
+
+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)
+{
+ t_atom *nlst = new t_atom[cnt+argc];
+ int i;
+ for(i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]);
+ 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)
+{
+ t_atom *nlst = new t_atom[cnt+argc];
+ int i;
+ 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);
+}
+
+//} // namespace flext
diff --git a/externals/grill/flext/source/flattr.cpp b/externals/grill/flext/source/flattr.cpp
new file mode 100644
index 00000000..20b06e41
--- /dev/null
+++ b/externals/grill/flext/source/flattr.cpp
@@ -0,0 +1,190 @@
+/*
+
+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 flattr.cpp
+ \brief Attribute handling for the flext base class
+*/
+
+#include "flext.h"
+#include <string.h>
+#include <stdio.h>
+
+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()
+{
+ if(nxt) delete nxt;
+}
+
+void flext_base::AddAttrItem(attritem *m)
+{
+ if(attrhead) {
+ attritem *mi;
+ for(mi = attrhead; mi->nxt; mi = mi->nxt) {}
+ mi->nxt = m;
+ }
+ else
+ attrhead = m;
+ attrcnt++;
+}
+
+void flext_base::AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun)
+{
+ if(procattr) {
+ char tmp[1024];
+ sprintf(tmp,"get%s",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);
+ }
+ else
+ error("%s - attribute procession is not enabled!",thisName());
+}
+
+int flext_base::CheckAttrib(int argc,const t_atom *argv)
+{
+ int offs = 0;
+ for(; offs < argc; ++offs)
+ if(IsString(argv[offs]) && *GetString(argv[offs]) == '@') break;
+ return offs;
+}
+
+bool flext_base::InitAttrib(int argc,const t_atom *argv)
+{
+ int cur,nxt;
+ for(cur = 0; cur < argc; cur = nxt) {
+ // find next @symbol
+ for(nxt = cur+1; nxt < argc; ++nxt)
+ if(IsString(argv[nxt]) && *GetString(argv[nxt]) == '@') break;
+
+ const t_symbol *tag = MakeSymbol(GetString(argv[cur])+1);
+ SetAttrib(tag,nxt-cur-1,argv+cur+1);
+ }
+ return true;
+}
+
+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);
+
+ ToOutAnything(outattr,thisTag(),la.Count(),la.Atoms());
+ return true;
+ }
+ else
+ return false;
+}
+
+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) {}
+
+ if(a) {
+ if(a->sfun) {
+ bool ok = 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();
+ }
+
+ if(!ok)
+ post("%s - wrong arguments for attribute %s",thisName(),GetString(tag));
+ }
+ else
+ post("%s - attribute %s has no get method",thisName(),GetString(tag));
+ }
+ else
+ error("%s - %s: attribute not found",thisName(),tag);
+ return true;
+}
+
+bool flext_base::GetAttrib(const t_symbol *tag,int argc,const t_atom *argv)
+{
+ if(argc)
+ post("%s - %s: arguments ignored",thisName(),GetString(tag));
+
+ attritem *a = attrhead;
+ for(; a && a->gtag != tag; a = a->nxt) {}
+
+ if(a) {
+ if(a->gfun) {
+ AtomList la;
+ t_any any;
+ switch(a->argtp) {
+ case a_float: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetFloat(la[0],any.ft);
+ break;
+ }
+ case a_int: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetInt(la[0],any.it);
+ break;
+ }
+ case a_symbol: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetSymbol(la[0],any.st);
+ break;
+ }
+ case a_LIST: {
+ any.vt = &la;
+ ((methfun_1)a->gfun)(this,any);
+ break;
+ }
+ default:
+ ERRINTERNAL();
+ }
+ ToOutAnything(outattr,a->tag,la.Count(),la.Atoms());
+ }
+ else
+ post("%s - attribute %s has no set method",thisName(),GetString(tag));
+ }
+ else
+ error("%s - %s: attribute not found",thisName(),tag);
+ return true;
+}
+
diff --git a/externals/grill/flext/source/flbase.cpp b/externals/grill/flext/source/flbase.cpp
new file mode 100644
index 00000000..97fed291
--- /dev/null
+++ b/externals/grill/flext/source/flbase.cpp
@@ -0,0 +1,118 @@
+/*
+
+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 flbase.cpp
+ \brief Implementation of the internal flext base classes.
+
+ \remark This is all derived from GEM by Mark Danks
+*/
+
+#include "flbase.h"
+#include "flinternal.h"
+#include <string.h>
+
+/////////////////////////////////////////////////////////
+//
+// flext_obj
+//
+/////////////////////////////////////////////////////////
+
+flext_hdr *flext_obj::m_holder = NULL;
+const t_symbol *flext_obj::m_holdname = NULL;
+bool flext_obj::m_holdattr = false;
+bool flext_obj::process_attributes = false;
+
+/////////////////////////////////////////////////////////
+// Constructor
+//
+/////////////////////////////////////////////////////////
+flext_obj :: flext_obj()
+ : x_obj(m_holder)
+ , m_name(m_holdname)
+ , procattr(m_holdattr)
+ , init_ok(true)
+{
+#ifdef PD
+ m_canvas = canvas_getcurrent();
+#elif defined(MAXMSP)
+ m_canvas = (t_patcher *)gensym("#P")->s_thing;
+ x_obj->curinlet = 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////
+// Destructor
+//
+/////////////////////////////////////////////////////////
+flext_obj :: ~flext_obj() {}
+
+
+void flext_obj::DefineHelp(t_class *c,const char *ref,const char *dir,bool addtilde)
+{
+#ifdef PD
+ char tmp[256];
+ if(dir) {
+ strcpy(tmp,dir);
+ strcat(tmp,"/");
+ strcat(tmp,ref);
+ if(addtilde) strcat(tmp,"~");
+ }
+ else
+ strcpy(tmp,ref);
+ ::class_sethelpsymbol(c,gensym(const_cast<char *>(tmp)));
+#else
+ // no solution for MaxMSP yet
+#endif
+}
+
+
+/////////////////////////////////////////////////////////
+// overloaded new/delete memory allocation methods
+//
+/////////////////////////////////////////////////////////
+
+void *flext_obj::operator new(size_t bytes)
+{
+ bytes += sizeof(size_t);
+ char *blk = (char *)getbytes(bytes);
+ *(size_t *)blk = bytes;
+ return blk+sizeof(size_t);
+}
+
+void flext_obj::operator delete(void *blk)
+{
+ char *ori = (char *)blk-sizeof(size_t);
+ size_t bytes = *(size_t *)ori;
+ freebytes(ori,bytes);
+}
+
+void *flext_obj::NewAligned(size_t bytes,int bitalign)
+{
+ const size_t ovh = sizeof(size_t)+sizeof(char *);
+ const unsigned long alignovh = bitalign/8-1;
+ bytes += ovh+alignovh;
+ char *blk = (char *)getbytes(bytes);
+ char *ablk = reinterpret_cast<char *>((reinterpret_cast<unsigned long>(blk)+ovh+alignovh) & ~alignovh);
+ *(char **)(ablk-sizeof(size_t)-sizeof(char *)) = blk;
+ *(size_t *)(ablk-sizeof(size_t)) = bytes;
+ return ablk;
+}
+
+void flext_obj::FreeAligned(void *blk)
+{
+ char *ori = *(char **)((char *)blk-sizeof(size_t)-sizeof(char *));
+ size_t bytes = *(size_t *)((char *)blk-sizeof(size_t));
+ freebytes(ori,bytes);
+}
+
+
+
+
+
diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h
new file mode 100644
index 00000000..f3f8b647
--- /dev/null
+++ b/externals/grill/flext/source/flbase.h
@@ -0,0 +1,426 @@
+/*
+
+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 flbase.h
+ \brief Internal flext base classes
+
+ \remark This is all derived from GEM by Mark Danks
+*/
+
+#ifndef __FLEXT_BASE_H
+#define __FLEXT_BASE_H
+
+#include "flstdc.h"
+#include "flsupport.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#endif
+
+class flext_obj;
+
+// ----------------------------------------------------------------------------
+/*! \struct flext_hdr
+ \brief The obligatory PD or Max/MSP object header
+ \internal
+
+ This is in a separate struct to assure that obj is the very first thing.
+ If it were the first thing in flext_obj, then there could be problems with
+ the virtual table of the C++ class.
+*/
+// ----------------------------------------------------------------------------
+
+struct FLEXT_EXT flext_hdr
+{
+ /*! \brief The obligatory object header
+ MUST reside at memory offset 0 (no virtual table possible)
+ */
+ t_sigobj obj;
+
+#ifdef PD
+ //! PD only: float signal holder for pd
+ float defsig;
+#endif
+
+#if defined(MAXMSP)
+ //! MaxMSP only: current inlet used by proxy objects
+ long curinlet;
+#endif
+
+ /*! \brief This points to flext object class
+ This points to the actual polymorphic C++ class
+ */
+ flext_obj *data;
+};
+
+
+// ----------------------------------------------------------------------------
+/*! \class flext_obj
+ \brief The mother of base classes for all flext externs
+ \internal
+
+ Each extern which is written in C++ needs to use the #defines at the
+ end of this header file.
+
+ The define
+
+ FLEXT_HEADER(NEW_CLASS, PARENT_CLASS)
+
+ should be somewhere in your header file.
+ One of the defines like
+
+ FLEXT_NEW(NEW_CLASS)
+ FLEXT_NEW_2(NEW_CLASS, float, float)
+
+ should be the first thing in your implementation file.
+ NEW_CLASS is the name of your class and PARENT_CLASS is the
+ parent of your class.
+*/
+// ----------------------------------------------------------------------------
+
+class FLEXT_EXT flext_obj:
+ public flext
+{
+ public:
+
+ // --- overloading of new/delete memory allocation methods ----
+ // MaxMSP allows only 16K in overdrive mode!
+
+ void *operator new(size_t bytes);
+ void operator delete(void *blk);
+
+ #ifndef __MRC__ // doesn't allow new[] overloading?!
+ void *operator new[](size_t bytes) { return operator new(bytes); }
+ void operator delete[](void *blk) { operator delete(blk); }
+ #endif
+
+ // these are aligned
+ static void *NewAligned(size_t bytes,int bitalign = 128);
+ static void FreeAligned(void *blk);
+
+ // ---------------------
+
+ //! Constructor
+ flext_obj();
+
+ //! Destructor
+ virtual ~flext_obj() = 0;
+
+ //! Get the object's canvas
+ t_canvas *thisCanvas() { return(m_canvas); }
+
+ t_sigobj *thisHdr() { return &x_obj->obj; }
+ const t_sigobj *thisHdr() const { return &x_obj->obj; }
+ const char *thisName() const { return GetString(m_name); }
+ const t_symbol *thisNameSym() const { return m_name; }
+
+#ifdef PD
+ t_class *thisClass() { return (t_class *)((t_object *)(x_obj))->te_g.g_pd; }
+#elif defined(MAXMSP)
+ t_class *thisClass() { return (t_class *)(((t_tinyobject *)x_obj)->t_messlist-1); }
+#endif
+
+ void InitProblem() { init_ok = false; }
+
+ static void ProcessAttributes(bool attr) { process_attributes = attr; }
+
+ // this also guarantees that there are no instances of flext_obj
+ virtual bool Init() = 0;
+ virtual void Exit() {}
+
+// --- help -------------------------------------------------------
+
+ /*! \defgroup FLEXT_C_HELP Flext help/assistance functionality
+
+ @{
+ */
+
+ static void DefineHelp(t_class *c,const char *ref,const char *dir = NULL,bool addtilde = false);
+ void DefineHelp(const char *ref,const char *dir = NULL,bool addtilde = false) { DefineHelp(thisClass(),ref,dir,addtilde); }
+
+ //! @}
+
+
+ protected:
+
+ //! The object header
+ flext_hdr *x_obj;
+
+ //! Flag for attribute procession
+ bool procattr;
+
+ static bool process_attributes;
+
+ private:
+
+ //! The canvas (patcher) that the object is in
+ t_canvas *m_canvas;
+
+ //! Flag for successful object construction
+ bool init_ok;
+
+ public:
+
+ //! Creation callback
+ static void __setup__(t_class *) { flext::Setup(); }
+
+ /*! \brief This is a temporary holder
+ \warning don't touch it!
+ */
+ static flext_hdr *m_holder;
+ //! Hold object's name during construction
+ static const t_symbol *m_holdname;
+
+ static bool m_holdattr;
+
+ //! The object's name in the patcher
+ const t_symbol *m_name;
+
+ //! Check whether construction was successful
+ bool InitOk() const { return init_ok; }
+
+ //@{
+ //! Definitions for library objects
+
+ static void lib_init(const char *name,void setupfun(),bool attr);
+ static void obj_add(bool lib,bool dsp,bool attr,const char *idname,const char *names,void setupfun(t_class *),flext_obj *(*newfun)(int,t_atom *),void (*freefun)(flext_hdr *),int argtp1,...);
+ static flext_hdr *obj_new(const t_symbol *s,int argc,t_atom *argv);
+ static void obj_free(flext_hdr *o);
+ //@}
+};
+
+
+// max. 4 creation args (see the following macros)
+#define FLEXT_MAXNEWARGS 4
+
+// max. 5 method args (see the following macros)
+#define FLEXT_MAXMETHARGS 5
+
+// prefixes for the macro generated handler functions
+#define FLEXT_CALL_PRE(F) flext_c_##F
+#define FLEXT_THR_PRE(F) flext_t_##F
+#define FLEXT_GET_PRE(F) flext_g_##F
+#define FLEXT_SET_PRE(F) flext_s_##F
+
+
+#ifndef FLEXT_ATTRIBUTES
+#define FLEXT_ATTRIBUTES 0
+#endif
+
+// ----------------------------------------
+// These should be used in the header
+// ----------------------------------------
+
+
+#define FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) \
+public: \
+typedef NEW_CLASS thisType; \
+static flext_obj *__init__(int argc,t_atom *argv); \
+static void __free__(flext_hdr *hdr) \
+{ flext_obj *mydata = hdr->data; delete mydata; \
+ hdr->flext_hdr::~flext_hdr(); } \
+static void __setup__(t_class *classPtr) { \
+ PARENT_CLASS::__setup__(classPtr); } \
+protected: \
+static inline NEW_CLASS *thisObject(void *c) { return FLEXT_CAST<NEW_CLASS *>(((flext_hdr *)c)->data); }
+
+
+#define FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
+public: \
+typedef NEW_CLASS thisType; \
+static flext_obj *__init__(int argc,t_atom *argv); \
+static void __free__(flext_hdr *hdr) \
+{ flext_obj *mydata = hdr->data; delete mydata; \
+ hdr->flext_hdr::~flext_hdr(); } \
+static void __setup__(t_class *classPtr) \
+{ PARENT_CLASS::__setup__(classPtr); \
+ NEW_CLASS::SETUPFUN(classPtr); } \
+protected: \
+static inline NEW_CLASS *thisObject(void *c) { return FLEXT_CAST<NEW_CLASS *>(((flext_hdr *)c)->data); }
+
+
+// generate name of dsp/non-dsp setup function
+#define FLEXT_STPF_0(NAME) NAME##_setup
+#define FLEXT_STPF_1(NAME) NAME##_tilde_setup
+#define FLEXT_STPF_(DSP) FLEXT_STPF_##DSP
+#define FLEXT_STPF(NAME,DSP) FLEXT_STPF_(DSP)(NAME)
+
+
+
+// --------------------------------------------------------------------------------------
+
+
+
+// these can be used in library setup functions
+// to register the individual objects in the library
+
+#define FLEXT_SETUP(cl) \
+extern void cl##_setup(); \
+cl##_setup()
+
+#define FLEXT_DSP_SETUP(cl) \
+extern void cl##_tilde_setup(); \
+cl##_tilde_setup()
+
+// deprecated
+#define FLEXT_TILDE_SETUP FLEXT_DSP_SETUP
+
+
+// specify that to define the library itself
+
+#ifdef PD
+#define FLEXT_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT void NAME##_setup() { flext_obj::lib_init(#NAME,SETUPFUN,FLEXT_ATTRIBUTES); }
+#else // MAXMSP
+#define FLEXT_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT int main() { flext_obj::lib_init(#NAME,SETUPFUN,FLEXT_ATTRIBUTES); return 0; }
+#endif
+
+
+// --------------------------------------------------
+
+
+#define FLEXT_EXP_0 extern "C" FLEXT_EXT
+#define FLEXT_EXP_1
+#define FLEXT_EXP(LIB) FLEXT_EXP_##LIB
+
+#ifdef PD
+#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP)
+#else // MAXMSP
+#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP) extern "C" FLEXT_EXT int main() { FLEXT_STPF(NEW_CLASS,DSP)(); return 0; }
+#endif
+#define FLEXT_OBJ_SETUP_1(NEW_CLASS,DSP)
+
+#define FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) FLEXT_OBJ_SETUP_##LIB(NEW_CLASS,DSP)
+
+
+
+// ----------------------------------------
+// These definitions are used below
+// ----------------------------------------
+
+// Shortcuts for PD/Max type arguments
+#define FLEXTTYPE_void A_NULL
+#define CALLBTYPE_void void
+#define FLEXTTYPE_float A_FLOAT
+#define CALLBTYPE_float float
+#define FLEXTTYPE_t_float A_FLOAT
+#define CALLBTYPE_t_float t_float
+
+//* #define FLEXTTYPE_t_flint A_FLINT
+
+#ifdef PD
+#define FLEXTTYPE_int A_FLOAT
+#define CALLBTYPE_int float
+#else
+#define FLEXTTYPE_int A_INT
+#define CALLBTYPE_int int
+#endif
+
+#define FLEXTTYPE_t_symptr A_SYMBOL
+#define CALLBTYPE_t_symptr t_symptr
+#define FLEXTTYPE_t_symtype A_SYMBOL
+#define CALLBTYPE_t_symtype t_symptr
+#define FLEXTTYPE_t_ptrtype A_POINTER
+#define CALLBTYPE_t_ptrtype t_ptrtype
+
+#define FLEXTTP(TP) FLEXTTYPE_ ## TP
+#define CALLBTP(TP) CALLBTYPE_ ## TP
+
+
+#define ARGMEMBER_int(a) GetInt(a)
+#define ARGMEMBER_float(a) GetFloat(a)
+#define ARGMEMBER_t_symptr(a) GetSymbol(a)
+#define ARGMEMBER_t_symtype(a) GetSymbol(a)
+#define ARGCAST(arg,tp) ARGMEMBER_##tp(arg)
+
+
+#define REAL_NEW(NAME,NEW_CLASS,DSP,LIB) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS; \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,A_NULL); \
+}
+
+#define REAL_NEW_V(NAME,NEW_CLASS,DSP,LIB) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(argc,argv); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,A_GIMME,A_NULL); \
+}
+
+#define REAL_NEW_1(NAME,NEW_CLASS,DSP,LIB, TYPE1) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),A_NULL); \
+}
+
+#define REAL_NEW_2(NAME,NEW_CLASS,DSP,LIB, TYPE1,TYPE2) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),A_NULL); \
+}
+
+#define REAL_NEW_3(NAME,NEW_CLASS,DSP,LIB, TYPE1, TYPE2, TYPE3) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),A_NULL); \
+}
+
+#define REAL_NEW_4(NAME,NEW_CLASS,DSP,LIB, TYPE1,TYPE2, TYPE3, TYPE4) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3),ARGCAST(argv[3],TYPE4)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),FLEXTTP(TYPE4),A_NULL); \
+}
+
+
+// Shortcuts for method arguments:
+#define FLEXTARG_float a_float
+#define FLEXTARG_int a_int
+#define FLEXTARG_bool a_int
+#define FLEXTARG_t_float a_float
+#define FLEXTARG_t_symtype a_symbol
+#define FLEXTARG_t_symptr a_symbol
+#define FLEXTARG_t_ptrtype a_pointer
+
+#define FLEXTARG(TP) FLEXTARG_ ## TP
+
+
+#endif
+
+
+
+
diff --git a/externals/grill/flext/source/flbuf.cpp b/externals/grill/flext/source/flbuf.cpp
new file mode 100644
index 00000000..dc5704c0
--- /dev/null
+++ b/externals/grill/flext/source/flbuf.cpp
@@ -0,0 +1,255 @@
+/*
+
+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 flbuf.cpp
+ \brief Implementation of the buffer abstraction class.
+*/
+
+#include "flext.h"
+
+#ifdef MAXMSP
+#include "flmspbuffer.h" // include inofficial buffer.h
+#endif
+
+#ifdef PD
+#define DIRTY_INTERVAL 0 // buffer dirty check in msec
+#endif
+
+
+
+flext::buffer::buffer(const t_symbol *bn,bool delayed):
+ sym(NULL),data(NULL),
+ chns(0),frames(0)
+{
+#ifdef PD
+ arr = NULL;
+ interval = DIRTY_INTERVAL;
+ isdirty = false;
+ ticking = false;
+ tick = clock_new(this,(t_method)cb_tick);
+#endif
+
+ if(bn) Set(bn,delayed);
+}
+
+flext::buffer::~buffer()
+{
+#ifdef PD
+ clock_free(tick);
+#endif
+}
+
+int flext::buffer::Set(const t_symbol *s,bool nameonly)
+{
+ int ret = 0;
+ bool valid = data != NULL; // valid now? (before change)
+
+ if(s && sym != s) {
+ ret = -1;
+ data = NULL;
+ frames = 0;
+ chns = 0;
+ }
+
+ if(s && *s->s_name) sym = s;
+
+ if(!sym) {
+ if(valid) ret = -1;
+ }
+ else if(!nameonly) {
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+
+ arr = (t_garray *)pd_findbyclass(const_cast<t_symbol *>(sym), garray_class);
+ if(!arr)
+ {
+ if (*sym->s_name) error("buffer: no such array '%s'",sym->s_name);
+ sym = NULL;
+ if(valid) ret = -1;
+ }
+ else if(!garray_getfloatarray(arr, &frames1, &data1))
+ {
+ error("buffer: bad template '%s'", sym->s_name);
+ data = NULL;
+ frames = 0;
+ if(valid) ret = -1;
+ }
+ else {
+ garray_usedindsp(arr);
+ if(frames != frames1) { frames = frames1; if(!ret) ret = 1; }
+ if(data != data1) { data = data1; if(!ret) ret = 1; }
+ chns = 1;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ if(valid) ret = -1;
+ }
+ else {
+#ifdef DEBUG
+ post("%s: buffer object '%s' - valid:%i samples:%i channels:%i frames:%i",thisName(),bufname->s_name,p->b_valid,p->b_frames,p->b_nchans,p->b_frames);
+#endif
+ if(data != p->b_samples) { data = p->b_samples; if(!ret) ret = 1; }
+ if(chns != p->b_nchans) { chns = p->b_nchans; if(!ret) ret = 1; }
+ if(frames != p->b_frames) { frames = p->b_frames; if(!ret) ret = 1; }
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined", sym->s_name);
+ if(valid) ret = -1;
+ }
+#endif
+ }
+
+ return ret;
+}
+
+bool flext::buffer::Update()
+{
+ if(!Ok()) return false;
+
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+ if(!garray_getfloatarray(arr, &frames1, &data1)) {
+ frames = 0;
+ data = NULL;
+ chns = 0;
+ return true;
+ }
+ else if(data != data1 || frames != frames1) {
+ frames = frames1;
+ data = data1;
+ return true;
+ }
+ else
+ return false;
+#else // MAXMSP
+ if(!sym->s_thing)
+ return false;
+ else {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+ if(data != p->b_samples || chns != p->b_nchans || frames != p->b_frames) {
+ data = p->b_samples;
+ chns = p->b_nchans;
+ frames = p->b_frames;
+ return true;
+ }
+ else
+ return false;
+ }
+#endif
+}
+
+void flext::buffer::Frames(int fr,bool keep)
+{
+#ifdef PD
+ ::garray_resize(arr,(float)fr);
+ Update();
+#else
+ t_sample *tmp = NULL;
+ int sz = frames;
+ if(fr < sz) sz = fr;
+
+ if(keep) {
+ // copy buffer data to tmp storage
+ tmp = new t_sample[sz];
+ if(tmp)
+ BlockMoveData(data,tmp,sizeof(t_sample)*sz);
+ else
+ error("flext::buffer - not enough memory for keeping buffer~ contents");
+ }
+
+ t_atom msg;
+ _buffer *buf = (_buffer *)sym->s_thing;
+ // b_msr reflects buffer sample rate... is this what we want?
+ // Max bug: adding small value 0.001 to get right sample count
+ float ms = fr/buf->b_msr+0.001;
+
+ SetFloat(msg,ms);
+ ::typedmess((object *)buf,gensym("size"),1,&msg);
+
+ Update();
+
+ if(tmp) {
+ // copy data back
+ BlockMoveData(tmp,data,sizeof(t_sample)*sz);
+ delete[] tmp;
+ }
+#endif
+}
+
+
+#ifdef PD
+void flext::buffer::SetRefrIntv(float intv)
+{
+ interval = intv;
+ if(interval == 0 && ticking) {
+ clock_unset(tick);
+ ticking = false;
+ }
+}
+#else
+void flext::buffer::SetRefrIntv(float) {}
+#endif
+
+
+void flext::buffer::Dirty(bool force)
+{
+ if(sym) {
+#ifdef PD
+ if((!ticking) && (interval || force)) {
+ ticking = true;
+ cb_tick(this); // immediately redraw
+ }
+ else {
+ if(force) clock_delay(tick,0);
+ isdirty = true;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ _buffer *p = (_buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ }
+ else {
+ p->b_modtime = gettime();
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined",sym->s_name);
+ }
+#endif
+ }
+}
+
+#ifdef PD
+void flext::buffer::cb_tick(buffer *b)
+{
+ if(b->arr) garray_redraw(b->arr);
+#ifdef _DEBUG
+ else error("buffer: array is NULL");
+#endif
+
+ if(b->isdirty && b->interval) {
+ b->isdirty = false;
+ b->ticking = true;
+ clock_delay(b->tick,b->interval);
+ }
+ else
+ b->ticking = false;
+}
+#endif
+
diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h
new file mode 100644
index 00000000..5c67dde9
--- /dev/null
+++ b/externals/grill/flext/source/flclass.h
@@ -0,0 +1,599 @@
+/*
+
+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 flclass.h
+ \brief User accessible flext base classes
+
+*/
+
+#ifndef __FLCLASS_H
+#define __FLCLASS_H
+
+// include the header file declaring the base classes
+#include "flbase.h"
+#include "flsupport.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#include <sched.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#ifdef __BORLANDC__
+#pragma warn -8008 // Condition is always false
+#pragma warn -8057 // Parameter is never used
+#pragma warn -8066 // Unreachable code
+#endif
+
+
+// === flext_base ==================================================
+
+//class qmsg;
+//class thr_entry;
+
+/*! \brief Flext message only base object
+*/
+
+
+class flext_base:
+ public flext_obj
+{
+ FLEXT_HEADER_S(flext_base,flext_obj,Setup)
+
+ friend class flext_obj;
+
+public:
+
+ /*! \defgroup FLEXT_C_BASE Flext basic class functionality
+
+ @{
+ */
+
+// --- compatibility mode ----------------------------------------
+
+ /*! \brief Cross-platform compatibility flag.
+ If set flext allows only operations valid for all platforms.
+ Set to true by default!
+ */
+ static bool compatibility;
+
+// --- inheritable virtual methods --------------------------------
+
+ /*! \defgroup FLEXT_C_VIRTUAL Flext virtual base class functions
+
+ @{
+ */
+
+ //! called on "help" message: should post some text
+ virtual void m_help();
+
+ //! called on patcher load (not on mere object creation!)
+ virtual void m_loadbang() {}
+
+ //! quickhelp for inlets/outlets (gets calles in MaxMSP only)
+ virtual void m_assist(long /*msg*/,long /*arg*/,char * /*s*/) {}
+
+ /*! \brief Called for every incoming message.
+ All method handling is done in there
+ \return True if a handler was found and called
+ */
+ virtual bool m_methodmain(int inlet,const t_symbol *s,int argc,t_atom *argv);
+
+ //! called for every unhandled message (by m_methodmain)
+ virtual bool m_method_(int inlet,const t_symbol *s,int argc,t_atom *argv);
+
+//! @}
+
+
+// --- inlet/outlet stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_C_INOUT Flext in-/outlet functions
+ \note These must be called in the class' constructor
+ \note All (also default) inlets must be defined
+
+ @{
+ */
+
+ // argument m specifies multiple inlet/outlet count
+
+// void AddInDef() { AddInlet(xlet::tp_def,1); }
+
+ /*! \brief Add inlet(s) for anythings
+ That's the one to choose for the left-most (first) inlet unless it's a signal inlet.
+ */
+ void AddInAnything(int m = 1) { AddInlet(xlet::tp_any,m); } // leftmost or via proxy
+ void AddInAnything(const char *desc,int m = 1) { AddInlet(xlet::tp_any,m,desc); } // leftmost or via proxy
+ //! Add inlet(s) for floats
+ void AddInFloat(int m = 1) { AddInlet(xlet::tp_float,m); }
+ void AddInFloat(const char *desc,int m = 1) { AddInlet(xlet::tp_float,m,desc); }
+ //! Add inlet(s) for ints
+ void AddInInt(int m = 1) { AddInlet(xlet::tp_int,m); }
+ void AddInInt(const char *desc,int m = 1) { AddInlet(xlet::tp_int,m,desc); }
+ //! Add inlet(s) for symbols
+ void AddInSymbol(int m = 1) { AddInlet(xlet::tp_sym,m); }
+ void AddInSymbol(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
+ //! Add inlet(s) for bang
+ void AddInBang(int m = 1) { AddInlet(xlet::tp_sym,m); }
+ void AddInBang(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
+ //! Add inlet(s) for lists
+ void AddInList(int m = 1) { AddInlet(xlet::tp_list,m); } // via proxy
+ void AddInList(const char *desc,int m = 1) { AddInlet(xlet::tp_list,m,desc); } // via proxy
+
+ //! Add outlet(s) for anythings
+ void AddOutAnything(int m = 1) { AddOutlet(xlet::tp_any,m); }
+ void AddOutAnything(const char *desc,int m = 1) { AddOutlet(xlet::tp_any,m,desc); }
+ //! Add outlet(s) for floats
+ void AddOutFloat(int m = 1) { AddOutlet(xlet::tp_float,m); }
+ void AddOutFloat(const char *desc,int m = 1) { AddOutlet(xlet::tp_float,m,desc); }
+ //! Add outlet(s) for ints
+ void AddOutInt(int m = 1) { AddOutlet(xlet::tp_int,m); }
+ void AddOutInt(const char *desc,int m = 1) { AddOutlet(xlet::tp_int,m,desc); }
+ //! Add outlet(s) for symbols
+ void AddOutSymbol(int m = 1) { AddOutlet(xlet::tp_sym,m); }
+ void AddOutSymbol(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
+ //! Add outlet(s) for bangs
+ void AddOutBang(int m = 1) { AddOutlet(xlet::tp_sym,m); }
+ void AddOutBang(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
+ //! Add outlet(s) for lists
+ void AddOutList(int m = 1) { AddOutlet(xlet::tp_list,m); }
+ void AddOutList(const char *desc,int m = 1) { AddOutlet(xlet::tp_list,m,desc); }
+
+ /*! \brief Set up inlets and outlets
+ \note this is deprecated... inlets and outlets are now set up automatically
+ */
+ bool SetupInOut() { return true; }
+
+ //! Get number of inlets
+ int CntIn() const { return incnt; }
+ //! Get number of outlets
+ int CntOut() const { return outcnt; }
+ //! Get number of signal inlets
+ int CntInSig() const { return insigs; }
+ //! Get number of signal outlets
+ int CntOutSig() const { return outsigs; }
+
+
+ class outlet;
+// class AtomList;
+// class AtomAnything;
+
+ //! Retrieve currently processed message tag (NULL if no message processing)
+ const t_symbol *thisTag() const { return curtag; }
+
+ //! Get pointer to outlet (_after_ calling setup_inout()!)
+ outlet *GetOut(int ix) { return (outlets && ix < outcnt)?outlets[ix]:NULL; }
+
+ // output messages
+
+ void ToOutBang(outlet *o);
+ //! Output bang (index n starts with 0)
+ void ToOutBang(int n) { outlet *o = GetOut(n); if(o) ToOutBang(o); }
+
+ void ToOutFloat(outlet *o,float f);
+ //! Output float (index n starts with 0)
+ void ToOutFloat(int n,float f) { outlet *o = GetOut(n); if(o) ToOutFloat(o,f); }
+
+ void ToOutInt(outlet *o,int f);
+ //! Output int (index n starts with 0)
+ void ToOutInt(int n,int f) { outlet *o = GetOut(n); if(o) ToOutInt(o,f); }
+
+ void ToOutSymbol(outlet *o,const t_symbol *s);
+ //! Output symbol (index n starts with 0)
+ void ToOutSymbol(int n,const t_symbol *s) { outlet *o = GetOut(n); if(o) ToOutSymbol(o,s); }
+
+ void ToOutString(outlet *o,const char *s) { ToOutSymbol(o,MakeSymbol(s)); }
+ //! Output string (index n starts with 0)
+ void ToOutString(int n,const char *s) { outlet *o = GetOut(n); if(o) ToOutString(o,s); }
+
+ void ToOutList(outlet *o,int argc,const t_atom *argv);
+ //! Output list (index n starts with 0)
+ void ToOutList(int n,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToOutList(o,argc,argv); }
+ //! Output list (index n starts with 0)
+ void ToOutList(int n,const AtomList &list) { ToOutList(n,list.Count(),list.Atoms()); }
+
+ void ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv);
+ //! Output anything (index n starts with 0)
+ void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToOutAnything(o,const_cast<t_symbol *>(s),argc,argv); }
+ //! Output anything (index n starts with 0)
+ void ToOutAnything(int n,const AtomAnything &any) { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); }
+
+ void ToQueueBang(outlet *o);
+ void ToQueueBang(int n) { outlet *o = GetOut(n); if(o) ToQueueBang(o); }
+ void ToQueueFloat(outlet *o,float f);
+ void ToQueueFloat(int n,float f) { outlet *o = GetOut(n); if(o) ToQueueFloat(o,f); }
+ void ToQueueInt(outlet *o,int f);
+ void ToQueueInt(int n,int f) { outlet *o = GetOut(n); if(o) ToQueueInt(o,f); }
+ void ToQueueSymbol(outlet *o,const t_symbol *s);
+ void ToQueueSymbol(int n,const t_symbol *s) { outlet *o = GetOut(n); if(o) ToQueueSymbol(o,s); }
+ void ToQueueString(int n,const char *s) { ToQueueSymbol(n,MakeSymbol(s)); }
+ void ToQueueList(outlet *o,int argc,const t_atom *argv);
+ void ToQueueList(int n,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToQueueList(o,argc,argv); }
+ void ToQueueList(int n,const AtomList &list) { ToQueueList(n,list.Count(),list.Atoms()); }
+ void ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv);
+ void ToQueueAnything(int n,const t_symbol *s,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToQueueAnything(o,s,argc,argv); }
+ void ToQueueAnything(int n,const AtomAnything &any) { ToQueueAnything(n,any.Header(),any.Count(),any.Atoms()); }
+
+//! @}
+
+
+// --- message handling -------------------------------------------
+
+ enum metharg {
+ a_null = 0,
+ a_float,a_int,
+ a_symbol,a_pointer,
+ a_list,a_any,
+ a_LIST,a_ANY
+ };
+
+ typedef bool (*methfun)(flext_base *c);
+
+ /*! \defgroup FLEXT_C_ADDMETHOD Flext method handling
+ \internal
+
+ @{
+ */
+
+ 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,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,tag,(methfun)m,a_null); } // pure method
+ void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,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 *,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
+#ifdef PD
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"float",(methfun)m,a_int,a_null); } // single float
+#else
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"int",(methfun)m,a_int,a_null); } // single float
+#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 *,const 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 *,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
+
+ //! Set MaxMSP style of distributing list elements over (message) inlets
+ void SetDist(bool d = true) { distmsgs = d; }
+
+//! @}
+
+// --- bind/unbind ---------------------------------------
+
+#ifdef PD
+ //! Bind object to a symbol
+ bool Bind(const t_symbol *s) { pd_bind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
+ //! Unbind object from a symbol
+ bool Unbind(const t_symbol *s) { pd_unbind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
+#else
+ //! Bind object to a symbol
+ bool Bind(const t_symbol *s) { if(s->s_thing) return false; else { const_cast<t_symbol *>(s)->s_thing = (t_object *)thisHdr(); return true; } }
+ //! Unbind object from a symbol
+ bool Unbind(const t_symbol *s) { if(s->s_thing != (t_object *)thisHdr()) return false; else { const_cast<t_symbol *>(s)->s_thing = NULL; return true; } }
+#endif
+ //! Bind object to a symbol (as string)
+ bool Bind(const char *c) { return Bind(MakeSymbol(c)); }
+ //! Unbind object from a symbol (as string)
+ bool Unbind(const char *c) { return Unbind(MakeSymbol(c)); }
+
+/*
+ // Low level
+
+ //! Bind object to a symbol
+ static void DoUnbind(t_symbol *s,flext_obj *o);
+ //! Unbind object from a symbol
+ static void DoBind(const t_symbol *s,flext_obj *o);
+ //! Get bound object of a symbol
+ static t_class **GetBound(const t_symbol *s) { return (t_class **)s->s_thing; }
+*/
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ /*! \defgroup FLEXT_C_THREAD Flext thread handling
+
+ @{
+ */
+
+ /*! \brief Check if current thread should terminate
+ \todo Check for currently running thread
+ */
+ bool ShouldExit() const { return shouldexit; }
+
+ //! Check if current thread is the realtime system's thread
+ bool IsSystemThread() const { pthread_t cur = pthread_self(); return pthread_equal(cur,thrid) != 0; }
+
+ /*! \brief Yield to other threads
+ \remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
+ */
+ static void ThrYield() { sched_yield(); }
+
+ typedef pthread_t thrid_t;
+
+ /*! \brief Increase/Decrease priority of a thread
+ */
+ static bool ChangePriority(int dp,thrid_t thr = GetThreadId());
+
+ /*! \brief Get priority of a thread
+ */
+ static int GetPriority(thrid_t thr = GetThreadId());
+
+ /*! \brief Set priority of a thread
+ */
+ static bool SetPriority(int p,thrid_t thr = GetThreadId());
+
+ /*! \brief Get current thread id
+ */
+ static thrid_t GetThreadId();
+
+
+#endif // FLEXT_THREADS
+
+//! @}
+
+// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+protected:
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ class thr_params
+ {
+ public:
+ thr_params(flext_base *c,int n = 1);
+ ~thr_params();
+
+ void set_any(const t_symbol *s,int argc,const t_atom *argv);
+ void set_list(int argc,const t_atom *argv);
+
+ flext_base *cl;
+ union _data {
+ bool _bool;
+ float _float;
+ int _int;
+ t_symptr _t_symptr;
+ struct { AtomAnything *args; } _any;
+ struct { AtomList *args; } _list;
+ struct { void *data; } _ext;
+ } *var;
+ };
+
+ class thr_entry
+ {
+ public:
+ thr_entry(pthread_t id = pthread_self()): thrid(id),nxt(NULL) {}
+
+ bool Is(pthread_t id = pthread_self()) const { return pthread_equal(thrid,id) != 0; }
+
+ pthread_t thrid;
+ thr_entry *nxt;
+ };
+
+ static bool StartThread(void *(*)(thr_params *p),thr_params *p,char *methname);
+ bool PushThread();
+ void PopThread();
+#endif
+
+protected:
+
+ flext_base();
+ virtual ~flext_base();
+
+// inlets and outlets
+
+ /*! \brief Set up inlets and outlets
+ \return True on successful creation of all inlets and outlets
+ */
+ virtual bool Init();
+
+ struct xlet {
+ enum type {
+ tp_none = 0,
+ tp_float,tp_int,tp_sym,tp_list,tp_any,
+ tp_LIST,tp_ANY, // use AtomList and AtomAnything
+ tp_sig
+ };
+
+ xlet(type t,const char *desc = NULL);
+ ~xlet();
+
+ char *desc;
+ type tp;
+ xlet *nxt;
+ };
+
+ /*! \addtogroup FLEXT_C_ATTR
+
+ @{
+ */
+
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(attr,a_float,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(attr,a_int,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,t_symbol *&),bool (*set)(flext_base *,t_symbol *&)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(attr,a_LIST,(methfun)get,(methfun)set); }
+
+//! @}
+
+ /*! \addtogroup FLEXT_C_INOUT
+
+ @{
+ */
+
+ unsigned long XletCode(xlet::type tp = xlet::tp_none,...); // end list with 0 (= tp_none) !!
+
+ void AddInlets(unsigned long code); // use XletCode to get code value
+ void AddInlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,inlist); }
+ void AddOutlets(unsigned long code); // use XletCode to get code value
+ void AddOutlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,outlist); }
+
+ void DescInlet(int ix,const char *desc) { DescXlet(ix,desc,inlist); }
+ void DescOutlet(int ix,const char *desc) { DescXlet(ix,desc,outlist); }
+
+//! @}
+
+// method handling
+
+ class methitem {
+ public:
+ methitem(int inlet,const t_symbol *t);
+ ~methitem();
+
+ void SetArgs(methfun fun,int argc,metharg *args);
+
+ const t_symbol *tag;
+ int inlet;
+ int argc;
+ metharg *args;
+ methfun fun;
+
+ methitem *nxt;
+ };
+
+// const methitem *FindMethItem(int inlet,const t_symbol *tag,const methitem *st);
+
+ class attritem {
+ public:
+ attritem(const t_symbol *tag,const t_symbol *gtag,metharg tp,methfun gfun,methfun sfun);
+ ~attritem();
+
+ const t_symbol *tag,*gtag;
+ metharg argtp;
+ methfun gfun,sfun;
+
+ attritem *nxt;
+ };
+
+private:
+
+ static void Setup(t_class *c);
+
+ xlet *inlist,*outlist;
+ const t_symbol *curtag;
+ int incnt,outcnt,insigs,outsigs;
+ outlet **outlets,*outattr;
+ bool distmsgs;
+
+ void AddXlet(xlet::type tp,int mult,const char *desc,xlet *&root);
+ void DescXlet(int ix,const char *desc,xlet *&root);
+
+ union t_any {
+ float ft;
+ int it;
+ t_symbol *st;
+ #ifdef PD
+ t_gpointer *pt;
+ #endif
+ void *vt;
+ };
+
+ typedef bool (*methfun_V)(flext_base *c,int argc,t_atom *argv);
+ typedef bool (*methfun_A)(flext_base *c,const t_symbol *s,int argc,t_atom *argv);
+ typedef bool (*methfun_0)(flext_base *c);
+ typedef bool (*methfun_1)(flext_base *c,t_any &);
+ typedef bool (*methfun_2)(flext_base *c,t_any &,t_any &);
+ 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);
+
+ void AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun);
+
+ 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 SetAttrib(const t_symbol *s,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); }
+
+#ifdef FLEXT_THREADS
+ bool shouldexit;
+ int thrcount;
+
+ pthread_t thrid; // the thread that created the object (the system thread)
+ ThrMutex qmutex;
+
+ thr_entry *thrhead,*thrtail;
+ ThrMutex tlmutex;
+#endif
+
+ class qmsg;
+ qmsg *qhead,*qtail;
+ t_qelem *qclk;
+#ifdef MAXMSP
+ t_clock *yclk;
+ static void YTick(flext_base *th);
+#endif
+
+ static void QTick(flext_base *th);
+ void Queue(qmsg *m);
+
+#ifdef PD
+ // proxy object (for additional inlets) stuff
+ struct px_object;
+ friend struct px_object;
+#elif defined(MAXMSP)
+ typedef object px_object;
+ static void cb_px_float(t_class *c,float f);
+ static void cb_px_int(t_class *c,int v);
+ static void cb_px_bang(t_class *c);
+
+ static void cb_px_in1(t_class *c,int v);
+ static void cb_px_in2(t_class *c,int v);
+ static void cb_px_in3(t_class *c,int v);
+ static void cb_px_in4(t_class *c,int v);
+ static void cb_px_in5(t_class *c,int v);
+ static void cb_px_in6(t_class *c,int v);
+ static void cb_px_in7(t_class *c,int v);
+ static void cb_px_in8(t_class *c,int v);
+ static void cb_px_in9(t_class *c,int v);
+#endif
+ static void cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv);
+
+ static void cb_px_ft1(t_class *c,float f);
+ static void cb_px_ft2(t_class *c,float f);
+ static void cb_px_ft3(t_class *c,float f);
+ static void cb_px_ft4(t_class *c,float f);
+ static void cb_px_ft5(t_class *c,float f);
+ static void cb_px_ft6(t_class *c,float f);
+ static void cb_px_ft7(t_class *c,float f);
+ static void cb_px_ft8(t_class *c,float f);
+ static void cb_px_ft9(t_class *c,float f);
+
+ px_object **inlets;
+
+ // callback functions
+
+ static void cb_help(t_class *c);
+
+ static void cb_loadbang(t_class *c);
+#ifdef MAXMSP
+ static void cb_assist(t_class *c,void *b,long msg,long arg,char *s);
+#endif
+};
+
+#endif
diff --git a/externals/grill/flext/source/flcwmax-thr.h b/externals/grill/flext/source/flcwmax-thr.h
new file mode 100755
index 00000000..1a9ecffb
--- /dev/null
+++ b/externals/grill/flext/source/flcwmax-thr.h
@@ -0,0 +1,20 @@
+/*
+
+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.
+
+*/
+
+// This is the prefix file for CodeWarrior projects - threaded version
+
+#ifndef _FLEXT_CW_MAX_THR_H
+#define _FLEXT_CW_MAX_THR_H
+
+#define FLEXT_THREADS
+
+#include "flcwmax.h"
+
+#endif
diff --git a/externals/grill/flext/source/flcwmax.h b/externals/grill/flext/source/flcwmax.h
new file mode 100644
index 00000000..5ef0b298
--- /dev/null
+++ b/externals/grill/flext/source/flcwmax.h
@@ -0,0 +1,26 @@
+/*
+
+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.
+
+*/
+
+/* This is the prefix file for CodeWarrior projects */
+
+#ifndef _FLEXT_CW_MAX_H
+#define _FLEXT_CW_MAX_H
+
+#include <MacHeaders.h>
+
+#define MAXMSP
+
+#if !defined(__OPTIMIZE__) || __OPTIMIZE__ == 0
+#define _DEBUG
+#endif
+
+/* #define _LOG */
+
+#endif
diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h
new file mode 100644
index 00000000..f92232f9
--- /dev/null
+++ b/externals/grill/flext/source/fldefs.h
@@ -0,0 +1,912 @@
+/*
+
+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 fldefs.h
+ \brief This file contains all #defines for actual usage
+
+*/
+
+#ifndef __FLEXT_DEFS_H
+#define __FLEXT_DEFS_H
+
+#ifdef FLEXT_GUI
+#define FLEXT_CAST dynamic_cast
+#else
+#define FLEXT_CAST static_cast
+#endif
+
+/*! \defgroup FLEXT_HEADER Flext class header
+ One (and only one!) of these definitions is compulsory for the class declaration.
+ It has to be placed somewhere in the class definition (not necessarily in a public section).
+
+ @{
+*/
+
+/*! \brief Plain flext class header
+ \param NEW_CLASS name of the current C++ class
+ \param PARENT_CLASS name of the base C++ class (e.g. flext_base or flext_dsp)
+*/
+#define FLEXT_HEADER(NEW_CLASS,PARENT_CLASS) \
+\
+FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS)
+
+/*! \brief Flext class header with setup function
+ \param NEW_CLASS name of the current C++ class
+ \param PARENT_CLASS name of the base C++ class (e.g. flext_base or flext_dsp)
+ \param SETUPFUN setup function, of type "void (*setupfn)(t_class *)"
+
+ The setup function is called after class creation. It corresponds to the
+ original "object_setup" function, apart from the
+ fact that all necessary class initializations have already been taken care by flext.
+ The setup function can e.g. be used for a message to the console upon first creation of an object.
+ The object's t_class* data can be accessed by the static function thisClass()
+*/
+#define FLEXT_HEADER_S(NEW_CLASS, PARENT_CLASS, SETUPFUN)\
+\
+FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS, SETUPFUN)
+
+
+//! @}
+
+
+
+// ====================================================================================
+
+/*! \defgroup FLEXT_NEW Flext class instantiation
+ Makes an actual instance of a class.
+*/
+
+/*! \defgroup FLEXT_NEW_DSP Flext dsp class instantiation
+ Makes an actual instance of a dsp (aka "tilde") class (with signal processing).
+*/
+
+/*! \defgroup FLEXT_LIB Flext library class instantiation
+ Makes an actual instance of a class which is part of an object library (and not stand-alone).
+*/
+
+/*! \defgroup FLEXT_LIB_DSP Flext dsp library class instantiation
+ Makes an actual instance of a dsp (aka "tilde") class with signal processing
+ which is part of an object library (and not stand-alone).
+*/
+
+// NO ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with no arguments
+ \ingroup FLEXT_NEW
+ \param NAME the object's actual name(s) as a string (like "*", "trigger", "noise~", etc.)
+ \param NEW_CLASS the object's C++ class name
+*/
+#define FLEXT_NEW(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,0,0)
+
+/*! Implementation of a flext dsp class with no arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,1,0)
+
+/*! Implementation of a flext class (part of a library) with no arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,0,1)
+
+/*! Implementation of a flext dsp class (part of a library) with no arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,1,1)
+
+
+// VARIABLE ARGUMENT LIST
+// ----------------------------------------
+
+/*! Implementation of a flext class with a variable argument list
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS,0,0) \
+
+/*! Implementation of a flext tilde class with a variable argument list
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS,1,0) \
+
+/*! Implementation of a flext class (part of a library) with a variable argument list
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS, 0,1)
+
+/*! Implementation of a flext tilde class (part of a library) with a variable argument list
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS, 1,1)
+
+
+// OBJECT NAME + VARIABLE ARGUMENT LIST
+// ----------------------------------------
+
+/*! Implementation of a flext class with its name and a variable argument list
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS,0,0) \
+
+/*! Implementation of a flext tilde class with its name and a variable argument list
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS,1,0) \
+
+/*! Implementation of a flext class (part of a library) with its name and a variable argument list
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS, 0,1)
+
+/*! Implementation of a flext tilde class (part of a library) with its name and a variable argument list
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS, 1,1)
+
+
+// ONE ARGUMENT
+// ----------------------------------------
+
+/*! Implementation of a flext class with one argument
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 0, 0,TYPE) \
+
+/*! Implementation of a flext tilde class with one argument
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 1, 0,TYPE) \
+
+/*! Implementation of a flext class (part of a library) with one argument
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 0,1,TYPE)
+
+/*! Implementation of a flext tilde class (part of a library) with one argument
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 1,1, TYPE)
+
+
+// TWO ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with 2 arguments
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 0,0, TYPE1, TYPE2) \
+
+/*! Implementation of a flext tilde class with 2 arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 1,0, TYPE1, TYPE2) \
+
+/*! Implementation of a flext class (part of a library) with 2 arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 0,1, TYPE1, TYPE2)
+
+/*! Implementation of a flext tilde class (part of a library) with 2 arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2)
+
+
+// THREE ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with 3 arguments
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 0,0, TYPE1, TYPE2, TYPE3) \
+
+/*! Implementation of a flext tilde class with 3 arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 1,0, TYPE1, TYPE2, TYPE3) \
+
+/*! Implementation of a flext class (part of a library) with 3 arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 0,1,TYPE1, TYPE2, TYPE3)
+
+/*! Implementation of a flext tilde class (part of a library) with 3 arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2, TYPE3)
+
+
+// deprecated stuff
+
+#define FLEXT_NEW_G FLEXT_NEW_V
+
+#define FLEXT_NEW_TILDE FLEXT_NEW_DSP
+#define FLEXT_NEW_TILDE_G FLEXT_NEW_DSP_V
+#define FLEXT_NEW_TILDE_1 FLEXT_NEW_DSP_1
+#define FLEXT_NEW_TILDE_2 FLEXT_NEW_DSP_2
+#define FLEXT_NEW_TILDE_3 FLEXT_NEW_DSP_3
+
+#define FLEXT_LIB_G FLEXT_LIB_V
+
+#define FLEXT_LIB_TILDE FLEXT_LIB_DSP
+#define FLEXT_LIB_TILDE_G FLEXT_LIB_DSP_V
+#define FLEXT_LIB_TILDE_1 FLEXT_LIB_DSP_1
+#define FLEXT_LIB_TILDE_2 FLEXT_LIB_DSP_2
+#define FLEXT_LIB_TILDE_3 FLEXT_LIB_DSP_3
+
+
+
+
+// ====================================================================================
+
+
+/*! \defgroup FLEXT_CALLBACK Flext callbacks
+
+ @{
+*/
+
+//! Set up a method callback with no arguments
+#define FLEXT_CALLBACK(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(); return true; }
+
+//! Set up a method callback for an anything argument
+#define FLEXT_CALLBACK_A(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,const t_symbol *s,int argc,t_atom *argv) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(s,argc,argv); return true; }
+
+//! Set up a method callback for a variable argument list
+#define FLEXT_CALLBACK_V(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(argc,argv); return true; }
+
+//! Set up a method callback for a data package (void *) argument
+#define FLEXT_CALLBACK_X(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(data); return true; }
+
+//! Set up a method callback for a boolean argument
+#define FLEXT_CALLBACK_B(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1 != 0); return true; }
+
+//! Set up a method callback for 1 argument
+#define FLEXT_CALLBACK_1(M_FUN,TP1) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1); return true; }
+
+//! Set up a method callback for 2 arguments
+#define FLEXT_CALLBACK_2(M_FUN,TP1,TP2) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2); return true; }
+
+//! Set up a method callback for 3 arguments
+#define FLEXT_CALLBACK_3(M_FUN,TP1,TP2,TP3) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3); return true; }
+
+//! Set up a method callback for 4 arguments
+#define FLEXT_CALLBACK_4(M_FUN,TP1,TP2,TP3,TP4) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3,arg4); return true; }
+
+//! Set up a method callback for 5 arguments
+#define FLEXT_CALLBACK_5(M_FUN,TP1,TP2,TP3,TP4,TP5) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4,TP5 &arg5) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3,arg4,arg5); return true; }
+
+
+// Shortcuts
+
+//! Set up a method callback for 1 float argument
+#define FLEXT_CALLBACK_F(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,float)
+
+//! Set up a method callback for 2 float arguments
+#define FLEXT_CALLBACK_FF(M_FUN) \
+\
+FLEXT_CALLBACK_2(M_FUN,float,float)
+
+//! Set up a method callback for 3 float arguments
+#define FLEXT_CALLBACK_FFF(M_FUN) \
+\
+FLEXT_CALLBACK_3(M_FUN,float,float,float)
+
+//! Set up a method callback for 1 integer argument
+#define FLEXT_CALLBACK_I(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,int)
+
+//! Set up a method callback for 2 integer arguments
+#define FLEXT_CALLBACK_II(M_FUN) \
+\
+FLEXT_CALLBACK_2(M_FUN,int,int)
+
+//! Set up a method callback for 3 integer arguments
+#define FLEXT_CALLBACK_III(M_FUN) \
+\
+FLEXT_CALLBACK_3(M_FUN,int,int,int)
+
+//! Set up a method callback for 1 symbol argument
+#define FLEXT_CALLBACK_S(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,t_symptr)
+
+
+// deprecated
+#define FLEXT_CALLBACK_G FLEXT_CALLBACK_V
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_THREAD Flext threads
+
+ @{
+*/
+
+#ifdef FLEXT_THREADS
+
+//! Set up a threaded method callback with no arguments
+#define FLEXT_THREAD(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) { \
+ thr_params *p = new thr_params(c); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for an anything argument
+#define FLEXT_THREAD_A(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,const t_symbol *s,int argc,t_atom *argv) { \
+ thr_params *p = new thr_params(c); p->set_any(s,argc,argv); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ AtomAnything *args = p->var[0]._any.args; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(args->Header(),args->Count(),args->Atoms()); \
+ th->PopThread(); \
+ } \
+ delete args; \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for a variable argument list
+#define FLEXT_THREAD_V(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) { \
+ thr_params *p = new thr_params(c); p->set_list(argc,argv); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ AtomList *args = p->var[0]._list.args; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(args->Count(),args->Atoms()); \
+ th->PopThread(); \
+ } \
+ delete args; \
+ return NULL; \
+}
+
+/*! \brief Set up a threaded method callback for an arbitrary data struct
+ \note Data is pure... no destructor is called upon delete
+*/
+#define FLEXT_THREAD_X(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) { \
+ thr_params *p = new thr_params(c); p->var[0]._ext.data = data; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ void *data = p->var[0]._ext.data; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(data); \
+ th->PopThread(); \
+ } \
+ delete data; \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for a boolean argument
+#define FLEXT_THREAD_B(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) { \
+ thr_params *p = new thr_params(c); p->var[0]._bool = arg1 != 0; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ bool b = p->var[0]._bool; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(b); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 1 argument
+#define FLEXT_THREAD_1(M_FUN,TP1) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) { \
+ thr_params *p = new thr_params(c,1); \
+ p->var[0]._ ## TP1 = arg1; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 2 arguments
+#define FLEXT_THREAD_2(M_FUN,TP1,TP2) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) { \
+ thr_params *p = new thr_params(c,2); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP1 v2 = p->var[1]._ ## TP2; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 3 arguments
+#define FLEXT_THREAD_3(M_FUN,TP1,TP2,TP3) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) { \
+ thr_params *p = new thr_params(c,3); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 4 arguments
+#define FLEXT_THREAD_4(M_FUN,TP1,TP2,TP3,TP4) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4) { \
+ thr_params *p = new thr_params(c,4); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ p->var[3]._ ## TP4 = arg4; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ const TP4 v4 = p->var[3]._ ## TP4; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3,v4); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 5 arguments
+#define FLEXT_THREAD_5(M_FUN,TP1,TP2,TP3,TP4,TP5) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4,TP5 &arg5) { \
+ thr_params *p = new thr_params(c,5); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ p->var[3]._ ## TP4 = arg4; \
+ p->var[4]._ ## TP5 = arg5; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ const TP4 v4 = p->var[3]._ ## TP4; \
+ const TP5 v5 = p->var[4]._ ## TP5; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3,v4,v5); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+
+//! Shortcuts
+
+//! Set up a threaded method callback for 1 float argument
+#define FLEXT_THREAD_F(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,float)
+
+//! Set up a threaded method callback for 2 float arguments
+#define FLEXT_THREAD_FF(M_FUN) \
+\
+FLEXT_THREAD_2(M_FUN,float,float)
+
+//! Set up a threaded method callback for 3 float arguments
+#define FLEXT_THREAD_FFF(M_FUN) \
+\
+FLEXT_THREAD_3(M_FUN,float,float,float)
+
+//! Set up a threaded method callback for 1 integer argument
+#define FLEXT_THREAD_I(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,int)
+
+//! Set up a threaded method callback for 2 integer arguments
+#define FLEXT_THREAD_II(M_FUN) \
+\
+FLEXT_THREAD_2(M_FUN,int,int)
+
+//! Set up a threaded method callback for 3 integer arguments
+#define FLEXT_THREAD_III(M_FUN) \
+\
+FLEXT_THREAD_3(M_FUN,int,int,int)
+
+//! Set up a threaded method callback for 1 symbol argument
+#define FLEXT_THREAD_S(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,t_symptr)
+
+// deprecated
+#define FLEXT_THREAD_G FLEXT_THREAD_V
+
+#endif // FLEXT_THREAD
+
+//! @}
+
+
+
+// ====================================================================================
+
+
+
+/*! \defgroup FLEXT_ADDMETHOD Add flext methods
+ These should be the used in the class' constructor
+
+ @{
+*/
+
+//! Enable list element distribution over inlets (if no better handler found)
+#define FLEXT_ADDDIST() \
+\
+SetDist(true)
+
+//! Add a method handler for bang
+#define FLEXT_ADDBANG(IX,M_FUN) \
+\
+AddMethod(IX,"bang",FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with no arguments
+#define FLEXT_ADDMETHOD(IX,M_FUN) \
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with a (variable argument) list
+#define FLEXT_ADDMETHOD_V(IX,M_FUN) \
+\
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with an anything argument
+#define FLEXT_ADDMETHOD_A(IX,M_FUN) \
+\
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a a handler for a method with implicit arguments
+#define FLEXT_ADDMETHOD_(IX,M_TAG,M_FUN) \
+\
+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)
+
+//! 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)
+
+//! 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)
+
+//! 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)
+
+//! 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)
+
+//! 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)
+
+
+// Shortcuts
+
+//! Add a handler for a method with a boolean argument
+#define FLEXT_ADDMETHOD_B(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,bool)
+
+//! Add a handler for a method with 1 float argument
+#define FLEXT_ADDMETHOD_F(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,float)
+
+//! Add a handler for a method with 2 float arguments
+#define FLEXT_ADDMETHOD_FF(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,float,float)
+
+//! Add a handler for a method with 3 float arguments
+#define FLEXT_ADDMETHOD_FFF(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,float,float,float)
+
+//! Add a handler for a method with 1 integer argument
+#define FLEXT_ADDMETHOD_I(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,int)
+
+//! Add a handler for a method with 2 integer arguments
+#define FLEXT_ADDMETHOD_II(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,int,int)
+
+//! Add a handler for a method with 3 integer arguments
+#define FLEXT_ADDMETHOD_III(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,int,int,int)
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_CALLMETHOD Call flext methods manually
+ These can only be used in class member functions!
+
+ @{
+*/
+
+//! Call a (already defined) method with no arguments
+#define FLEXT_CALLMETHOD(M_FUN) \
+\
+FLEXT_CALL_PRE(M_FUN)(this)
+
+//! Call a (already defined) method with variable list arguments
+#define FLEXT_CALLMETHOD_V(M_FUN,ARGC,ARGV) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARGC,ARGV)
+
+//! Call a (already defined) method with anything arguments
+#define FLEXT_CALLMETHOD_A(M_FUN,HDR,ARGC,ARGV) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,HDR,ARGC,ARGV)
+
+//! Call a (already defined) method with a data package (void *)
+#define FLEXT_CALLMETHOD_X(M_FUN,DATA) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,DATA)
+
+//! Call a (already defined) method with 1 enum type argument
+#define FLEXT_CALLMETHOD_E(M_FUN,ARG) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG)
+
+//! Call a (already defined) method with 1 argument
+#define FLEXT_CALLMETHOD_1(M_FUN,ARG) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG)
+
+//! Call a (already defined) method with 2 arguments
+#define FLEXT_CALLMETHOD_2(M_FUN,ARG1,ARG2) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2)
+
+//! Call a (already defined) method with 3 arguments
+#define FLEXT_CALLMETHOD_3(M_FUN,ARG1,ARG2,ARG3) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3)
+
+//! Call a (already defined) method with 4 arguments
+#define FLEXT_CALLMETHOD_4(M_FUN,ARG1,ARG2,ARG3,ARG4) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3,ARG4)
+
+//! Call a (already defined) method with 5 arguments
+#define FLEXT_CALLMETHOD_5(M_FUN,ARG1,ARG2,ARG3,ARG4,ARG5) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3,ARG4,ARG5)
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_DEFATTR flext functions for attribute definition
+
+ @{
+*/
+
+#define FLEXT_CALLSET_(FUN,TP) \
+static bool FLEXT_SET_PRE(FUN)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(arg); return true; }
+
+#define FLEXT_CALLGET_(FUN,TP) \
+static bool FLEXT_GET_PRE(FUN)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(arg); return true; }
+
+#define FLEXT_ATTRSET_(VAR,TP) \
+static bool FLEXT_SET_PRE(VAR)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->VAR = arg; return true; }
+
+#define FLEXT_ATTRGET_(VAR,TP) \
+static bool FLEXT_GET_PRE(VAR)(flext_base *c,TP &arg) \
+{ arg = FLEXT_CAST<thisType *>(c)->VAR; return true; }
+
+#define FLEXT_CALLSET_F(SFUN) FLEXT_CALLSET_(SFUN,float)
+#define FLEXT_CALLSET_I(SFUN) FLEXT_CALLSET_(SFUN,int)
+#define FLEXT_CALLSET_S(SFUN) FLEXT_CALLSET_(SFUN,t_symptr)
+
+#define FLEXT_CALLSET_V(FUN) \
+static bool FLEXT_SET_PRE(FUN)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(*arg); return true; }
+
+#define FLEXT_CALLGET_F(GFUN) FLEXT_CALLGET_(GFUN,float)
+#define FLEXT_CALLGET_I(GFUN) FLEXT_CALLGET_(GFUN,int)
+#define FLEXT_CALLGET_S(GFUN) FLEXT_CALLGET_(GFUN,t_symptr)
+
+#define FLEXT_CALLGET_V(FUN) \
+static bool FLEXT_GET_PRE(FUN)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(*arg); return true; }
+
+#define FLEXT_CALLXFER_F(GFUN,SFUN) FLEXT_CALLGET_F(GFUN) FLEXT_CALLSET_F(SFUN)
+#define FLEXT_CALLXFER_I(GFUN,SFUN) FLEXT_CALLGET_I(GFUN) FLEXT_CALLSET_I(SFUN)
+#define FLEXT_CALLXFER_S(GFUN,SFUN) FLEXT_CALLGET_S(GFUN) FLEXT_CALLSET_S(SFUN)
+#define FLEXT_CALLXFER_V(GFUN,SFUN) FLEXT_CALLGET_V(GFUN) FLEXT_CALLSET_V(SFUN)
+
+#define FLEXT_ATTRSET_F(VAR) FLEXT_ATTRSET_(VAR,float)
+#define FLEXT_ATTRSET_I(VAR) FLEXT_ATTRSET_(VAR,int)
+#define FLEXT_ATTRSET_S(VAR) FLEXT_ATTRSET_(VAR,t_symptr)
+
+#define FLEXT_ATTRSET_V(VAR) \
+static bool FLEXT_SET_PRE(VAR)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->VAR = *arg; return true; }
+
+#define FLEXT_ATTRGET_F(VAR) FLEXT_ATTRGET_(VAR,float)
+#define FLEXT_ATTRGET_I(VAR) FLEXT_ATTRGET_(VAR,int)
+#define FLEXT_ATTRGET_S(VAR) FLEXT_ATTRGET_(VAR,t_symptr)
+
+#define FLEXT_ATTRGET_V(VAR) \
+static bool FLEXT_GET_PRE(VAR)(flext_base *c,AtomList *&arg) \
+{ *arg = FLEXT_CAST<thisType *>(c)->VAR; return true; }
+
+#define FLEXT_ATTRXFER_F(VAR) FLEXT_ATTRGET_F(VAR) FLEXT_ATTRSET_F(VAR)
+#define FLEXT_ATTRXFER_I(VAR) FLEXT_ATTRGET_I(VAR) FLEXT_ATTRSET_I(VAR)
+#define FLEXT_ATTRXFER_S(VAR) FLEXT_ATTRGET_S(VAR) FLEXT_ATTRSET_S(VAR)
+#define FLEXT_ATTRXFER_V(VAR) FLEXT_ATTRGET_V(VAR) FLEXT_ATTRSET_V(VAR)
+
+//! @}
+
+/*! \defgroup FLEXT_ADDATTR flext methods for defining attributes
+ These can only be used in class member functions!
+
+ @{
+*/
+
+#define FLEXT_ADDATTR_GET(NAME,GFUN) AddAttrib(NAME,(FLEXT_GET_PRE(GFUN)),NULL)
+#define FLEXT_ADDATTR_SET(NAME,SFUN) AddAttrib(NAME,NULL,(FLEXT_SET_PRE(SFUN)))
+#define FLEXT_ADDATTRIB(NAME,FUN) AddAttrib(NAME,(FLEXT_GET_PRE(FUN)),(FLEXT_SET_PRE(FUN)))
+
+//! @}
+
+
+
+
+#endif // __FLEXT_DEFS_H
diff --git a/externals/grill/flext/source/fldoxygen.h b/externals/grill/flext/source/fldoxygen.h
new file mode 100644
index 00000000..bae97b44
--- /dev/null
+++ b/externals/grill/flext/source/fldoxygen.h
@@ -0,0 +1,22 @@
+#ifndef __FLEXT_DOXYGEN_H
+#define __FLEXT_DOXYGEN_H
+
+/*! \file fldoxygen.h
+ \brief Doxygen definitions
+ \remark There is no code in here, just documentation stuff.
+*/
+
+/*! \mainpage flext - C++ layer for cross-platform development of PD and Max/MSP objects
+
+ \section intro Introduction
+
+ This is the introduction
+
+ \section install Installation
+
+ \subsection step1 Step 1: Opening the box
+
+ etc...
+*/
+
+#endif
diff --git a/externals/grill/flext/source/fldsp.cpp b/externals/grill/flext/source/fldsp.cpp
new file mode 100644
index 00000000..fc5db717
--- /dev/null
+++ b/externals/grill/flext/source/fldsp.cpp
@@ -0,0 +1,119 @@
+/*
+
+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 fldsp.cpp
+ \brief Implementation of the flext dsp base class.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+
+
+
+// === flext_dsp ==============================================
+
+void flext_dsp::Setup(t_class *c)
+{
+#ifdef PD
+// CLASS_MAINSIGNALIN(c,flext_hdr,defsig);
+#elif defined(MAXMSP)
+// dsp_initclass();
+ dsp_initboxclass();
+#endif
+
+ add_dsp(c,cb_dsp);
+#ifndef MAXMSP
+ add_method1(c,cb_enable,"enable",A_FLINT);
+#endif
+}
+
+flext_dsp::flext_dsp():
+#ifndef MAXMSP
+ dspon(true),
+#endif
+ srate(sys_getsr()), // should we set it?
+ blksz(sys_getblksize()),
+#ifdef PD
+ chnsin(sys_get_inchannels()),
+ chnsout(sys_get_outchannels()),
+#else // MAXMSP
+ chnsin(sys_getch()),
+ chnsout(sys_getch()),
+#endif
+ invecs(NULL),outvecs(NULL)
+{}
+
+
+flext_dsp::~flext_dsp()
+{
+ if(invecs) delete[] invecs;
+ if(outvecs) delete[] outvecs;
+}
+
+
+t_int *flext_dsp::dspmeth(t_int *w)
+{
+ flext_dsp *obj = (flext_dsp *)w[1];
+#ifdef MAXMSP
+ if(!obj->thisHdr()->z_disabled)
+#else
+ if(obj->dspon)
+#endif
+ obj->m_signal((int)w[2],obj->invecs,obj->outvecs);
+ return w+3;
+}
+
+void flext_dsp::m_dsp(int /*n*/,t_sample *const * /*insigs*/,t_sample *const * /*outsigs*/) {}
+
+void flext_dsp::m_signal(int n,t_sample *const * /*insigs*/,t_sample *const *outsigs)
+{
+ for(int i = 0; i < CntOutSig(); ++i)
+ memset(outsigs[i],0,n*sizeof(*outsigs[i]));
+}
+
+void flext_dsp::cb_dsp(t_class *c,t_signal **sp)
+{
+ flext_dsp *obj = thisObject(c);
+
+ // store current dsp parameters
+ obj->srate = sp[0]->s_sr;
+ obj->blksz = sp[0]->s_n; // is this guaranteed to be the same as sys_getblksize() ?
+
+#ifdef PD
+ obj->chnsin = sys_get_inchannels();
+ obj->chnsout = sys_get_outchannels();
+#else // MAXMSP
+ obj->chnsin = obj->chnsout = sys_getch();
+#endif
+
+ // store in and out signal vectors
+ int i,in = obj->CntInSig(),out = obj->CntOutSig();
+ if(obj->invecs) delete[] obj->invecs;
+ obj->invecs = new t_sample *[in];
+ for(i = 0; i < in; ++i) obj->invecs[i] = sp[i]->s_vec;
+
+ if(obj->outvecs) delete[] obj->outvecs;
+ obj->outvecs = new t_sample *[out];
+ for(i = 0; i < out; ++i) obj->outvecs[i] = sp[in+i]->s_vec;
+
+ // with the following call derived classes can do their eventual DSP setup
+ obj->m_dsp(sp[0]->s_n,obj->invecs,obj->outvecs);
+
+ // set the DSP function
+ dsp_add((t_dspmethod)dspmeth,2,obj,sp[0]->s_n);
+}
+
+#ifndef MAXMSP
+void flext_dsp::cb_enable(t_class *c,t_flint on) { thisObject(c)->m_enable(on != 0); }
+void flext_dsp::m_enable(bool en) { dspon = en; }
+#endif
+
+
diff --git a/externals/grill/flext/source/fldsp.h b/externals/grill/flext/source/fldsp.h
new file mode 100644
index 00000000..70c88745
--- /dev/null
+++ b/externals/grill/flext/source/fldsp.h
@@ -0,0 +1,140 @@
+/*
+
+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 fldsp.h
+ \brief Declares the flext dsp class
+
+*/
+
+#ifndef __FLDSP_H
+#define __FLDSP_H
+
+// include the header file declaring the base classes
+#include "flext.h"
+
+
+// === flext_dsp ==================================================
+
+/*! \brief Flext dsp enabled base object
+*/
+class flext_dsp:
+ public flext_base
+{
+ FLEXT_HEADER_S(flext_dsp,flext_base,Setup)
+
+public:
+
+/*! \defgroup FLEXT_C_DSP Flext basic dsp functionality
+
+ @{
+*/
+
+ //! returns current sample rate
+ float Samplerate() const { return srate; }
+
+ //! returns current block (aka vector) size
+ int Blocksize() const { return blksz; }
+
+ /*! \brief returns number of audio system input channels
+ \bug Doesn't work in Max/MSP - is always 0
+ */
+ int ChannelsIn() const { return chnsin; }
+
+ /*! \brief returns number of audio system output channels
+ \bug Doesn't work in Max/MSP - is always 0
+ */
+ int ChannelsOut() const { return chnsout; }
+
+//! @}
+
+
+// --- inheritable virtual methods --------------------------------
+
+/*! \defgroup FLEXT_C_VIRTUAL_DSP Flext virtual dsp functions
+
+ @{
+*/
+ /*! \brief Called on every dsp init.
+ \note Don't expect any valid data in the signal vectors!
+
+ \param n: frames (aka samples) in one signal vector
+ \param insigs: array of input vectors (get number with function CntInSig())
+ \param outsigs: array of output vectors (get number with function CntOutSig())
+ */
+ virtual void m_dsp(int n,t_sample *const *insigs,t_sample *const *outsigs);
+
+ /*! \brief Called with every signal vector - here you do the dsp calculation
+
+ \param n: frames (aka samples) in one signal vector
+ \param insigs: array of input vectors (get number with function CntInSig())
+ \param outsigs: array of output vectors (get number with function CntOutSig())
+ */
+ virtual void m_signal(int n,t_sample *const *insigs,t_sample *const *outsigs);
+
+#ifndef MAXMSP
+ /*! \brief called with "enable" message: pauses/resumes dsp
+ \note PD only - implicitely defined in MaxMSP
+ */
+ virtual void m_enable(bool on);
+#endif
+
+//! @}
+
+
+/*! \defgroup FLEXT_C_INOUT_DSP Flext dsp in-/outlet functions
+ \note These must be called in the class' constructor
+
+ @{
+*/
+// --- inlet/outlet stuff -----------------------------------------
+
+ /*! \brief Add signal inlet(s)
+ \param m Number of inlets to add
+ */
+ void AddInSignal(int m = 1) { AddInlet(xlet::tp_sig,m); }
+
+ /*! \brief Add signal outlet(s)
+ \param m Number of inlets to add
+ */
+ void AddOutSignal(int m = 1) { AddOutlet(xlet::tp_sig,m); }
+
+//! @}
+
+
+protected:
+
+ flext_dsp();
+ virtual ~flext_dsp();
+
+private:
+
+ // not static, could be different in different patchers..
+ float srate;
+ int blksz;
+ int chnsin,chnsout;
+
+ // setup function
+ static void Setup(t_class *c);
+
+ // callback functions
+
+ static void cb_dsp(t_class *c,t_signal **s);
+#ifndef MAXMSP
+ static void cb_enable(t_class *c,t_flint on);
+ bool dspon;
+#endif
+
+ // dsp stuff
+
+ static t_int *dspmeth(t_int *w);
+ t_sample **invecs,**outvecs;
+};
+
+#endif
diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp
new file mode 100644
index 00000000..5ed852c3
--- /dev/null
+++ b/externals/grill/flext/source/flext.cpp
@@ -0,0 +1,748 @@
+/*
+
+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 flext.cpp
+ \brief Implementation of the flext base class.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+#include <stdarg.h>
+
+
+// === proxy class for flext_base ============================
+
+#ifdef 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 defined(MAXMSP)
+
+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)
+
+#endif // MAXMSP
+
+
+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 ============================================
+
+bool flext_base::compatibility = true;
+
+flext_base::flext_base():
+ inlist(NULL),outlist(NULL),
+ incnt(0),outcnt(0),
+ insigs(0),outsigs(0),
+ curtag(NULL),
+ outlets(NULL),inlets(NULL),outattr(NULL),
+ methhead(NULL),attrhead(NULL),attrcnt(0),
+ distmsgs(false)
+{
+ LOG1("%s - flext logging is on",thisName());
+
+#ifdef FLEXT_THREADS
+ thrid = pthread_self();
+
+ shouldexit = false;
+ thrhead = thrtail = NULL;
+#endif
+ qhead = qtail = NULL;
+ qclk = (t_qelem *)(qelem_new(this,(t_method)QTick));
+#ifdef MAXMSP
+ yclk = (t_clock *)(clock_new(this,(t_method)YTick));
+#endif
+
+ AddMethod(0,"getattributes",(methfun)cb_ListAttrib);
+}
+
+flext_base::~flext_base()
+{
+#ifdef FLEXT_THREADS
+ // wait for thread termination
+ shouldexit = true;
+ for(int wi = 0; thrhead && wi < 100; ++wi) Sleep(0.01f);
+
+#ifdef PD
+ qmutex.Lock(); // Lock message queue
+ tlmutex.Lock();
+ // timeout -> hard termination
+ while(thrhead) {
+ thr_entry *t = thrhead;
+ if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName());
+ thrhead = t->nxt;
+ t->nxt = NULL; delete t;
+ }
+ tlmutex.Unlock();
+ qmutex.Unlock();
+#else
+#pragma message ("No tread cancelling")
+#endif
+
+#endif
+
+ // send remaining pending messages
+ while(qhead) QTick(this);
+ qelem_free((t_qelem *)qclk);
+#ifdef MAXMSP
+ clock_free((object *)yclk);
+#endif
+
+ if(inlist) delete inlist;
+ if(outlist) delete outlist;
+ if(outlets) delete[] outlets;
+
+ if(inlets) {
+ for(int ix = 0; ix < incnt; ++ix)
+ if(inlets[ix]) {
+#ifdef PD
+ pd_free(&inlets[ix]->obj.ob_pd);
+#elif defined(MAXMSP)
+ freeobject((object *)inlets[ix]);
+#endif
+ }
+ delete[] inlets;
+ }
+
+#ifdef MAXMSP
+// if(insigs) dsp_free(thisHdr());
+ if(insigs) dsp_freebox(thisHdr());
+#endif
+
+ if(methhead) delete methhead;
+ if(attrhead) delete attrhead;
+}
+
+
+bool flext_base::Init()
+{
+// if(!flext_obj::Init()) return false;
+
+ bool ok = true;
+
+ incnt = insigs = 0;
+
+ if(inlets) {
+ for(int ix = 0; ix < incnt; ++ix)
+ if(inlets[ix]) {
+#ifdef PD
+ pd_free(&inlets[ix]->obj.ob_pd);
+#elif defined(MAXMSP)
+ freeobject(inlets[ix]);
+#endif
+ }
+ delete[] inlets;
+ inlets = NULL;
+ }
+
+ 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
+#ifdef 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 defined(MAXMSP)
+ {
+ 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
+ }
+#endif
+
+ delete[] list;
+ }
+
+ if(outlets) { delete[] outlets; outlets = NULL; }
+ outcnt = outsigs = 0;
+
+ 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;
+
+ outlets = new outlet *[outcnt];
+
+ // type info is now in list array
+#ifdef PD
+ for(int ix = 0; ix < outcnt; ++ix)
+#elif defined(MAXMSP)
+ for(int ix = outcnt-1; ix >= 0; --ix)
+#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 _DEBUG
+ default:
+ ERRINTERNAL();
+ ok = false;
+#endif
+ }
+ }
+
+ delete[] list;
+ }
+
+ if(procattr)
+ // attribute dump outlet is the last one
+ outattr = (outlet *)newout_anything(&x_obj->obj);
+
+ return ok;
+}
+
+void flext_base::Setup(t_class *c)
+{
+ add_method(c,cb_help,"help");
+ add_loadbang(c,cb_loadbang);
+#ifdef MAXMSP
+ add_assist(c,cb_assist);
+#endif
+
+ // proxy for extra inlets
+#ifdef 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 defined(MAXMSP)
+ 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);
+#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);
+}
+
+void flext_base::cb_help(t_class *c) { thisObject(c)->m_help(); }
+
+void flext_base::cb_loadbang(t_class *c) { thisObject(c)->m_loadbang(); }
+#ifdef MAXMSP
+void flext_base::cb_assist(t_class *c,void * /*b*/,long msg,long arg,char *s) { thisObject(c)->m_assist(msg,arg,s); }
+#endif
+
+void flext_base::m_help()
+{
+ // This should better be overloaded
+ post("%s (using flext " FLEXT_VERSTR ") - compiled on %s %s",thisName(),__DATE__,__TIME__);
+}
+
+
+bool flext_base::m_methodmain(int inlet,const t_symbol *s,int argc,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,argv);
+ }
+ else if(m->argc == 1 && m->args[0] == a_any) {
+ ret = ((methfun_A)m->fun)(this,s,argc,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;
+ }
+#ifdef 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,argv);
+ }
+ }
+
+#ifdef MAXMSP
+ // 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
+#ifdef MAXMSP
+ || s == sym_int
+#endif
+ )) {
+ t_atom list;
+ if(s == sym_float)
+ SetFloat(list,GetFloat(argv[0]));
+#ifdef MAXMSP
+ 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;
+ }
+
+ // 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;
+#ifdef 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,t_atom *argv)
+{
+//#ifdef _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):
+ inlet(in),tag(t),
+ fun(NULL),
+ argc(0),args(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));
+}
+
+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 _DEBUG
+ if(a == a_list && ix > 0) {
+ ERRINTERNAL();
+ }
+#endif
+#ifdef 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);
+}
+
+
diff --git a/externals/grill/flext/source/flext.h b/externals/grill/flext/source/flext.h
new file mode 100644
index 00000000..fd99f253
--- /dev/null
+++ b/externals/grill/flext/source/flext.h
@@ -0,0 +1,45 @@
+/*
+
+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 flext.h
+ \brief This is the main flext include file.
+
+ The basic definitions are set here and the necessary header files are included
+*/
+
+#ifndef __FLEXT_H
+#define __FLEXT_H
+
+
+/*! \defgroup FLEXT_GLOBAL Flext global definitions
+ @{
+*/
+
+//! \brief flext version number
+#define FLEXT_VERSION 400
+
+//! \brief flext version string
+#define FLEXT_VERSTR "0.4.0pre"
+
+//! @}
+
+
+// include all the flext interface definitions
+#include "fldefs.h"
+
+// include the basic flext object classes
+#include "flclass.h"
+
+// include the flext dsp class
+#include "fldsp.h"
+
+#endif // FLEXT_H
+
+
diff --git a/externals/grill/flext/source/flinternal.h b/externals/grill/flext/source/flinternal.h
new file mode 100644
index 00000000..20989b1b
--- /dev/null
+++ b/externals/grill/flext/source/flinternal.h
@@ -0,0 +1,111 @@
+/*
+
+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 flinternal.h
+ \brief Definitions for internal flext usage
+ \internal
+
+ Here, a few shortcuts for common MaxMSP or PD library calls and type definitions
+ are declared
+*/
+
+#ifndef __FLEXT_INTERNALS_H
+#define __FLEXT_INTERNALS_H
+
+#include "flstdc.h"
+
+
+#ifdef PD
+
+#define object_new(clss) pd_new(clss)
+#define object_free(obj) pd_free(&(obj).ob_pd)
+
+
+
+#define add_dsp(clss,meth) class_addmethod(clss, (t_method)meth,gensym("dsp"),A_NULL)
+#define add_bang(clss,meth) class_addbang(clss, (t_method)meth)
+#define add_float(clss,meth) class_addfloat(clss, (t_method)meth)
+#define add_floatn(clss,meth,n) class_addmethod(clss, (t_method)meth,gensym("ft" #n),A_FLOAT,A_NULL)
+#define add_flint(clss,meth) class_addfloat(clss, (t_method)meth)
+#define add_flintn(clss,meth,n) class_addmethod(clss, (t_method)meth,gensym("ft" #n),A_FLOAT,A_NULL)
+#define add_method(clss,meth,text) class_addmethod(clss, (t_method)meth, gensym(text), A_NULL)
+#define add_methodG(clss,meth,text) class_addmethod(clss, (t_method)meth, gensym(text), A_GIMME,A_NULL)
+#define add_method1(clss,meth,text,a1) class_addmethod(clss, (t_method)meth, gensym(text), a1,A_NULL)
+#define add_method2(clss,meth,text,a1,a2) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,A_NULL)
+#define add_method3(clss,meth,text,a1,a2,a3) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,A_NULL)
+#define add_method4(clss,meth,text,a1,a2,a3,a4) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,a4,A_NULL)
+#define add_method5(clss,meth,text,a1,a2,a3,a5) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,a4,a5,A_NULL)
+#define add_loadbang(clss,meth) class_addmethod(clss,(t_method)meth, gensym("loadbang"), A_CANT, A_NULL)
+#define add_anything(clss,meth) class_addanything(clss,meth)
+
+
+#define newout_signal(clss) outlet_new(clss,&s_signal)
+#define newout_float(clss) outlet_new(clss,&s_float)
+#define newout_flint(clss) outlet_new(clss,&s_float)
+#define newout_list(clss) outlet_new(clss,&s_list)
+#define newout_symbol(clss) outlet_new(clss,&s_symbol)
+#define newout_anything(clss) outlet_new(clss,&s_anything)
+
+#define outlet_flint(o,v) outlet_float(o,(float)(v))
+
+typedef t_perfroutine t_dspmethod;
+
+#define qelem_new clock_new
+#define qelem_free clock_free
+#define qelem_set clock_set
+#define qelem_unset clock_unset
+
+#elif defined(MAXMSP)
+
+/*
+typedef void _inlet;
+typedef _inlet t_inlet;
+*/
+
+typedef void t_outlet;
+//typedef _outlet t_outlet;
+
+#define object_new(clss) pd_new(clss)
+#define object_free(obj) freeobject((object *)obj)
+
+#define add_dsp(clss,meth) addmess((method)meth,"dsp",A_CANT,A_NOTHING)
+#define add_bang(clss,meth) addbang((method)meth)
+#define add_float(clss,meth) addfloat((method)meth)
+#define add_floatn(clss,meth,n) addftx((method)meth,n)
+#define add_flint(clss,meth) addint((method)meth)
+#define add_flintn(clss,meth,n) addinx((method)meth,n)
+#define add_method(clss,meth,text) addmess((method)meth, text, A_NOTHING)
+#define add_methodG(clss,meth,text) addmess((method)meth, text, A_GIMME,A_NOTHING)
+#define add_method1(clss,meth,text,a1) addmess((method)meth, text, a1,A_NOTHING)
+#define add_method2(clss,meth,text,a1,a2) addmess((method)meth, text, a1,a2,A_NOTHING)
+#define add_method3(clss,meth,text,a1,a2,a3) addmess((method)meth, text, a1,a2,a3,A_NOTHING)
+#define add_method4(clss,meth,text,a1,a2,a3,a4) addmess((method)meth, text, a1,a2,a3,a4,A_NOTHING)
+#define add_method5(clss,meth,text,a1,a2,a3,a5) addmess((method)meth, text, a1,a2,a3,a4,a5,A_NOTHING)
+#define add_anything(clss,meth) addmess((method)meth, "anything", A_GIMME,A_NOTHING)
+
+#define add_assist(clss,meth) addmess((method)meth, "assist", A_CANT, A_NULL)
+#define add_loadbang(clss,meth) addmess((method)meth, "loadbang", A_CANT, A_NULL)
+
+#define newout_signal(clss) outlet_new(clss,"signal")
+#define newout_float(clss) outlet_new(clss,"float")
+#define newout_flint(clss) outlet_new(clss,"int")
+#define newout_list(clss) outlet_new(clss,"list")
+#define newout_symbol(clss) outlet_new(clss,"symbol")
+#define newout_anything(clss) outlet_new(clss,"anything")
+
+#define outlet_flint(o,v) outlet_int(o,(int)(v))
+#define outlet_symbol(o,s) outlet_anything(o,s,0,NULL)
+
+typedef t_perfroutine t_dspmethod;
+
+#endif
+
+
+#endif
diff --git a/externals/grill/flext/source/fllib.cpp b/externals/grill/flext/source/fllib.cpp
new file mode 100755
index 00000000..eee94ce5
--- /dev/null
+++ b/externals/grill/flext/source/fllib.cpp
@@ -0,0 +1,386 @@
+/*
+
+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.
+
+*/
+
+// Code for handling of object creation functions
+
+#include "flext.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#define ALIASDEL ','
+
+#define ALIASSLASHES ":/\\"
+#ifdef MAXMSP
+ #define ALIASSLASH ':'
+#elif defined(NT)
+ #define ALIASSLASH '/'
+#else
+ #define ALIASSLASH '/'
+#endif
+
+//! Extract space-delimited words from a string
+static const char *extract(const char *name,int ix = 0)
+{
+ static char tmp[1024];
+ const char *n = name;
+
+ const char *del = strchr(name,ALIASDEL);
+
+ if(del) {
+ if(ix < 0) {
+ char *t = tmp;
+ while(n < del && (isspace(*n) || strchr(ALIASSLASHES,*n))) ++n;
+ while(n < del && !isspace(*n)) {
+ char c = *(n++);
+ *(t++) = strchr(ALIASSLASHES,c)?ALIASSLASH:c;
+ }
+ while(*t == ALIASSLASH && t > tmp) --t;
+ *t = 0;
+
+ return tmp;
+ }
+
+ n = del+1;
+ }
+
+ while(*n && isspace(*n)) ++n;
+
+ for(int i = 0; n && *n; ++i) {
+ if(i == ix) {
+ char *t = tmp;
+
+ for(; *n && !isspace(*n); ++t,++n) *t = *n;
+ *t = 0;
+ return *tmp?tmp:NULL;
+ }
+ else {
+ while(*n && !isspace(*n)) ++n;
+ while(*n && isspace(*n)) ++n;
+ }
+ }
+
+ return NULL;
+}
+
+
+//! Check if object's name ends with a tilde
+static bool chktilde(const char *objname)
+{
+// int stplen = strlen(setupfun);
+ bool tilde = true; //!strncmp(setupfun,"_tilde",6);
+
+ if((objname[strlen(objname)-1] == '~'?1:0)^(tilde?1:0)) {
+ if(tilde)
+ error("flext: %s (no trailing ~) is defined as a tilde object",objname);
+ else
+ error("flext::check_tilde: %s is no tilde object",objname);
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+// this class stands for one registered object
+// it holds the class, type flags, constructor and destructor of the object and the creation arg types
+// it will never be destroyed
+class libobject {
+public:
+ libobject(t_class *&cl,flext_obj *(*newf)(int,t_atom *),void (*freef)(flext_hdr *));
+
+ flext_obj *(*newfun)(int,t_atom *);
+ void (*freefun)(flext_hdr *c);
+
+ t_class *const &clss;
+ bool lib,dsp,attr;
+ int argc;
+ int *argv;
+};
+
+libobject::libobject(t_class *&cl,flext_obj *(*newf)(int,t_atom *),void (*freef)(flext_hdr *)):
+ clss(cl),newfun(newf),freefun(freef),argc(0),argv(NULL)
+{}
+
+// this class stands for one registered object name
+// it holds a pointer to the respective object
+// it will never be destroyed
+class libname {
+public:
+ libname(const t_symbol *n,libobject *o): name(n),obj(o),nxt(NULL) {}
+
+ const t_symbol *name;
+ libobject *obj;
+
+ static void add(libname *n);
+ static libname *find(const t_symbol *s);
+
+protected:
+ libname *nxt;
+ void addrec(libname *n);
+ static libname *root;
+};
+
+void libname::addrec(libname *n) { if(nxt) nxt->addrec(n); else nxt = n; }
+
+libname *libname::root = NULL;
+
+void libname::add(libname *l) {
+ if(root) root->addrec(l);
+ else root = l;
+}
+
+libname *libname::find(const t_symbol *s) {
+ libname *l;
+ for(l = root; l; l = l->nxt)
+ if(s == l->name) break;
+ return l;
+}
+
+// for MAXMSP, the library is represented by a special object (class) registered at startup
+// all objects in the library are clones of that library object - they share the same class
+#ifdef MAXMSP
+static t_class *lib_class = NULL;
+static const t_symbol *lib_name = NULL;
+#endif
+
+void flext_obj::lib_init(const char *name,void setupfun(),bool attr)
+{
+#ifdef MAXMSP
+ lib_name = MakeSymbol(name);
+ ::setup(
+ (t_messlist **)&lib_class,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),NULL,A_GIMME,A_NULL);
+#endif
+ process_attributes = attr;
+ setupfun();
+}
+
+void flext_obj::obj_add(bool lib,bool dsp,bool attr,const char *idname,const char *names,void setupfun(t_class *),flext_obj *(*newfun)(int,t_atom *),void (*freefun)(flext_hdr *),int argtp1,...)
+{
+ // get first possible object name
+ const t_symbol *nsym = MakeSymbol(extract(names));
+
+#ifdef _DEBUG
+ if(dsp) chktilde(GetString(nsym));
+#endif
+
+ if(!lib) process_attributes = attr;
+
+ // set dynamic class pointer
+ t_class **cl =
+#ifdef MAXMSP
+ lib?&lib_class:
+#endif
+ new t_class *;
+
+ // register object class
+#ifdef PD
+ *cl = ::class_new(
+ (t_symbol *)nsym,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),0,A_GIMME,A_NULL);
+#elif defined(MAXMSP)
+ if(!lib) {
+ ::setup(
+ (t_messlist **)cl,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),NULL,A_GIMME,A_NULL);
+ }
+#endif
+
+ // make new dynamic object
+ libobject *lo = new libobject(*cl,newfun,freefun);
+ lo->lib = lib;
+ lo->dsp = dsp;
+ lo->attr = process_attributes;
+
+ // parse the argument type list and store it with the object
+ if(argtp1 == A_GIMME)
+ lo->argc = -1;
+ else {
+ int argtp,i;
+ va_list marker;
+
+ // parse a first time and count only
+ va_start(marker,argtp1);
+ for(argtp = argtp1; argtp != A_NULL; ++lo->argc) argtp = (int)va_arg(marker,int);
+ va_end(marker);
+
+ lo->argv = new int[lo->argc];
+
+ // now parse and store
+ va_start(marker,argtp1);
+ for(argtp = argtp1,i = 0; i < lo->argc; ++i) {
+ lo->argv[i] = argtp;
+ argtp = (int)va_arg(marker,int);
+ }
+ va_end(marker);
+ }
+
+ // make help reference
+ flext_obj::DefineHelp(lo->clss,idname,extract(names,-1),dsp);
+
+ for(int ix = 0; ; ++ix) {
+ // in this loop register all the possible aliases of the object
+
+ const char *c = ix?extract(names,ix):GetString(nsym);
+ if(!c || !*c) break;
+
+ // add to name list
+ libname *l = new libname(MakeSymbol(c),lo);
+ libname::add(l);
+
+#ifdef PD
+ if(ix > 0)
+ // in PD the first name is already registered with class creation
+ ::class_addcreator((t_newmethod)obj_new,(t_symbol *)l->name,A_GIMME,A_NULL);
+#elif defined(MAXMSP)
+ if(ix > 0 || lib)
+ // in MaxMSP the first alias gets its name from the name of the object file,
+ // unless it is a library (then the name can be different)
+ ::alias(const_cast<char *>(c));
+#endif
+ }
+
+ // call class setup function
+ setupfun(lo->clss);
+}
+
+
+typedef flext_obj *(*libfun)(int,t_atom *);
+
+flext_hdr *flext_obj::obj_new(const t_symbol *s,int _argc_,t_atom *argv)
+{
+ flext_hdr *obj = NULL;
+ libname *l = libname::find(s);
+ if(l) {
+ bool ok = true;
+ t_atom args[FLEXT_MAXNEWARGS];
+ libobject *lo = l->obj;
+
+ int argc = _argc_;
+ if(lo->attr) {
+ argc = flext_base::CheckAttrib(argc,argv);
+ }
+
+ if(lo->argc >= 0) {
+#ifdef _DEBUG
+ if(lo->argc > FLEXT_MAXNEWARGS) { ERRINTERNAL(); ok = false; }
+#endif
+
+ if(argc == lo->argc) {
+ for(int i = 0; /*ok &&*/ i < lo->argc; ++i) {
+ switch(lo->argv[i]) {
+#ifdef MAXMSP
+ case A_INT:
+ if(flext::IsInt(argv[i])) args[i] = argv[i];
+ else if(flext::IsFloat(argv[i])) flext::SetInt(args[i],(int)flext::GetFloat(argv[i]));
+ else ok = false;
+ break;
+#endif
+ case A_FLOAT:
+ if(flext::IsInt(argv[i])) flext::SetFloat(args[i],(float)flext::GetInt(argv[i]));
+ else if(flext::IsFloat(argv[i])) args[i] = argv[i];
+ else ok = false;
+ break;
+ case A_SYMBOL:
+ if(flext::IsSymbol(argv[i])) args[i] = argv[i];
+ else ok = false;
+ break;
+ }
+ }
+
+ if(!ok)
+ post("%s: Creation arguments do not match",s->s_name);
+ }
+ else {
+ error("%s: %s creation arguments",s->s_name,argc < lo->argc?"Not enough":"Too many");
+ ok = false;
+ }
+ }
+
+ if(ok) {
+#ifdef PD
+ obj = (flext_hdr *)::pd_new(lo->clss);
+#elif defined(MAXMSP)
+ obj = (flext_hdr *)::newobject(lo->clss);
+#endif
+ flext_obj::m_holder = obj;
+ flext_obj::m_holdname = l->name;
+ flext_obj::m_holdattr = lo->attr;
+
+ // get actual flext object (newfun calls "new flext_obj()")
+ if(lo->argc >= 0)
+ // for interpreted arguments
+ obj->data = lo->newfun(lo->argc,args);
+ else
+ obj->data = lo->newfun(argc,argv);
+
+ flext_obj::m_holder = NULL;
+ flext_obj::m_holdname = NULL;
+ flext_obj::m_holdattr = false;
+
+ bool ok = obj->data ||
+ // check constructor exit flag
+ obj->data->InitOk();
+
+ if(ok && lo->attr && argc < _argc_)
+ // set cmdline attributes (this is a flext_base function!)
+ ok = ((flext_base *)obj->data)->InitAttrib(_argc_-argc,argv+argc);
+
+ if(ok) // call virtual init function
+ ok = obj->data->Init();
+
+ if(!ok) {
+ // there was some init error, free object
+ lo->freefun(obj);
+ obj = NULL;
+ }
+ }
+ }
+#ifdef _DEBUG
+ else
+#ifdef MAXMSP
+ // in MaxMSP an object with the name of the library exists, even if not explicitely declared!
+ if(s != lib_name)
+#endif
+ error("Class %s not found in library!",s->s_name);
+#endif
+
+ return obj;
+}
+
+void flext_obj::obj_free(flext_hdr *hdr)
+{
+ const t_symbol *name = hdr->data->thisNameSym();
+ libname *l = libname::find(name);
+
+ if(l) {
+ // call virtual exit function
+ hdr->data->Exit();
+
+ // now call object destructor and deallocate
+ l->obj->freefun(hdr);
+ }
+#ifdef _DEBUG
+ else
+#ifdef MAXMSP
+ // in MaxMSP an object with the name of the library exists, even if not explicitely declared!
+ if(name != lib_name)
+#endif
+ error("Class %s not found in library!",name);
+#endif
+}
+
+
diff --git a/externals/grill/flext/source/flmspbuffer.h b/externals/grill/flext/source/flmspbuffer.h
new file mode 100755
index 00000000..4a8ffe69
--- /dev/null
+++ b/externals/grill/flext/source/flmspbuffer.h
@@ -0,0 +1,83 @@
+/*
+
+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 flmspbuffer.h
+ \brief Definition of the Max/MSP buffer structure
+ \internal
+
+ This file comes from David Zicarellis inofficial package index.sit
+ The latter is not easily found so i included the original file buffer.h with flext
+*/
+
+#if defined(MAXMSP) && !defined(__FLEXT_MSPBUFFER_H)
+#define __FLEXT_MSPBUFFER_H
+
+enum {
+ MAXCHAN = 4
+};
+
+enum {
+ bi_basefreq = 0,
+ bi_detune,
+ bi_lowfreq,
+ bi_hifreq,
+ bi_lowvel,
+ bi_hivel,
+ bi_gain,
+ bi_numparams
+};
+
+typedef struct _buffer
+{
+ t_object b_obj; // doesn't have any signals so it doesn't need to be pxobject
+ long b_valid; // flag is off during read replacement or editing operation
+ float *b_samples; // stored with interleaved channels if multi-channel
+ long b_frames; // number of sample frames (each one is sizeof(float) * b_nchans bytes)
+ long b_nchans; // number of channels
+ long b_size; // size of buffer in floats
+ float b_sr; // sampling rate of the buffer
+ float b_1oversr; // 1 / sr
+ float b_msr; // sr * .001
+ // Mac-specific stuff
+ float *b_memory; // pointer to where memory starts (initial padding for interp)
+ t_symbol *b_name;
+ short b_vol;
+ short b_space;
+ // looping info (from AIFF file)
+ long b_susloopstart; // in samples
+ long b_susloopend; // in samples
+ long b_relloopstart; // in samples
+ long b_relloopend; // in samples
+ // instrument info (from AIFF file)
+ short b_inst[bi_numparams];
+ // window stuff
+ void *b_wind;
+ double b_pixperfr;
+ double b_frperpix;
+ long b_imagesize;
+ Point b_scroll;
+ long b_scrollscale;
+ long b_selbegin[MAXCHAN];
+ long b_selend[MAXCHAN];
+ long b_zoom;
+ long b_zim[11];
+ void *b_mouseout;
+ long b_format; // 'AIFF' or 'Sd2f'
+ t_symbol *b_filename; // last file read (not written) for readagain message
+ long b_oldnchans; // used for resizing window in case of # of channels change
+ void *b_doneout;
+ long b_outputbytes; // number of bytes used for output sample (1-4)
+ long b_modtime; // last modified time ("dirty" method)
+} t_buffer;
+
+#define BUFWIND(x) ((t_wind *)(x->b_wind))
+
+
+#endif
diff --git a/externals/grill/flext/source/flout.cpp b/externals/grill/flext/source/flout.cpp
new file mode 100644
index 00000000..3b7c6bd9
--- /dev/null
+++ b/externals/grill/flext/source/flout.cpp
@@ -0,0 +1,201 @@
+/*
+
+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 flout.cpp
+ \brief Implementation of the flext outlet functionality.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+
+
+#ifdef MAXMSP
+#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) { CRITON(); outlet_bang((t_outlet *)o); CRITOFF(); }
+void flext_base::ToOutFloat(outlet *o,float f) { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); }
+void flext_base::ToOutInt(outlet *o,int f) { CRITON(); outlet_flint((t_outlet *)o,f); CRITOFF(); }
+void flext_base::ToOutSymbol(outlet *o,const t_symbol *s) { CRITON(); outlet_symbol((t_outlet *)o,const_cast<t_symbol *>(s)); CRITOFF(); }
+void flext_base::ToOutList(outlet *o,int argc,const t_atom *argv) { CRITON(); outlet_list((t_outlet *)o,gensym("list"),argc,(t_atom *)argv); CRITOFF(); }
+void flext_base::ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { CRITON(); outlet_anything((t_outlet *)o,const_cast<t_symbol *>(s),argc,(t_atom *)argv); CRITOFF(); }
+#else
+void flext_base::ToOutBang(outlet *o) { if(IsSystemThread()) { CRITON(); outlet_bang((t_outlet *)o); CRITOFF(); } else ToQueueBang(o); }
+void flext_base::ToOutFloat(outlet *o,float f) { if(IsSystemThread()) { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); } else ToQueueFloat(o,f); }
+void flext_base::ToOutInt(outlet *o,int f) { if(IsSystemThread()) { CRITON(); outlet_flint((t_outlet *)o,f); CRITOFF(); } else ToQueueInt(o,f); }
+void flext_base::ToOutSymbol(outlet *o,const t_symbol *s) { if(IsSystemThread()) { CRITON(); outlet_symbol((t_outlet *)o,const_cast<t_symbol *>(s)); CRITOFF(); } else ToQueueSymbol(o,s); }
+void flext_base::ToOutList(outlet *o,int argc,const t_atom *argv) { if(IsSystemThread()) { CRITON(); outlet_list((t_outlet *)o,gensym("list"),argc,(t_atom *)argv); CRITOFF(); } else ToQueueList(o,argc,(t_atom *)argv); }
+void flext_base::ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { if(IsSystemThread()) { CRITON(); outlet_anything((t_outlet *)o,const_cast<t_symbol *>(s),argc,(t_atom *)argv); CRITOFF(); } else ToQueueAnything(o,s,argc,(t_atom *)argv); }
+#endif
+
+
+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;
+ };
+
+// void Add(qmsg *o);
+};
+
+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::qmsg::Add(qmsg *o)
+{
+ if(nxt) nxt->Add(o);
+ else nxt = o;
+}
+*/
+
+void flext_base::QTick(flext_base *th)
+{
+#ifdef DEBUG
+ if(!th->IsSystemThread()) {
+ error("flext - Queue tick called by wrong thread!");
+ return;
+ }
+#endif
+
+#ifdef FLEXT_THREADS
+ th->qmutex.Lock();
+#endif
+ while(th->qhead) {
+ qmsg *m = th->qhead;
+
+#ifdef MAXMSP
+ short state = lockout_set(1);
+#endif
+
+ 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 DEBUG
+ default: ERRINTERNAL();
+#endif
+ }
+
+#ifdef MAXMSP
+ lockout_set(state);
+#endif
+
+ 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)
+{
+#ifdef FLEXT_THREADS
+ qmutex.Lock();
+#endif
+ if(qtail) qtail->nxt = m;
+ else qhead = m;
+ qtail = m;
+#ifdef FLEXT_THREADS
+ qmutex.Unlock();
+#endif
+#ifdef PD
+ clock_delay(qclk,0);
+#elif defined(MAXMSP)
+ clock_delay(yclk,0);
+#else
+ #error "To implement!"
+#endif
+}
+
+void flext_base::ToQueueBang(outlet *o)
+{
+ qmsg *m = new qmsg();
+ m->SetBang(o);
+ Queue(m);
+}
+
+void flext_base::ToQueueFloat(outlet *o,float f)
+{
+ qmsg *m = new qmsg;
+ m->SetFloat(o,f);
+ Queue(m);
+}
+
+void flext_base::ToQueueInt(outlet *o,int f)
+{
+ qmsg *m = new qmsg;
+ m->SetInt(o,f);
+ Queue(m);
+}
+
+void flext_base::ToQueueSymbol(outlet *o,const t_symbol *s)
+{
+ qmsg *m = new qmsg;
+ m->SetSymbol(o,s);
+ Queue(m);
+}
+
+void flext_base::ToQueueList(outlet *o,int argc,const t_atom *argv)
+{
+ qmsg *m = new qmsg;
+ m->SetList(o,argc,argv);
+ Queue(m);
+}
+
+void flext_base::ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv)
+{
+ qmsg *m = new qmsg;
+ m->SetAny(o,s,argc,argv);
+ Queue(m);
+}
+
diff --git a/externals/grill/flext/source/flsndobj.cpp b/externals/grill/flext/source/flsndobj.cpp
new file mode 100644
index 00000000..1965b86b
--- /dev/null
+++ b/externals/grill/flext/source/flsndobj.cpp
@@ -0,0 +1,107 @@
+#include "flsndobj.h"
+
+//namespace flext {
+
+flext_sndobj::flext_sndobj():
+ inobjs(0),outobjs(0),
+ inobj(NULL),tmpobj(NULL),outobj(NULL),
+ smprt(0),blsz(0)
+{}
+
+flext_sndobj::~flext_sndobj()
+{
+ ClearObjs();
+}
+
+void flext_sndobj::ClearObjs()
+{
+ FreeObjs();
+
+ if(inobj) {
+ for(int i = 0; i < inobjs; ++i) { delete inobj[i]; delete tmpobj[i]; }
+ delete[] inobj; inobj = NULL;
+ delete[] tmpobj; tmpobj = NULL;
+ inobjs = 0;
+ }
+ if(outobj) {
+ for(int i = 0; i < outobjs; ++i) delete outobj[i];
+ delete[] outobj; outobj = NULL; outobjs = 0;
+ }
+}
+
+void flext_sndobj::m_dsp(int n,t_sample *const *in,t_sample *const *out)
+{
+ // called on every rebuild of the dsp chain
+
+ int i;
+ if(Blocksize() != blsz || Samplerate() != smprt) {
+ // block size or sample rate has changed... rebuild all objects
+
+ ClearObjs();
+
+ blsz = Blocksize();
+ smprt = Samplerate();
+
+ // set up sndobjs for inlets and outlets
+ inobj = new Inlet *[inobjs = CntInSig()];
+ tmpobj = new SndObj *[inobjs];
+ for(i = 0; i < inobjs; ++i) {
+ inobj[i] = new Inlet(in[i],blsz,smprt);
+ tmpobj[i] = new SndObj(NULL,blsz,smprt);
+ }
+ outobj = new Outlet *[outobjs = CntInSig()];
+ for(i = 0; i < outobjs; ++i) outobj[i] = new Outlet(out[i],blsz,smprt);
+
+ NewObjs();
+ }
+ else {
+ // assign changed input/output vectors
+
+ for(i = 0; i < inobjs; ++i) inobj[i]->SetBuf(in[i]);
+ for(i = 0; i < outobjs; ++i) outobj[i]->SetBuf(out[i]);
+ }
+}
+
+void flext_sndobj::m_signal(int n,t_sample *const *in,t_sample *const *out)
+{
+ for(int i = 0; i < inobjs; ++i) *tmpobj[i] << *inobj[i];
+ ProcessObjs();
+}
+
+
+flext_sndobj::Inlet::Inlet(const t_sample *b,int vecsz,float sr):
+ SndIO(1,sizeof(t_sample)*8,NULL,vecsz,sr),buf(b)
+{}
+
+short flext_sndobj::Inlet::Read()
+{
+ if(!m_error) {
+ for(m_vecpos = 0; m_vecpos < m_samples; m_vecpos++)
+ m_output[m_vecpos] = buf[m_vecpos];
+ return 1;
+ }
+ else return 0;
+}
+
+short flext_sndobj::Inlet::Write() { return 0; }
+
+
+flext_sndobj::Outlet::Outlet(t_sample *b,int vecsz,float sr):
+ SndIO(1,sizeof(t_sample)*8,NULL,vecsz,sr),buf(b)
+{}
+
+short flext_sndobj::Outlet::Read() { return 0; }
+
+short flext_sndobj::Outlet::Write()
+{
+ if(!m_error) {
+ if(m_IOobjs[0])
+ for(m_vecpos = 0; m_vecpos < m_samples; m_vecpos++)
+ buf[m_vecpos] = m_IOobjs[0]->Output(m_vecpos);
+ return 1;
+ }
+ else return 0;
+}
+
+//} // namespace flext
+
diff --git a/externals/grill/flext/source/flsndobj.h b/externals/grill/flext/source/flsndobj.h
new file mode 100644
index 00000000..f68054ed
--- /dev/null
+++ b/externals/grill/flext/source/flsndobj.h
@@ -0,0 +1,83 @@
+/*
+
+Copyright (c) 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.
+
+*/
+
+#ifndef FLEXT_SNDOBJ
+#define FLEXT_SNDOBJ
+
+#include "flext.h"
+#include <SndObj/AudioDefs.h>
+
+//namespace flext {
+
+class flext_sndobj:
+ public flext_dsp
+{
+ FLEXT_HEADER(flext_sndobj,flext_dsp)
+
+public:
+ flext_sndobj();
+ virtual ~flext_sndobj();
+
+ // these have to be overridden in child classes
+ virtual void NewObjs() {}
+ virtual void FreeObjs() {}
+ virtual void ProcessObjs() {}
+
+ // inputs and outputs
+ SndObj &InObj(int i) { return *tmpobj[i]; }
+ SndIO &OutObj(int i) { return *outobj[i]; }
+
+protected:
+ virtual void m_dsp(int n,t_sample *const *in,t_sample *const *out);
+ virtual void m_signal(int n,t_sample *const *in,t_sample *const *out);
+
+private:
+ //! SndObj for reading from inlet buffer
+ class Inlet:
+ public SndIO
+ {
+ public:
+ Inlet(const t_sample *b,int vecsz,float sr);
+ virtual short Read();
+ virtual short Write();
+
+ void SetBuf(const t_sample *b) { buf = b; }
+
+ private:
+ const t_sample *buf;
+ };
+
+ //! SndObj for writing to outlet buffer
+ class Outlet:
+ public SndIO
+ {
+ public:
+ Outlet(t_sample *b,int vecsz,float sr);
+ virtual short Read();
+ virtual short Write();
+
+ void SetBuf(t_sample *b) { buf = b; }
+
+ private:
+ t_sample *buf;
+ };
+
+ void ClearObjs();
+
+ int inobjs,outobjs;
+ SndObj **tmpobj;
+ Inlet **inobj;
+ Outlet **outobj;
+
+ float smprt;
+ int blsz;
+};
+
+//} // namespace flext
+
+#endif
diff --git a/externals/grill/flext/source/flstdc.h b/externals/grill/flext/source/flstdc.h
new file mode 100644
index 00000000..73ce613c
--- /dev/null
+++ b/externals/grill/flext/source/flstdc.h
@@ -0,0 +1,163 @@
+/*
+
+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 flstdc.h
+ \brief Definitions to unite MaxMSP and PD notions
+
+ This file contains a few definitions to unite a few of the notions that
+ once drifted apart in Max and PD. It is not elegant but helps.
+*/
+
+#ifndef __FLEXT_STDC_H
+#define __FLEXT_STDC_H
+
+// Be sure that one target is defined
+#if !defined(PD) && !defined(MAXMSP)
+#error Either PD or MAXMSP must be defined
+#endif
+
+// Do some compiler checking
+#if defined(__MRC__) && __MRC__ < 0x500
+#error Apple MPW MrCpp v.5.0.0 or better compiler required
+#endif
+
+
+// PD stuff
+
+#ifdef PD
+
+/* PD definitions start here */
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable:4091)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Include the relevant PD header files
+#ifdef _DEBUG
+#include <m_imp.h> // for easier debugging
+#else
+#include <m_pd.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+typedef t_object t_sigobj;
+typedef t_gpointer *t_ptrtype;
+
+typedef t_float t_flint;
+typedef t_symbol *t_symptr;
+typedef t_symbol *t_symtype;
+typedef t_class **t_thing;
+
+typedef t_clock t_qelem;
+
+#define A_NOTHING A_NULL
+#define A_FLINT A_FLOAT
+#define A_DEFFLINT A_DEFFLOAT
+
+// MAX stuff
+#elif defined(MAXMSP)
+
+/* MaxMSP definitions start here */
+
+// Include the relevant MaxMSP header files
+extern "C"
+{
+#include "ext.h"
+//#include "ext_strings.h" // clashes with MPW
+#include "ext_user.h"
+#include "z_dsp.h"
+//#include "z_atom.h"
+}
+
+typedef t_pxbox t_sigobj; // that's the all-in-one object type of MaxMSP (not very memory-efficent, i guess)
+typedef t_patcher t_canvas;
+
+typedef t_int t_flint;
+typedef t_symbol *t_symptr;
+typedef t_symbol *t_symtype;
+typedef t_object *t_thing;
+
+typedef qelem t_qelem;
+
+typedef method t_method;
+typedef method t_newmethod;
+typedef int t_atomtype;
+
+typedef struct clock t_clock;
+typedef void t_binbuf;
+
+#undef clock_free
+#define clock_free(tick) freeobject((object *)tick)
+
+#define A_NULL A_NOTHING
+#define A_FLINT A_INT
+#define A_DEFFLINT A_DEFLONG
+
+#endif
+
+
+#ifdef _LOG
+
+/* If _LOG is defined implement logging */
+#define LOG(s) post(s)
+#define LOG1(s,v1) post(s,v1)
+#define LOG2(s,v1,v2) post(s,v1,v2)
+#define LOG3(s,v1,v2,v3) post(s,v1,v2,v3)
+#define LOG4(s,v1,v2,v3,v4) post(s,v1,v2,v3,v4)
+#define LOG5(s,v1,v2,v3,v4,v5) post(s,v1,v2,v3,v4,v5)
+
+
+#else
+
+/* If _LOG is not defined avoid logging */
+#define LOG(s) ((void)0)
+#define LOG1(s,v1) ((void)0)
+#define LOG2(s,v1,v2) ((void)0)
+#define LOG3(s,v1,v2,v3) ((void)0)
+#define LOG4(s,v1,v2,v3,v4) ((void)0)
+#define LOG5(s,v1,v2,v3,v4,v5) ((void)0)
+
+#endif
+
+#ifdef _DEBUG
+#define ASSERT(b) ((void)(!(b)?(error("Assertion failed: " #b " - in " __FILE__ " line %i",(int)__LINE__),0):0))
+#else
+#define ASSERT(b) ((void)0)
+#endif
+
+#define ERRINTERNAL() error("flext: Internal error in file " __FILE__ ", line %i - please report",(int)__LINE__)
+
+
+/* Set the right calling convention (and exporting) for the OS */
+
+#if defined(NT)
+#define FLEXT_EXT __declspec(dllexport)
+#else // other OS's
+#define FLEXT_EXT
+#endif
+
+#endif
+
+
+
+
+
diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp
new file mode 100644
index 00000000..854fe871
--- /dev/null
+++ b/externals/grill/flext/source/flsupport.cpp
@@ -0,0 +1,58 @@
+/*
+
+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 flsupport.cpp
+ \brief flext support functions and classes.
+*/
+
+#include "flsupport.h"
+
+const t_symbol *flext::sym_float = NULL;
+const t_symbol *flext::sym_symbol = NULL;
+const t_symbol *flext::sym_bang = NULL;
+const t_symbol *flext::sym_list = NULL;
+const t_symbol *flext::sym_anything = NULL;
+const t_symbol *flext::sym_pointer = NULL;
+const t_symbol *flext::sym_int = NULL;
+
+#ifdef PD
+const t_symbol *flext::sym_signal = NULL;
+#endif
+
+void flext::Setup()
+{
+#ifdef PD
+ sym_anything = &s_anything;
+ sym_pointer = &s_pointer;
+ sym_float = &s_float;
+ sym_symbol = &s_symbol;
+ sym_bang = &s_bang;
+ sym_list = &s_list;
+ sym_signal = &s_signal;
+#elif defined(MAXMSP)
+ sym_int = gensym("int");
+ sym_float = gensym("float");
+ sym_symbol = gensym("symbol");
+ sym_bang = gensym("bang");
+ sym_list = gensym("list");
+ sym_anything = gensym("anything");
+#endif
+}
+
+void flext::GetAString(const t_atom &a,char *buf,int szbuf)
+{
+#ifdef PD
+ atom_string(const_cast<t_atom *>(&a),buf,szbuf);
+#else
+ if(IsSymbol(a)) sprintf(buf,GetString(a));
+ else if(IsFloat(a)) sprintf(buf,"%f",GetFloat(a));
+ else if(IsInt(a)) sprintf(buf,"%i",GetInt(a));
+#endif
+}
diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h
new file mode 100644
index 00000000..148790ae
--- /dev/null
+++ b/externals/grill/flext/source/flsupport.h
@@ -0,0 +1,438 @@
+/*
+
+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 flsupport.h
+ \brief flext support functions and classes
+*/
+
+#ifndef __FLSUPPORT_H
+#define __FLSUPPORT_H
+
+#include "flstdc.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#endif
+
+class FLEXT_EXT flext {
+public:
+// --- buffer/array stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_N_BUFFER Flext buffer handling
+
+ @{
+ */
+
+ //! Class for platform independent buffer handling
+ class buffer
+ {
+ public:
+ /*! \brief Construct buffer.
+ \param delayed = true: only sets name, needs another Set(NULL) to really initialize the buffer
+ \remark As externals can be created prior to the buffer objects they are pointing to, initialization should be done at loadbang!
+ */
+ buffer(const t_symbol *s = NULL,bool delayed = false);
+
+ //! Destroy buffer
+ ~buffer();
+
+ /*! \brief Check if the data is valid
+ */
+ bool Ok() const { return sym != NULL && data != NULL; }
+
+ /*! \brief Check and update if the buffer has been changed (e.g. resized)
+ */
+ bool Update();
+
+ /*! \brief Set to specified buffer.
+ \param nameonly: if true sets name only, but doesn't look at buffer actually
+ */
+ int Set(const t_symbol *s = NULL,bool nameonly = false);
+
+ /*! \brief Declare buffer content as dirty.
+ \param refr: if true forces immediate graphics refresh
+ */
+ void Dirty(bool refr = false);
+
+ //! Get symbol of buffer
+ t_symbol *Symbol() const { return const_cast<t_symbol *>(sym); }
+
+ //! Get literal name of buffer
+ const char *Name() const { return sym?sym->s_name:""; }
+
+ /*! \brief Get pointer to buffer, channel and frame count.
+ \remark Channels are interleaved
+ */
+ t_sample *Data() { return data; }
+
+ //! Get channel count
+ int Channels() const { return chns; }
+ //! Get frame count
+ int Frames() const { return frames; }
+ //! Set frame count
+ void Frames(int fr,bool keep = false);
+
+ //! Graphic auto refresh interval
+ void SetRefrIntv(float intv);
+
+ protected:
+ const t_symbol *sym;
+ t_sample *data;
+ int chns,frames;
+#ifdef PD
+ t_garray *arr;
+ float interval;
+ bool isdirty,ticking;
+ t_clock *tick;
+
+ private:
+ static void cb_tick(buffer *b);
+#endif
+ };
+
+//! @}
+
+// --- various symbols --------------------------------------------
+
+ /*! \defgroup FLEXT_N_SYMBOL Flext atom/symbol handling
+
+ @{
+ */
+
+ //! Symbol constant for "float"
+ static const t_symbol *sym_float;
+ //! Symbol constant for "symbol"
+ static const t_symbol *sym_symbol;
+ //! Symbol constant for "bang"
+ static const t_symbol *sym_bang;
+ //! Symbol constant for "list"
+ static const t_symbol *sym_list;
+ //! Symbol constant for "anything"
+ static const t_symbol *sym_anything;
+
+ /*! \brief Symbol constant for "int"
+ \note Only the Max/MSP system has this defined as an internal type
+ */
+ static const t_symbol *sym_int;
+
+ /*! Symbol constant for "pointer"
+ \note Only PD has this defined as an internal type
+ */
+ static const t_symbol *sym_pointer;
+
+#ifdef PD
+
+ /*! \brief Symbol constant for "signal"
+ \note PD only
+ */
+ static const t_symbol *sym_signal;
+#endif
+
+ //! Make a symbol from a string
+ static const t_symbol *MakeSymbol(const char *s) { return gensym(const_cast<char *>(s)); }
+
+ //! Get symbol string
+ static const char *GetString(const t_symbol *s) { return s->s_name; }
+ //! Check for symbol and get string
+ static const char *GetAString(const t_symbol *s) { return s?s->s_name:""; }
+
+//! @}
+
+// --- utilities --------------------------------------------------
+
+ /*! \defgroup FLEXT_C_UTIL Flext utility functions
+
+ @{
+ */
+
+ //! Copy an atom
+ static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
+
+ //! Copy a list of atoms
+ static t_atom *CopyList(int argc,const t_atom *argv);
+ //! Copy a memory region
+ static void CopyMem(void *dst,const void *src,int bytes);
+ //! Sleep for an amount of time
+ static void Sleep(float s);
+
+//! @}
+
+// --- atom stuff ----------------------------------------
+
+ //! Set atom from another atom
+ static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
+
+ //! Check whether the atom is nothing
+ static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
+ //! Set the atom to represent nothing
+ static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
+
+ //! Check whether the atom is a float
+ static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
+ //! Check whether the atom can be represented as a float
+ static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+ //! Access the float value (without type check)
+ static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
+ //! Set the atom to represent a float
+ static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
+
+ //! Check whether the atom is a symbol
+ static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_symbol; }
+ //! Check for a symbol and get its value
+ static t_symbol *GetASymbol(const t_atom &a) { return IsSymbol(a)?GetSymbol(a):NULL; } // NULL or empty symbol?
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast<t_symbol *>(s); }
+
+ //! Check whether the atom is a string
+ static bool IsString(const t_atom &a) { return IsSymbol(a); }
+ //! Access the string value (without type check)
+ static const char *GetString(const t_atom &a) { t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
+ //! Check for a string and get its value
+ static void GetAString(const t_atom &a,char *buf,int szbuf);
+ //! Set the atom to represent a string
+ static void SetString(t_atom &a,const char *c) { SetSymbol(a,gensym(const_cast<char *>(c))); }
+
+ //! Check whether the atom can be represented as an integer
+ static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+ //! Check whether the atom can be represented as a boolean
+ static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
+ //! Check for an boolean and get its value
+ static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
+
+#ifdef PD
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):0; }
+
+ //! Check whether the atom is an integer
+ static bool IsInt(const t_atom &) { return false; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a) { return (int)GetAFloat(a); }
+ //! Set the atom to represent a integer (depending on the system)
+ static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
+
+ //! Check whether the atom is a pointer
+ static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
+ //! Access the pointer value (without type check)
+ static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
+ //! Check for a pointer and get its value
+ static t_gpointer *GetAPointer(const t_atom &a) { return IsPointer(a)?GetPointer(a):NULL; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = p; }
+
+#elif defined(MAXMSP)
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):0); }
+
+ //! Check whether the atom is an int
+ static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return a.a_w.w_long; }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a) { return IsInt(a)?GetInt(a):(IsFloat(a)?GetFloat(a):0); }
+ //! Set the atom to represent an integer
+ static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
+
+ //! Check whether the atom is a pointer
+ static bool IsPointer(const t_atom &) { return false; }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &) { return NULL; }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &) { return NULL; }
+// void SetPointer(t_atom &,void *) {}
+#endif
+
+// --- atom list stuff -------------------------------------------
+
+ /*! \defgroup FLEXT_N_ATOM Flext atom/list handling
+
+ @{
+ */
+
+ //! Class representing a list of atoms
+ class AtomList
+ {
+ public:
+ //! Construct list
+ AtomList(int argc = 0,const t_atom *argv = NULL);
+ //! Construct list
+ AtomList(const AtomList &a);
+ //! Destroy list
+ ~AtomList();
+
+ //! Clear list
+ AtomList &Clear() { return operator()(); }
+
+ //! Set list
+ AtomList &operator()(int argc = 0,const t_atom *argv = NULL);
+ //! Set list by another AtomList
+ AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
+
+ //! Get number of atoms in the list
+ int Count() const { return cnt; }
+ //! Get a reference to an indexed atom
+ t_atom &operator [](int ix) { return lst[ix]; }
+ //! Get a reference to an indexed atom
+ const t_atom &operator [](int ix) const { return lst[ix]; }
+
+ //! Get a pointer to the list of atoms
+ t_atom *Atoms() { return lst; }
+ //! Get a pointer to the list of atoms
+ const t_atom *Atoms() const { return lst; }
+
+ //! Append an atom to the list
+ AtomList &Append(const t_atom &a);
+ //! Append an atom list to the list
+ AtomList &Append(int argc,const t_atom *argv);
+ //! Append an atom list to the list
+ AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
+ //! Prepend an atom to the list
+ AtomList &Prepend(const t_atom &a);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(int argc,const t_atom *argv);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
+
+ //! Get a part of the list
+ AtomList GetPart(int offs,int len) const;
+ //! Set to a part of the list
+ AtomList &Part(int offs,int len) { return (*this = GetPart(offs,len)); }
+
+ protected:
+ int cnt;
+ t_atom *lst;
+ };
+
+
+ //! Class representing an "anything"
+ class AtomAnything:
+ public AtomList
+ {
+ public:
+ //! Construct anything
+ AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(h) {}
+ //! Construct anything
+ AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(MakeSymbol(h)) {}
+ //! Construct anything
+ AtomAnything(const AtomAnything &a): AtomList(a),hdr(a.hdr) {}
+
+ //! Clear anything
+ AtomAnything &Clear() { return operator()(); }
+
+ //! Get header symbol of anything
+ const t_symbol *Header() const { return hdr; }
+
+ //! Set anything
+ AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
+ {
+ hdr = h; AtomList::operator()(argc,argv);
+ return *this;
+ }
+
+ //! Set list by another AtomAnything
+ AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
+
+ protected:
+ const t_symbol *hdr;
+ };
+
+//! @}
+
+// --- clock stuff ------------------------------------------------
+
+
+ /*! \defgroup FLEXT_N_CLOCK Flext clock functions
+
+ At the moment there are none
+
+ @{
+ */
+
+//! @}
+
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ /*! \defgroup FLEXT_N_THREAD Flext thread handling
+
+ @{
+ */
+
+ /*! \brief Thread mutex
+ \sa pthreads documentation
+ */
+ class ThrMutex
+ {
+ public:
+ //! Construct thread mutex
+ ThrMutex(): cnt(0) { pthread_mutex_init(&mutex,NULL); }
+ //! Destroy thread mutex
+ ~ThrMutex() { pthread_mutex_destroy(&mutex); }
+
+ //! Lock thread mutex
+ int Lock() { cnt = 1; return pthread_mutex_lock(&mutex); }
+ //! Try to lock, but don't wait
+ int TryLock() { return pthread_mutex_trylock(&mutex); }
+ //! Unlock thread mutex
+ int Unlock() { cnt = 0; return pthread_mutex_unlock(&mutex); }
+
+ //! Lock thread mutex (increase lock count by one)
+ void Push() { if(!cnt++) Lock(); }
+ //! Unlock thread mutex if lock count reaches zero
+ void Pop() { if(!--cnt) Unlock(); }
+ protected:
+ pthread_mutex_t mutex;
+ int cnt;
+ };
+
+ /*! \brief Thread conditional
+ \sa pthreads documentation
+ */
+ class ThrCond:
+ public ThrMutex
+ {
+ public:
+ //! Construct thread conditional
+ ThrCond() { pthread_cond_init(&cond,NULL); }
+ //! Destroy thread conditional
+ ~ThrCond() { pthread_cond_destroy(&cond); }
+
+ //! Wait for condition
+ int Wait() { return pthread_cond_wait(&cond,&mutex); }
+
+ /*! \brief Wait for condition (for a certain time)
+ \param time Wait time in seconds
+ */
+ int TimedWait(float time)
+ {
+ timespec tm; tm.tv_sec = (long)time; tm.tv_nsec = (long)((time-(long)time)*1.e9);
+ return pthread_cond_timedwait(&cond,&mutex,&tm);
+ }
+
+ //! Signal condition
+ int Signal() { return pthread_cond_signal(&cond); }
+ //! Broadcast condition
+ int Broadcast() { return pthread_cond_broadcast(&cond); }
+ protected:
+ pthread_cond_t cond;
+ };
+//! @}
+#endif // FLEXT_THREADS
+
+protected:
+ static void Setup();
+};
+
+#endif
diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp
new file mode 100644
index 00000000..fd780a1c
--- /dev/null
+++ b/externals/grill/flext/source/flthr.cpp
@@ -0,0 +1,237 @@
+/*
+
+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 flthr.cpp
+ \brief Implementation of the flext thread functionality.
+*/
+
+#ifdef FLEXT_THREADS
+
+#include "flext.h"
+#include "flinternal.h"
+
+#ifdef MAXMSP
+#define SCHEDTICK 1
+#endif
+
+#ifdef NT
+#include <windows.h>
+#endif
+#include <errno.h>
+
+bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname)
+{
+ static bool init = false;
+ static pthread_attr_t attr;
+#ifdef _DEBUG
+ if(!p) {
+ ERRINTERNAL();
+ return false;
+ }
+#endif
+ if(!init) {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
+ init = true;
+ }
+
+ // set thread priority one point below normal
+ // so thread construction won't disturb real-time audio
+ pthread_t id = pthread_self();
+ sched_param parm;
+ int policy;
+ pthread_getschedparam(id,&policy,&parm);
+ int prio = parm.sched_priority;
+ int schmin = sched_get_priority_min(policy);
+ if(prio > schmin) {
+ parm.sched_priority = prio-1;
+ pthread_setschedparam(id,policy,&parm);
+ }
+
+ pthread_t thrid;
+ int ret = pthread_create (&thrid,&attr,(void *(*)(void *))meth,p);
+
+ // set thread priority back to normal
+ parm.sched_priority = prio;
+ pthread_setschedparam(id,policy,&parm);
+
+ if(ret) {
+#ifdef _DEBUG
+ error((char *)(ret == EAGAIN?"%s - Unsufficient resources to launch thread!":"%s - Could not launch method!"),methname);
+#endif
+ delete p;
+ return false;
+ }
+ else {
+#ifdef MAXMSP
+ sched_yield();
+#endif
+ return true;
+ }
+}
+
+bool flext_base::PushThread()
+{
+ tlmutex.Lock();
+
+ // make an entry into thread list
+ thr_entry *nt = new thr_entry;
+ if(thrtail) thrtail->nxt = nt;
+ else thrhead = nt;
+ thrtail = nt;
+
+ {
+#ifdef NT
+ // set detached thread to lower priority class
+ DWORD err;
+ HANDLE thr = GetCurrentThread();
+ DWORD cl = GetThreadPriority(thr);
+ if(!cl && (err = GetLastError()))
+ post("flext - error getting thread priority");
+ else {
+ BOOL ret = SetThreadPriority(thr,cl-2);
+ if(!ret) {
+ err = GetLastError();
+ if(!err) post("flext - error setting thread priority");
+ }
+ }
+#else
+ // set initial detached thread priority two points below normal
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(nt->thrid,&policy,&parm))
+ post("flext - can't get thread parameters");
+ int prio = parm.sched_priority;
+ int schmin = sched_get_priority_min(policy);
+ if(prio > schmin) {
+ parm.sched_priority = prio-2;
+ if(pthread_setschedparam(nt->thrid,policy,&parm))
+ post("flext - can't set thread parameters");
+ }
+#endif
+ }
+
+ tlmutex.Unlock();
+
+#ifdef MAXMSP
+ clock_delay(yclk,0);
+#endif
+ return true;
+}
+
+void flext_base::PopThread()
+{
+ tlmutex.Lock();
+
+ pthread_t id = pthread_self();
+
+ thr_entry *prv = NULL,*ti;
+ for(ti = thrhead; ti; prv = ti,ti = ti->nxt)
+ if(ti->Is()) break;
+
+ if(ti) {
+ if(prv)
+ prv->nxt = ti->nxt;
+ else
+ thrhead = ti->nxt;
+ if(thrtail == ti) thrtail = prv;
+
+ ti->nxt = NULL;
+ delete ti;
+ }
+ else {
+#ifdef _DEBUG
+ post("%s - INTERNAL ERROR: Thread not found!",thisName());
+#endif
+ }
+
+ tlmutex.Unlock();
+}
+
+#ifdef MAXMSP
+void flext_base::YTick(flext_base *th)
+{
+ clock_delay(th->yclk,0);
+ qelem_set(th->qclk);
+ sched_yield();
+}
+#endif
+
+flext_base::thrid_t flext_base::GetThreadId()
+{
+ return pthread_self();
+}
+
+bool flext_base::ChangePriority(int dp,thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return false;
+ }
+ else {
+ parm.sched_priority += dp;
+ if(pthread_setschedparam(id,policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to change priority");
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+
+
+int flext_base::GetPriority(thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return -1;
+ }
+ return parm.sched_priority;
+}
+
+
+bool flext_base::SetPriority(int p,thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return false;
+ }
+ else {
+ parm.sched_priority = p;
+ if(pthread_setschedparam(id,policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to change priority");
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+
+flext_base::thr_params::thr_params(flext_base *c,int n): cl(c),var(new _data[n]) {}
+flext_base::thr_params::~thr_params() { if(var) delete[] var; }
+
+void flext_base::thr_params::set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any.args = new AtomAnything(s,argc,argv); }
+void flext_base::thr_params::set_list(int argc,const t_atom *argv) { var[0]._list.args = new AtomList(argc,argv); }
+
+#endif // FLEXT_THREADS
diff --git a/externals/grill/flext/source/flutil.cpp b/externals/grill/flext/source/flutil.cpp
new file mode 100644
index 00000000..509c3ab4
--- /dev/null
+++ b/externals/grill/flext/source/flutil.cpp
@@ -0,0 +1,68 @@
+/*
+
+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 flutil.cpp
+ \brief Implementation of the various utility functions.
+*/
+
+#include "flext.h"
+#include <string.h>
+
+#ifdef NT
+#include <windows.h>
+#endif
+
+#ifdef MAXMSP
+#include <Timer.h>
+#include <Threads.h>
+#endif
+
+#ifdef unix
+#include <unistd.h>
+#endif
+
+//namespace flext {
+
+t_atom *flext::CopyList(int argc,const t_atom *argv)
+{
+ int i;
+ t_atom *dst = new t_atom[argc];
+ for(i = 0; i < argc; ++i) CopyAtom(dst+i,argv+i);
+ return dst;
+}
+
+void flext::CopyMem(void *dst,const void *src,int bytes)
+{
+#ifdef macintosh
+ BlockMoveData(src,dst,bytes);
+#else
+ memcpy(dst,src,bytes);
+#endif
+}
+
+void flext::Sleep(float s)
+{
+#ifdef NT
+ ::Sleep((long)(s*1000));
+#elif defined MAXMSP
+ UnsignedWide tick;
+ Microseconds(&tick);
+ double target = tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo+s*1.e6;
+ for(;;) {
+ Microseconds(&tick);
+ if(target <= tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo) break;
+ YieldToAnyThread(); // should we really yield?
+ }
+#else
+ usleep((long)(s*1000000));
+#endif
+}
+
+//} // namespace flext
diff --git a/externals/grill/flext/source/flxlet.cpp b/externals/grill/flext/source/flxlet.cpp
new file mode 100755
index 00000000..881769da
--- /dev/null
+++ b/externals/grill/flext/source/flxlet.cpp
@@ -0,0 +1,88 @@
+/*
+
+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 flxlet.cpp
+ \brief Implementation of the variable inlet/outlet functionality.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+#include <stdarg.h>
+
+//namespace flext {
+
+flext_base::xlet::xlet(type t,const char *d):
+ tp(t),nxt(NULL)
+{
+ if(d) {
+ int ln = strlen(d);
+ desc = new char[ln];
+ strncpy(desc,d,ln);
+ }
+ else desc = NULL;
+}
+
+flext_base::xlet::~xlet()
+{
+ if(desc) delete[] desc;
+ if(nxt) delete nxt;
+}
+
+void flext_base::AddXlet(xlet::type tp,int mult,const char *desc,xlet *&root)
+{
+ if(!root && mult) { root = new xlet(tp,desc); --mult; }
+ if(mult) {
+ xlet *xi = root;
+ while(xi->nxt) xi = xi->nxt;
+ while(mult--) xi = xi->nxt = new xlet(tp,desc);
+ }
+}
+
+void flext_base::DescXlet(int ix,const char *desc,xlet *&root)
+{
+ post("%s - sorry, not implemented",thisName());
+}
+
+unsigned long flext_base::XletCode(xlet::type tp,...)
+{
+ unsigned long code = 0;
+
+ va_list marker;
+ va_start(marker,tp);
+ int cnt = 0;
+ xlet::type *args = NULL,arg = tp;
+ for(; arg; ++cnt) {
+#ifdef _DEBUG
+ if(cnt > 9) {
+ error("%s - Too many in/outlets defined - truncated to 9",thisName());
+ break;
+ }
+#endif
+
+ code = code*10+(int)arg;
+ arg = (xlet::type)va_arg(marker,int);
+ }
+ va_end(marker);
+
+ return code;
+}
+
+void flext_base::AddInlets(unsigned long code)
+{
+ for(; code; code /= 10) AddInlet((xlet::type)(code%10));
+}
+
+void flext_base::AddOutlets(unsigned long code)
+{
+ for(; code; code /= 10) AddOutlet((xlet::type)(code%10));
+}
+
+//} // namespace flext