diff options
Diffstat (limited to 'externals/grill/flext/source')
-rw-r--r-- | externals/grill/flext/source/flatom_pr.cpp | 156 | ||||
-rw-r--r-- | externals/grill/flext/source/fldsp.cpp | 420 | ||||
-rw-r--r-- | externals/grill/flext/source/flstdc.h | 424 | ||||
-rw-r--r-- | externals/grill/flext/source/flstk.cpp | 12 | ||||
-rw-r--r-- | externals/grill/flext/source/flstk.h | 19 | ||||
-rw-r--r-- | externals/grill/flext/source/flsupport.cpp | 313 | ||||
-rw-r--r-- | externals/grill/flext/source/flsupport.h | 1678 |
7 files changed, 1501 insertions, 1521 deletions
diff --git a/externals/grill/flext/source/flatom_pr.cpp b/externals/grill/flext/source/flatom_pr.cpp index 7eeada93..b6cc0e5f 100644 --- a/externals/grill/flext/source/flatom_pr.cpp +++ b/externals/grill/flext/source/flatom_pr.cpp @@ -1,87 +1,69 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2003 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_pr.cpp - \brief Definitions for printing and scanning the t_atom type. -*/ - -#include "flext.h" -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#ifdef __MWERKS__ -#define STD std -#else -#define STD -#endif - -void flext::PrintAtom(const t_atom &a,char *buf) -{ - if(IsFloat(a)) { -#if FLEXT_SYS == FLEXT_SYS_PD - if(a.a_w.w_float == (int)a.a_w.w_float) - STD::sprintf(buf,"%i",(int)GetFloat(a)); - else -#endif - STD::sprintf(buf,"%f",GetFloat(a)); - } - else if(IsInt(a)) - STD::sprintf(buf,"%i",GetInt(a)); - else if(IsPointer(a)) - STD::sprintf(buf,"%p",GetPointer(a)); - else if(IsSymbol(a)) - strcpy(buf,GetString(a)); - else if(IsNothing(a)) {} -#ifdef FLEXT_DEBUG - else - ERRINTERNAL(); -#endif -} - -bool flext::ScanAtom(t_atom &a,const char *buf) -{ - // skip whitespace - while(*buf && isspace(*buf)) ++buf; - if(!*buf) return false; - - char tmp[1024]; - strcpy(tmp,buf); - char *c = tmp; - - // check for word type (s = 0,1,2 ... int,float,symbol) - int s = 0; - for(; *c && !isspace(*c); ++c) { - if(!isdigit(*c)) - s = (*c != '.' || s == 1)?2:1; - } - - switch(s) { - case 0: // integer -#if FLEXT_SYS == FLEXT_SYS_MAX - SetInt(a,atol(tmp)); - break; -#endif - case 1: // float - SetFloat(a,(float)atof(tmp)); - break; - default: { // anything else is a symbol - char t = *c; *c = 0; - SetString(a,tmp); - *c = t; - break; - } - } - - return true; -} - - +/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 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_pr.cpp
+ \brief Definitions for printing and scanning the t_atom type.
+*/
+
+#include "flext.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef __MWERKS__
+#define STD std
+#else
+#define STD
+#endif
+
+void flext::PrintAtom(const t_atom &a,char *buf,int bufsz)
+{
+ GetAString(a,buf,bufsz?bufsz:100000);
+}
+
+bool flext::ScanAtom(t_atom &a,const char *buf)
+{
+ // skip whitespace
+ while(*buf && isspace(*buf)) ++buf;
+ if(!*buf) return false;
+
+ char tmp[1024];
+ strcpy(tmp,buf);
+ char *c = tmp;
+
+ // check for word type (s = 0,1,2 ... int,float,symbol)
+ int s = 0;
+ for(; *c && !isspace(*c); ++c) {
+ if(!isdigit(*c))
+ s = (*c != '.' || s == 1)?2:1;
+ }
+
+ switch(s) {
+ case 0: // integer
+#if FLEXT_SYS == FLEXT_SYS_MAX
+ SetInt(a,atol(tmp));
+ break;
+#endif
+ case 1: // float
+ SetFloat(a,(float)atof(tmp));
+ break;
+ default: { // anything else is a symbol
+ char t = *c; *c = 0;
+ SetString(a,tmp);
+ *c = t;
+ break;
+ }
+ }
+
+ return true;
+}
+
+
diff --git a/externals/grill/flext/source/fldsp.cpp b/externals/grill/flext/source/fldsp.cpp index 64051008..a90545d2 100644 --- a/externals/grill/flext/source/fldsp.cpp +++ b/externals/grill/flext/source/fldsp.cpp @@ -1,210 +1,210 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2003 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 ============================================== - -#if FLEXT_SYS == FLEXT_SYS_JMAX -const t_symbol *flext_dsp::dspsym = MakeSymbol("__flext_dspfun__"); -#endif - -void flext_dsp::Setup(t_classid id) -{ - t_class *c = getClass(id); - -#if FLEXT_SYS == FLEXT_SYS_MAX -// dsp_initclass(); - dsp_initboxclass(); - add_dsp(c,cb_dsp); -#elif FLEXT_SYS == FLEXT_SYS_PD - CLASS_MAINSIGNALIN(c,flext_hdr,defsig); // float messages going into the left inlet are converted to signal - add_dsp(c,cb_dsp); - add_method1(c,cb_enable,"enable",A_FLOAT); -#elif FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_declare_function(dspsym,dspmeth); - fts_class_message_varargs(c, fts_s_put, cb_dsp); - fts_class_message_varargs(c, MakeSymbol("enable"), cb_enable); -#endif -} - -flext_dsp::flext_dsp(): -#if FLEXT_SYS == FLEXT_SYS_JMAX - srate(fts_dsp_get_sample_rate()), // should we set it? - blksz(fts_dsp_get_tick_size()), -#else - srate(sys_getsr()), // should we set it? - blksz(sys_getblksize()), -#endif -#if FLEXT_SYS == FLEXT_SYS_PD - chnsin(sys_get_inchannels()), - chnsout(sys_get_outchannels()), -#elif FLEXT_SYS == FLEXT_SYS_MAX - chnsin(sys_getch()), - chnsout(sys_getch()), -#elif FLEXT_SYS == FLEXT_SYS_JMAX - #pragma message("not implemented") - chnsin(0),chnsout(0), -#else -#error -#endif -#if FLEXT_SYS != FLEXT_SYS_MAX - dspon(true), -#endif - invecs(NULL),outvecs(NULL) -{ -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_object_init(thisHdr()); -#endif -} - - -flext_dsp::~flext_dsp() -{ -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_object_delete(thisHdr()); -#endif - if(invecs) delete[] invecs; - if(outvecs) delete[] outvecs; -} - -#if FLEXT_SYS == FLEXT_SYS_JMAX -void flext_dsp::dspmeth(fts_word_t *w) -{ -} -#else -t_int *flext_dsp::dspmeth(t_int *w) -{ - flext_dsp *obj = (flext_dsp *)w[1]; -#if FLEXT_SYS == FLEXT_SYS_MAX - if(!obj->thisHdr()->z_disabled) -#else - if(obj->dspon) -#endif - obj->m_signal((int)w[2],obj->invecs,obj->outvecs); - return w+3; -} -#endif - -#if FLEXT_SYS == FLEXT_SYS_JMAX -void flext_dsp::cb_dsp(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at) -#else -void flext_dsp::cb_dsp(t_class *c,t_signal **sp) -#endif -{ - flext_dsp *obj = thisObject(c); - - if(obj->CntInSig()+obj->CntOutSig() == 0) return; - - // store current dsp parameters -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_descr_t *dsp = (fts_dsp_descr_t *)fts_get_pointer(at+0); - obj->srate = fts_dsp_get_input_srate(dsp,0); - obj->blksz = fts_dsp_get_input_size(dsp,0); // is this guaranteed to be the same as sys_getblksize() ? -#else - obj->srate = sp[0]->s_sr; - obj->blksz = sp[0]->s_n; // is this guaranteed to be the same as sys_getblksize() ? -#endif - -#if FLEXT_SYS == FLEXT_SYS_PD - obj->chnsin = sys_get_inchannels(); - obj->chnsout = sys_get_outchannels(); -#elif FLEXT_SYS == FLEXT_SYS_MAX - obj->chnsin = obj->chnsout = sys_getch(); -#elif FLEXT_SYS == FLEXT_SYS_JMAX - #pragma message ("How to query the channels?") -#else -#error -#endif - - // store in and out signal vectors - int i,in = obj->CntInSig(),out = obj->CntOutSig(); - -#if FLEXT_SYS == FLEXT_SYS_PD - // min. 1 input channel! (CLASS_MAININLET in pd...) - if(!in) in = 1; -#endif - - if(obj->invecs) delete[] obj->invecs; - obj->invecs = new t_signalvec[in]; - for(i = 0; i < in; ++i) - obj->invecs[i] = -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_get_input_name(dsp,i); -#else - sp[i]->s_vec; -#endif - - if(obj->outvecs) delete[] obj->outvecs; - obj->outvecs = new t_signalvec[out]; - for(i = 0; i < out; ++i) - obj->outvecs[i] = -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_dsp_get_output_name(dsp,i); -#else - sp[in+i]->s_vec; -#endif - - // with the following call derived classes can do their eventual DSP setup - obj->m_dsp(obj->blksz,obj->invecs,obj->outvecs); - - // set the DSP function -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_atom_t args[2]; - fts_set_pointer(args+0,obj); - fts_set_int(args+1,obj->blksz); - fts_dsp_add_function(dspsym,2,args); -#else - dsp_add((t_dspmethod)dspmeth,2,obj,obj->blksz); -#endif -} - -/* -#if FLEXT_SYS == FLEXT_SYS_JMAX -void flext_dsp::cb_dsp_init(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at) -{ - fts_dsp_add_object(c); -} - -void flext_dsp::cb_dsp_delete(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at) -{ - fts_dsp_remove_object(c); -} -#endif -*/ - -void flext_dsp::m_dsp(int /*n*/,t_signalvec const * /*insigs*/,t_signalvec const * /*outsigs*/) {} - -void flext_dsp::m_signal(int n,t_sample *const * /*insigs*/,t_sample *const *outs) -{ - for(int i = 0; i < CntOutSig(); ++i) ZeroMem(outs[i],n*sizeof(*outs[i])); -} - -#if FLEXT_SYS != FLEXT_SYS_MAX - -#if FLEXT_SYS == FLEXT_SYS_PD -void flext_dsp::cb_enable(t_class *c,t_float on) { thisObject(c)->m_enable(on != 0); } -#elif FLEXT_SYS == FLEXT_SYS_JMAX -void flext_dsp::cb_enable(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at) -{ thisObject(c)->m_enable(fts_get_int(at+0) != 0); } -#endif - -void flext_dsp::m_enable(bool en) { dspon = en; } -#endif - - +/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 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 ==============================================
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+const t_symbol *flext_dsp::dspsym = MakeSymbol("__flext_dspfun__");
+#endif
+
+void flext_dsp::Setup(t_classid id)
+{
+ t_class *c = getClass(id);
+
+#if FLEXT_SYS == FLEXT_SYS_MAX
+// dsp_initclass();
+ dsp_initboxclass();
+ add_dsp(c,cb_dsp);
+#elif FLEXT_SYS == FLEXT_SYS_PD
+ CLASS_MAINSIGNALIN(c,flext_hdr,defsig); // float messages going into the left inlet are converted to signal
+ add_dsp(c,cb_dsp);
+ add_method1(c,cb_enable,"enable",A_FLOAT);
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_declare_function(dspsym,dspmeth);
+ fts_class_message_varargs(c, fts_s_put, cb_dsp);
+ fts_class_message_varargs(c, MakeSymbol("enable"), cb_enable);
+#endif
+}
+
+flext_dsp::flext_dsp():
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ srate(fts_dsp_get_sample_rate()), // should we set it?
+ blksz(fts_dsp_get_tick_size()),
+#else
+ srate(sys_getsr()), // should we set it?
+ blksz(sys_getblksize()),
+#endif
+#if FLEXT_SYS == FLEXT_SYS_PD
+ chnsin(sys_get_inchannels()),
+ chnsout(sys_get_outchannels()),
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ chnsin(sys_getch()),
+ chnsout(sys_getch()),
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ #pragma message("not implemented")
+ chnsin(0),chnsout(0),
+#else
+#error
+#endif
+#if FLEXT_SYS != FLEXT_SYS_MAX
+ dspon(true),
+#endif
+ invecs(NULL),outvecs(NULL)
+{
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_object_init(thisHdr());
+#endif
+}
+
+
+flext_dsp::~flext_dsp()
+{
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_object_delete(thisHdr());
+#endif
+ if(invecs) delete[] invecs;
+ if(outvecs) delete[] outvecs;
+}
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+void flext_dsp::dspmeth(fts_word_t *w)
+{
+}
+#else
+t_int *flext_dsp::dspmeth(t_int *w)
+{
+ flext_dsp *obj = (flext_dsp *)w[1];
+#if FLEXT_SYS == FLEXT_SYS_MAX
+ if(!obj->thisHdr()->z_disabled)
+#else
+ if(obj->dspon)
+#endif
+ obj->m_signal((int)w[2],obj->invecs,obj->outvecs);
+ return w+3;
+}
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+void flext_dsp::cb_dsp(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at)
+#else
+void flext_dsp::cb_dsp(t_class *c,t_signal **sp)
+#endif
+{
+ flext_dsp *obj = thisObject(c);
+
+ if(obj->CntInSig()+obj->CntOutSig() == 0) return;
+
+ // store current dsp parameters
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_descr_t *dsp = (fts_dsp_descr_t *)fts_get_pointer(at+0);
+ obj->srate = fts_dsp_get_input_srate(dsp,0);
+ obj->blksz = fts_dsp_get_input_size(dsp,0); // is this guaranteed to be the same as sys_getblksize() ?
+#else
+ obj->srate = sp[0]->s_sr;
+ obj->blksz = sp[0]->s_n; // is this guaranteed to be the same as sys_getblksize() ?
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ obj->chnsin = sys_get_inchannels();
+ obj->chnsout = sys_get_outchannels();
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ obj->chnsin = obj->chnsout = sys_getch();
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ #pragma message ("How to query the channels?")
+#else
+#error
+#endif
+
+ // store in and out signal vectors
+ int i,in = obj->CntInSig(),out = obj->CntOutSig();
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ // min. 1 input channel! (CLASS_MAININLET in pd...)
+ if(!in) in = 1;
+#endif
+
+ if(obj->invecs) delete[] obj->invecs;
+ obj->invecs = new t_signalvec[in];
+ for(i = 0; i < in; ++i)
+ obj->invecs[i] =
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_get_input_name(dsp,i);
+#else
+ sp[i]->s_vec;
+#endif
+
+ if(obj->outvecs) delete[] obj->outvecs;
+ obj->outvecs = new t_signalvec[out];
+ for(i = 0; i < out; ++i)
+ obj->outvecs[i] =
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_dsp_get_output_name(dsp,i);
+#else
+ sp[in+i]->s_vec;
+#endif
+
+ // with the following call derived classes can do their eventual DSP setup
+ obj->m_dsp(obj->blksz,obj->invecs,obj->outvecs);
+
+ // set the DSP function
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_atom_t args[2];
+ fts_set_pointer(args+0,obj);
+ fts_set_int(args+1,obj->blksz);
+ fts_dsp_add_function(dspsym,2,args);
+#else
+ dsp_add((t_dspmethod)dspmeth,2,obj,obj->blksz);
+#endif
+}
+
+/*
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+void flext_dsp::cb_dsp_init(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
+{
+ fts_dsp_add_object(c);
+}
+
+void flext_dsp::cb_dsp_delete(fts_object_t *c, int winlet, fts_symbol_t *s, int ac, const fts_atom_t *at)
+{
+ fts_dsp_remove_object(c);
+}
+#endif
+*/
+
+void flext_dsp::m_dsp(int /*n*/,t_signalvec const * /*insigs*/,t_signalvec const * /*outsigs*/) {}
+
+void flext_dsp::m_signal(int n,t_sample *const * /*insigs*/,t_sample *const *outs)
+{
+ for(int i = 0; i < CntOutSig(); ++i) ZeroSamples(outs[i],n);
+}
+
+#if FLEXT_SYS != FLEXT_SYS_MAX
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+void flext_dsp::cb_enable(t_class *c,t_float on) { thisObject(c)->m_enable(on != 0); }
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+void flext_dsp::cb_enable(fts_object_t *c, int winlet, fts_symbol_t s, int ac, const fts_atom_t *at)
+{ thisObject(c)->m_enable(fts_get_int(at+0) != 0); }
+#endif
+
+void flext_dsp::m_enable(bool en) { dspon = en; }
+#endif
+
+
diff --git a/externals/grill/flext/source/flstdc.h b/externals/grill/flext/source/flstdc.h index 873f4243..44d2dc03 100644 --- a/externals/grill/flext/source/flstdc.h +++ b/externals/grill/flext/source/flstdc.h @@ -1,212 +1,212 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2003 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 Max/MSP 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 - -// PD stuff - -#if FLEXT_SYS == FLEXT_SYS_PD - -/* PD definitions start here */ - -#ifdef _MSC_VER - #pragma warning (push) - #pragma warning (disable:4091 4005) -#endif - -#if FLEXT_OS == FLEXT_OS_WIN && !defined(NT) -#define NT -#endif - -extern "C" { - // Include the relevant PD header files - #ifdef FLEXT_DEBUG - #include <m_imp.h> // for easier debugging - #else - #include <m_pd.h> - #endif -} - -#ifdef _MSC_VER - #pragma warning (pop) -#endif - -#ifdef cabs -#undef cabs // this is defined in m_pd.h (clashes with math.h in MacOSX) -#endif - -typedef t_object t_sigobj; -typedef t_gpointer *t_ptrtype; - -typedef t_float t_flint; -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 - - -#elif FLEXT_SYS == FLEXT_SYS_MAX - -/* Max/MSP definitions start here */ - - -// Include the relevant Max/MSP header files - -#if FLEXT_OS == FLEXT_OS_MAC - #ifndef __MRC__ - #define powerc - #endif - #define __MOTO__ 0 - - #include <MacTypes.h> -#elif FLEXT_OS == FLEXT_OS_WIN - #define WIN_VERSION 1 -#endif - -extern "C" -{ - #include "ext.h" - #include "ext_user.h" - #include "z_dsp.h" -} - -#undef WIN_VERSION - - -typedef t_pxbox t_sigobj; // that's the all-in-one object type of Max/MSP (not very memory-efficent, i guess) -typedef t_patcher t_canvas; - -typedef t_int t_flint; -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_DEFFLINT A_DEFLONG - -#ifndef A_INT -#define A_INT A_LONG -#endif - -#ifndef A_SYMBOL -#define A_SYMBOL A_SYM -#endif - - -#elif FLEXT_SYS == FLEXT_SYS_JMAX - -extern "C" { - // Wow, the jMax developers made excessive use of C++ reserved words - // good hit! - #define typeid c_typeid_ - #define template c_template_ - #define this c_this_ - #define class c_class_ - - #include <fts/fts.h> - - // undefine them again - #undef typeid - #undef template - #undef this - #undef class -} - -typedef fts_dsp_object t_sigobj; -typedef void t_canvas; // decide type later on - -typedef char t_symbol; -typedef fts_atom_t t_atom; -typedef fts_class_t t_class; -typedef float t_sample; // is there no sample type in jMax? - -typedef fts_timebase_entry_t t_clock; -typedef fts_timebase_entry_t t_qelem; - -#endif // FLEXT_SYS - - -// general definitions - -typedef t_symbol *t_symptr; - - -// ------------------------- - -#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 FLEXT_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 */ - -#ifdef _MSC_VER - #ifdef FLEXT_SHARED - #define FLEXT_SHARE __declspec(dllexport) - #else - #define FLEXT_SHARE - #endif - #define FLEXT_EXT __declspec(dllexport) -#else // other OS's - #define FLEXT_SHARE - #define FLEXT_EXT -#endif - -#endif +/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 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 Max/MSP 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
+
+// PD stuff
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+
+/* PD definitions start here */
+
+#ifdef _MSC_VER
+ #pragma warning (push)
+ #pragma warning (disable:4091 4005)
+#endif
+
+#if FLEXT_OS == FLEXT_OS_WIN && !defined(NT)
+#define NT
+#endif
+
+extern "C" {
+ // Include the relevant PD header files
+ #ifdef FLEXT_DEBUG
+ #include <m_imp.h> // for easier debugging
+ #else
+ #include <m_pd.h>
+ #endif
+}
+
+#ifdef _MSC_VER
+ #pragma warning (pop)
+#endif
+
+#ifdef cabs
+#undef cabs // this is defined in m_pd.h (clashes with math.h in MacOSX)
+#endif
+
+typedef t_object t_sigobj;
+typedef t_gpointer *t_ptrtype;
+
+typedef t_float t_flint;
+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
+
+
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+
+/* Max/MSP definitions start here */
+
+
+// Include the relevant Max/MSP header files
+
+#if FLEXT_OS == FLEXT_OS_MAC
+ #ifndef __MRC__
+ #define powerc
+ #endif
+ #define __MOTO__ 0
+
+ #include <MacTypes.h>
+#elif FLEXT_OS == FLEXT_OS_WIN
+ #define WIN_VERSION 1
+#endif
+
+extern "C"
+{
+ #include "ext.h"
+ #include "ext_user.h"
+ #include "z_dsp.h"
+}
+
+#undef WIN_VERSION
+
+
+typedef t_pxbox t_sigobj; // that's the all-in-one object type of Max/MSP (not very memory-efficent, i guess)
+typedef t_patcher t_canvas;
+
+typedef t_int t_flint;
+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_DEFFLINT A_DEFLONG
+
+#ifndef A_INT
+#define A_INT A_LONG
+#endif
+
+#ifndef A_SYMBOL
+#define A_SYMBOL A_SYM
+#endif
+
+
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+
+extern "C" {
+ // Wow, the jMax developers made excessive use of C++ reserved words
+ // good hit!
+ #define typeid c_typeid_
+ #define template c_template_
+ #define this c_this_
+ #define class c_class_
+
+ #include <fts/fts.h>
+
+ // undefine them again
+ #undef typeid
+ #undef template
+ #undef this
+ #undef class
+}
+
+typedef fts_dsp_object t_sigobj;
+typedef void t_canvas; // decide type later on
+
+typedef char t_symbol;
+typedef fts_atom_t t_atom;
+typedef fts_class_t t_class;
+typedef float t_sample; // is there no sample type in jMax?
+
+typedef fts_timebase_entry_t t_clock;
+typedef fts_timebase_entry_t t_qelem;
+
+#endif // FLEXT_SYS
+
+
+// general definitions
+
+typedef t_symbol *t_symptr;
+
+
+// -------------------------
+
+#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 FLEXT_DEBUG
+#define FLEXT_ASSERT(b) ((void)(!(b)?(error("Assertion failed: " #b " - in " __FILE__ " line %i",(int)__LINE__),0):0))
+#else
+#define FLEXT_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 */
+
+#ifdef _MSC_VER
+ #ifdef FLEXT_SHARED
+ #define FLEXT_SHARE __declspec(dllexport)
+ #else
+ #define FLEXT_SHARE
+ #endif
+ #define FLEXT_EXT __declspec(dllexport)
+#else // other OS's
+ #define FLEXT_SHARE
+ #define FLEXT_EXT
+#endif
+
+#endif
diff --git a/externals/grill/flext/source/flstk.cpp b/externals/grill/flext/source/flstk.cpp index 58fd192e..42f2fa85 100644 --- a/externals/grill/flext/source/flstk.cpp +++ b/externals/grill/flext/source/flstk.cpp @@ -95,12 +95,6 @@ flext_stk::Input::Input(const t_sample *b,int v): index(0) {} -MY_FLOAT flext_stk::Input::tick() -{ - if(++index >= vecsz) index = 0; - return lastOut(); -} - MY_FLOAT *flext_stk::Input::tick(MY_FLOAT *vector,unsigned int vectorSize) { for(unsigned int i = 0; i < vectorSize; i++) vector[i] = tick(); @@ -115,12 +109,6 @@ flext_stk::Output::Output(t_sample *b,int v): index(0) {} -void flext_stk::Output::tick(MY_FLOAT s) -{ - buf[index] = (t_sample)s; - if(++index >= vecsz) index = 0; -} - void flext_stk::Output::tick(const MY_FLOAT *vector,unsigned int vectorSize) { for(unsigned int i = 0; i < vectorSize; i++) tick(vector[i]); diff --git a/externals/grill/flext/source/flstk.h b/externals/grill/flext/source/flstk.h index 11d8ec6b..d6bad079 100644 --- a/externals/grill/flext/source/flstk.h +++ b/externals/grill/flext/source/flstk.h @@ -38,11 +38,16 @@ protected: public: Input(const t_sample *b,int vecsz); - MY_FLOAT lastOut() const { return (MY_FLOAT)buf[index]; } - MY_FLOAT tick(); + inline MY_FLOAT lastOut() const { return (MY_FLOAT)buf[index]; } + + inline MY_FLOAT tick() { + if(++index >= vecsz) index = 0; + return lastOut(); + } + MY_FLOAT *tick(MY_FLOAT *vector,unsigned int vectorSize); - void SetBuf(const t_sample *b) { buf = b; } + inline void SetBuf(const t_sample *b) { buf = b; } private: const t_sample *buf; @@ -56,10 +61,14 @@ protected: public: Output(t_sample *b,int vecsz); - void tick(MY_FLOAT sample); + inline void tick(MY_FLOAT s) { + buf[index] = (t_sample)s; + if(++index >= vecsz) index = 0; + } + void tick(const MY_FLOAT *vector,unsigned int vectorSize); - void SetBuf(t_sample *b) { buf = b; } + inline void SetBuf(t_sample *b) { buf = b; } private: t_sample *buf; diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp index f3309ab0..115e0ee6 100644 --- a/externals/grill/flext/source/flsupport.cpp +++ b/externals/grill/flext/source/flsupport.cpp @@ -1,156 +1,157 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2003 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 "flext.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_pointer = NULL; -const t_symbol *flext::sym_int = NULL; - -#if FLEXT_SYS != FLEXT_SYS_JMAX -const t_symbol *flext::sym_anything = NULL; -#endif - -#if FLEXT_SYS == FLEXT_SYS_PD -const t_symbol *flext::sym_signal = NULL; -#endif - -void flext::Setup() -{ -#if FLEXT_SYS == FLEXT_SYS_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 FLEXT_SYS == FLEXT_SYS_MAX - sym_int = gensym("int"); - sym_float = gensym("float"); - sym_symbol = gensym("symbol"); - sym_bang = gensym("bang"); - sym_list = gensym("list"); - sym_anything = gensym("anything"); -#elif FLEXT_SYS == FLEXT_SYS_JMAX - sym_int = fts_s_int; - sym_float = fts_s_float; - sym_symbol = fts_s_symbol; - sym_bang = fts_s_bang; - sym_list = fts_s_list; - sym_pointer = fts_s_pointer; -#else -#endif -} - - -///////////////////////////////////////////////////////// -// overloaded new/delete memory allocation methods -// -///////////////////////////////////////////////////////// - -void *flext::operator new(size_t bytes) -{ - bytes += sizeof(size_t); -#if FLEXT_SYS == FLEXT_SYS_JMAX - char *blk = (char *)::fts_malloc(bytes); -#else - char *blk = (char *)::getbytes(bytes); -#endif - *(size_t *)blk = bytes; - return blk+sizeof(size_t); -} - -void flext::operator delete(void *blk) -{ - char *ori = (char *)blk-sizeof(size_t); -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_free(ori); -#else - size_t bytes = *(size_t *)ori; - ::freebytes(ori,bytes); -#endif -} - -void *flext::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; -#if FLEXT_SYS == FLEXT_SYS_JMAX - char *blk = (char *)::fts_malloc(bytes); -#else - char *blk = (char *)::getbytes(bytes); -#endif - 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::FreeAligned(void *blk) -{ - char *ori = *(char **)((char *)blk-sizeof(size_t)-sizeof(char *)); - -#if FLEXT_SYS == FLEXT_SYS_JMAX - fts_free(ori); -#else - size_t bytes = *(size_t *)((char *)blk-sizeof(size_t)); - ::freebytes(ori,bytes); -#endif -} - -// ------------------------------------------ - -//! \todo there is probably also a shortcut for Max and jMax -void flext::GetAString(const t_atom &a,char *buf,int szbuf) -{ -#if FLEXT_SYS == FLEXT_SYS_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 -} - -unsigned long flext::AtomHash(const t_atom &a) -{ -#if FLEXT_SYS == FLEXT_SYS_MAX || FLEXT_SYS == FLEXT_SYS_PD - return ((unsigned long)a.a_type<<28)^*(unsigned long *)&a.a_w; -#else -#error Not implemented -#endif -} - -unsigned int flext::FoldBits(unsigned long h,int bits) -{ - if(!bits) return 0; - const int hmax = (1<<bits)-1; - unsigned int ret = 0; - for(unsigned int i = 0; i < sizeof(h)*8; i += bits) - ret ^= (h>>i)&hmax; - return ret; -} - -int flext::Int2Bits(unsigned long n) -{ - int b; - for(b = 0; n; ++b) n >>= 1; - return b; -} - +/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 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 "flext.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_pointer = NULL;
+const t_symbol *flext::sym_int = NULL;
+
+#if FLEXT_SYS != FLEXT_SYS_JMAX
+const t_symbol *flext::sym_anything = NULL;
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+const t_symbol *flext::sym_signal = NULL;
+#endif
+
+void flext::Setup()
+{
+#if FLEXT_SYS == FLEXT_SYS_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 FLEXT_SYS == FLEXT_SYS_MAX
+ sym_int = gensym("int");
+ sym_float = gensym("float");
+ sym_symbol = gensym("symbol");
+ sym_bang = gensym("bang");
+ sym_list = gensym("list");
+ sym_anything = gensym("anything");
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ sym_int = fts_s_int;
+ sym_float = fts_s_float;
+ sym_symbol = fts_s_symbol;
+ sym_bang = fts_s_bang;
+ sym_list = fts_s_list;
+ sym_pointer = fts_s_pointer;
+#else
+#endif
+}
+
+
+/////////////////////////////////////////////////////////
+// overloaded new/delete memory allocation methods
+//
+/////////////////////////////////////////////////////////
+
+void *flext::operator new(size_t bytes)
+{
+ bytes += sizeof(size_t);
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ char *blk = (char *)::fts_malloc(bytes);
+#else
+ char *blk = (char *)::getbytes(bytes);
+#endif
+ *(size_t *)blk = bytes;
+ return blk+sizeof(size_t);
+}
+
+void flext::operator delete(void *blk)
+{
+ char *ori = (char *)blk-sizeof(size_t);
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_free(ori);
+#else
+ size_t bytes = *(size_t *)ori;
+ ::freebytes(ori,bytes);
+#endif
+}
+
+void *flext::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;
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ char *blk = (char *)::fts_malloc(bytes);
+#else
+ char *blk = (char *)::getbytes(bytes);
+#endif
+ 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::FreeAligned(void *blk)
+{
+ char *ori = *(char **)((char *)blk-sizeof(size_t)-sizeof(char *));
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ fts_free(ori);
+#else
+ size_t bytes = *(size_t *)((char *)blk-sizeof(size_t));
+ ::freebytes(ori,bytes);
+#endif
+}
+
+// ------------------------------------------
+
+//! \todo there is probably also a shortcut for Max and jMax
+void flext::GetAString(const t_atom &a,char *buf,int szbuf)
+{
+#if FLEXT_SYS == FLEXT_SYS_PD
+ atom_string(const_cast<t_atom *>(&a),buf,szbuf);
+#else
+ if(IsSymbol(a)) snprintf(buf,szbuf,GetString(a));
+ else if(IsFloat(a)) snprintf(buf,szbuf,"%f",GetFloat(a));
+ else if(IsInt(a)) snprintf(buf,szbuf,"%i",GetInt(a));
+ else strncpy(buf,"",szbuf);
+#endif
+}
+
+unsigned long flext::AtomHash(const t_atom &a)
+{
+#if FLEXT_SYS == FLEXT_SYS_MAX || FLEXT_SYS == FLEXT_SYS_PD
+ return ((unsigned long)a.a_type<<28)^*(unsigned long *)&a.a_w;
+#else
+#error Not implemented
+#endif
+}
+
+unsigned int flext::FoldBits(unsigned long h,int bits)
+{
+ if(!bits) return 0;
+ const int hmax = (1<<bits)-1;
+ unsigned int ret = 0;
+ for(unsigned int i = 0; i < sizeof(h)*8; i += bits)
+ ret ^= (h>>i)&hmax;
+ return ret;
+}
+
+int flext::Int2Bits(unsigned long n)
+{
+ int b;
+ for(b = 0; n; ++b) n >>= 1;
+ return b;
+}
+
diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index 497351d2..8202922c 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -1,839 +1,839 @@ -/* - -flext - C++ layer for Max/MSP and pd (pure data) externals - -Copyright (c) 2001-2003 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" -#include <time.h> - -class FLEXT_SHARE flext_base; - -/*! \brief Flext support class - A number of methods (most are static functions) are defined here for convenience. - This class doesn't define any data members, hence it can be inherited to all - classes (not only PD objects) to profit from the cross-platform functionality. - Examples are the overloaded memory allocation, atom and atom list functions, - thread functions and classes, the sample buffer class and others. -*/ -class FLEXT_SHARE flext { - - /*! \defgroup FLEXT_SUPPORT Flext support class - @{ - */ -public: - -// --- console output ----------------------------------------------- - -#if FLEXT_SYS == FLEXT_SYS_JMAX - //! post message to console - static void post(const char *s,...); - //! post error message to console - static void error(const char *s,...); -#endif - -// --- memory ------------------------------------------------------- - - /*! \defgroup FLEXT_S_MEMORY Memory allocation functions - @{ - */ - - /*! Overloaded new memory allocation method - \warning Max/MSP (or MacOS) allows only 16K in overdrive mode! - */ - void *operator new(size_t bytes); - //! Overloaded delete method - 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 - - //! Get an aligned memory block - static void *NewAligned(size_t bytes,int bitalign = 128); - //! Free an aligned memory block - static void FreeAligned(void *blk); - - //! @} FLEXT_S_MEMORY - -// --- buffer/array stuff ----------------------------------------- - - /*! \defgroup FLEXT_S_BUFFER Buffer handling - @{ - */ - -// not for Jmax at the moment -#if FLEXT_SYS != FLEXT_SYS_JMAX - - //! Class for platform independent buffer handling - class FLEXT_SHARE buffer - { - public: - /*! \brief Construct buffer. - \param s: symbol name, can be NULL - \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 if buffer is valid - */ - bool Valid() const; - - /*! \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?GetString(sym):""; } - - /*! \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; -#if FLEXT_SYS == FLEXT_SYS_PD - t_garray *arr; - float interval; - bool isdirty,ticking; - t_clock *tick; - - private: - static void cb_tick(buffer *b); -#endif - }; - -#endif // jmax - -//! @} FLEXT_S_BUFFER - -// --- utilities -------------------------------------------------- - - /*! \defgroup FLEXT_S_UTIL Utility functions - @{ - */ - - //! Copy an atom - static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; } - - //! Print an atom - static void PrintAtom(const t_atom &a,char *buf); - //! Scan an atom - static bool ScanAtom(t_atom &a,const char *buf); - - //! 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); - static void CopySamples(t_sample *dst,const t_sample *src,int cnt); - //! Set a memory region - static void ZeroMem(void *dst,int bytes); - static void SetSamples(t_sample *dst,int cnt,t_sample s); - static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); } - - //! Sleep for an amount of time - static void Sleep(double s); - - - //! Get a 32 bit hash value frm an atom - static unsigned long AtomHash(const t_atom &a); - - /*! \brief Fold value to a number of bits - \remark Good for hash tables - */ - static unsigned int FoldBits(unsigned long h,int bits); - - //! \brief How many bits are necessary to represent n - static int Int2Bits(unsigned long n); - -//! @} FLEXT_S_UTIL - -// --- various symbols -------------------------------------------- - - /*! \defgroup FLEXT_S_ATOM Atom/list 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; - -#if FLEXT_SYS == FLEXT_SYS_PD - /*! \brief Symbol constant for "signal" - \note PD only - */ - static const t_symbol *sym_signal; -#endif - -#if FLEXT_SYS == FLEXT_SYS_JMAX - //! Make a symbol from a string - static const t_symbol *MakeSymbol(const char *s) { return ::fts_new_symbol(s); } - //! Get symbol string - static const char *GetString(const t_symbol *s); // ** TODO ** -#else - //! 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; } -#endif - //! Check for symbol and get string - static const char *GetAString(const t_symbol *s,const char *def = "") { return s?GetString(s):def; } - -// --- atom stuff ---------------------------------------- - - //! Set atom from another atom - static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); } - -#if FLEXT_SYS == FLEXT_SYS_JMAX - //! Set atom from another atom - static int GetType(const t_atom &a); // ** TODO ** - - //! Check whether the atom is nothing - static bool IsNothing(const t_atom &a) { return fts_is_a(&a,fts_void_class); } - //! Set the atom to represent nothing - static void SetNothing(t_atom &a) { fts_set_void(&a); } - - //! Check whether the atom is a float - static bool IsFloat(const t_atom &a) { return fts_is_a(&a,fts_float_class); } -#else - //! Set atom from another atom - static int GetType(const t_atom &a) { return a.a_type; } - - //! 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; } -#endif - - //! Check whether the atom can be represented as a float - static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); } - -#if FLEXT_SYS == FLEXT_SYS_JMAX - //! Access the float value (without type check) - static float GetFloat(const t_atom &a) { return fts_get_float(&a); } - //! Set the atom to represent a float - static void SetFloat(t_atom &a,float v) { fts_set_float(&a,v); } - - //! Check whether the atom is a symbol - static bool IsSymbol(const t_atom &a) { return fts_is_a(&a,fts_symbol_class); } -#else - //! 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; } -#endif - -#if FLEXT_SYS == FLEXT_SYS_PD - //! Access the symbol value (without type check) - static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_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); } -#elif FLEXT_SYS == FLEXT_SYS_MAX - //! Access the symbol value (without type check) - static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_sym; } - //! 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_sym = const_cast<t_symbol *>(s); } -#elif FLEXT_SYS == FLEXT_SYS_JMAX - //! Access the symbol value (without type check) - static t_symbol *GetSymbol(const t_atom &a); // ** TODO ** - //! Set the atom to represent a symbol - static void SetSymbol(t_atom &a,const t_symbol *s) { fts_set_symbol(&a,s); } -#else -#error -#endif - //! Check for a symbol and get its value - static t_symbol *GetASymbol(const t_atom &a,t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol? - - //! 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,MakeSymbol(c)); } - - //! Check whether the atom can be represented as an integer - static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); } - - //! Set the atom to represent a boolean - static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); } - //! 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; } - -#if FLEXT_SYS == FLEXT_SYS_PD - //! Check for a float and get its value - static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; } - - //! 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,int def = 0) { return (int)GetAFloat(a,(float)def); } - //! 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 strictly is a pointer - static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; } - //! Check whether the atom can be a pointer - static bool CanbePointer(const t_atom &a) { return IsPointer(a); } - //! Access the pointer value (without type check) - static void *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; } - //! Check for a pointer and get its value - static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; } - //! Set the atom to represent a pointer - static void SetPointer(t_atom &a,void *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; } - -#elif FLEXT_SYS == FLEXT_SYS_MAX - //! Check for a float and get its value - static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); } - - //! 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,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); } - //! 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 strictly is a pointer - static bool IsPointer(const t_atom &) { return false; } - //! Check whether the atom can be a pointer - static bool CanbePointer(const t_atom &a) { return IsInt(a); } - //! 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 &a,void *def = NULL) { return IsInt(a)?(void *)GetInt(a):def; } - //! Set the atom to represent a pointer - static void SetPointer(t_atom &a,void *p) { SetInt(a,(int)p); } -#elif FLEXT_SYS == FLEXT_SYS_JMAX - //! Check for a float and get its value - static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); } - - //! Check whether the atom is an int - static bool IsInt(const t_atom &a) { return fts_is_a(&a,fts_int_class); } - //! Access the integer value (without type check) - static int GetInt(const t_atom &a) { return fts_get_int(&a); } - //! Check for an integer and get its value - static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); } - //! Set the atom to represent an integer - static void SetInt(t_atom &a,int v) { fts_set_int(&a,v); } - - //! Check whether the atom strictly is a pointer - static bool IsPointer(const t_atom &a) { return fts_is_a(&a,fts_pointer_class); } - //! Check whether the atom can be a pointer - static bool CanbePointer(const t_atom &a) { return IsPointer(a); } - //! Access the pointer value (without type check) - static void *GetPointer(const t_atom &a) { return fts_get_pointer(&a); } - //! Check for a pointer and get its value - static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; } - //! Set the atom to represent a pointer - static void SetPointer(t_atom &a,void *p) { fts_set_pointer(&a,p); } -#else -#error "Platform not supported" -#endif - -// --- atom list stuff ------------------------------------------- - - //! Class representing a list of atoms - class FLEXT_SHARE 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 &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false); - //! Get list - int Get(t_atom *argv,int mxsz = -1) const; - - //! Set list - AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); } - //! 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 = NULL); - //! 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 = NULL); - //! 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 FLEXT_SHARE AtomAnything: - public AtomList - { - public: -#if FLEXT_SYS != FLEXT_SYS_JMAX - //! Construct anything - AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL); -#endif - //! Construct anything - AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL); - //! Construct anything - AtomAnything(const AtomAnything &a); - - //! Clear anything - AtomAnything &Clear() { return operator()(); } - - //! Get header symbol of anything - const t_symbol *Header() const { return hdr; } - - //! Set header symbol of anything - void Header(const t_symbol *h) { hdr = h; } - - //! 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; - }; - -//! @} FLEXT_S_ATOM - - -// --- clock stuff ------------------------------------------------ - - - /*! \defgroup FLEXT_S_CLOCK Flext clock functions - - At the moment there are none - - @{ - */ - -//! @} - - -// --- thread stuff ----------------------------------------------- - -#ifdef FLEXT_THREADS - /*! \defgroup FLEXT_S_THREAD Flext thread handling - @{ - */ - - //! thread type -#if FLEXT_THREADS == FLEXT_THR_MP - typedef MPTaskID thrid_t; -#elif FLEXT_THREADS == FLEXT_THR_POSIX - typedef pthread_t thrid_t; -#else -#error -#endif - - /*! \brief Get current thread id - */ - static thrid_t GetThreadId() { -#if FLEXT_THREADS == FLEXT_THR_POSIX - return pthread_self(); -#elif FLEXT_THREADS == FLEXT_THR_MP - return MPCurrentTaskID(); -#else -#error -#endif - } - - /*! \brief Get system thread id - */ - static thrid_t GetSysThreadId() { return thrid; } - - //! Check if current thread is the realtime system's thread - static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) { -#if FLEXT_THREADS == FLEXT_THR_POSIX - return pthread_equal(ref,t) != 0; -#else - return ref == t; -#endif - } - - //! Check if current thread is the realtime system's thread - static bool IsSystemThread() { return IsThread(GetSysThreadId()); } - - - /*! \brief Thread parameters - \internal - */ - class thr_params - { - public: - thr_params(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; - }; - - /*! \brief This represents an entry to the list of active method threads - \internal - */ - class thr_entry - { - public: - thr_entry(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId()); - - //! \brief Check if this class represents the current thread - bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); } - - flext_base *This() const { return th; } - thrid_t Id() const { return thrid; } - - flext_base *th; - void (*meth)(thr_params *); - thr_params *params; - thrid_t thrid; - bool active,shouldexit; -#if FLEXT_THREADS == FLEXT_THR_MP - int weight; -#endif - thr_entry *nxt; - }; - -protected: - - static thrid_t thrhelpid; - static bool StartHelper(); - static bool StopHelper(); - static void ThrHelper(void *); - - //! system's thread id - static thrid_t thrid; // the system thread - -public: - - /*! \brief Yield to other threads - \remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9 - */ - static void ThrYield() { -#if FLEXT_THREADS == FLEXT_THR_POSIX - sched_yield(); -#elif FLEXT_THREADS == FLEXT_THR_MP - MPYield(); -#else -#error -#endif - } - - /*! \brief Query whether task is preemptive - */ - static bool IsThreadPreemptive(thrid_t t = GetThreadId()) { -#if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32 - return true; -#elif FLEXT_THREADS == FLEXT_THR_MP - return MPTaskIsPreemptive(t); -#else -#error -#endif - } - - - /*! \brief Increase/Decrease priority of a thread - */ - static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),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 Thread mutex - \sa pthreads documentation - */ - class FLEXT_SHARE ThrMutex -#if FLEXT_THREADS == FLEXT_THR_POSIX - { - public: - //! Construct thread mutex - ThrMutex() /*: cnt(0)*/ { pthread_mutex_init(&mutex,NULL); } - //! Destroy thread mutex - ~ThrMutex() { pthread_mutex_destroy(&mutex); } - - //! Lock thread mutex - bool Lock() { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; } - //! Lock thread mutex - bool WaitForLock(float tm) { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; } - //! Try to lock, but don't wait - bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; } - //! Unlock thread mutex - bool Unlock() { /*cnt = 0;*/ return pthread_mutex_unlock(&mutex) == 0; } -/* - //! 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; - }; -#elif FLEXT_THREADS == FLEXT_THR_MP - { - public: - //! Construct thread mutex - ThrMutex() /*: cnt(0)*/ { MPCreateCriticalRegion(&crit); } - //! Destroy thread mutex - ~ThrMutex() { MPDeleteCriticalRegion(crit); } - - //! Lock thread mutex - bool Lock() { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,kDurationForever) == noErr; } - //! Wait to lock thread mutex - bool WaitForLock(float tm) { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; } - //! Try to lock, but don't wait - bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; } - //! Unlock thread mutex - bool Unlock() { /*cnt = 0;*/ return MPExitCriticalRegion(crit) == noErr; } - - protected: - MPCriticalRegionID crit; - }; -#else -#error "Not implemented" -#endif - - /*! \brief Thread conditional - \sa pthreads documentation - */ - class FLEXT_SHARE ThrCond -#if FLEXT_THREADS == FLEXT_THR_POSIX - :public ThrMutex - { - public: - //! Construct thread conditional - ThrCond() { pthread_cond_init(&cond,NULL); } - //! Destroy thread conditional - ~ThrCond() { pthread_cond_destroy(&cond); } - - //! Wait for condition - bool Wait() { - Lock(); - bool ret = pthread_cond_wait(&cond,&mutex) == 0; - Unlock(); - return ret; - } - - /*! \brief Wait for condition (for a certain time) - \param ftime Wait time in seconds - \ret 0 = signalled, 1 = timed out - \remark Depending on the implementation ftime may not be fractional. - \remark So if ftime = 0 this may suck away your cpu if used in a signalled loop. - */ - bool TimedWait(float ftime) - { - timespec tm; -#if 0 // find out when the following is defined - clock_gettime(CLOCK_REALTIME,tm); - tm.tv_nsec += (long)((ftime-(long)ftime)*1.e9); - long nns = tm.tv_nsec%1000000000; - tm.tv_sec += (long)ftime+(tm.tv_nsec-nns)/1000000000; - tm.tv_nsec = nns; -#else - tm.tv_sec = time(NULL)+(long)ftime; - tm.tv_nsec = 0; -#endif - Lock(); - bool ret = pthread_cond_timedwait(&cond,&mutex,&tm) == 0; - Unlock(); - return ret; - } - - //! Signal condition - bool Signal() - { - Lock(); - bool ret = pthread_cond_signal(&cond) == 0; - Unlock(); - return ret; - } - //! Broadcast condition -// int Broadcast() { return pthread_cond_broadcast(&cond); } - protected: - pthread_cond_t cond; - }; -#elif FLEXT_THREADS == FLEXT_THR_MP - { - public: - //! Construct thread conditional - ThrCond() { MPCreateEvent(&ev); } - //! Destroy thread conditional - ~ThrCond() { MPDeleteEvent(ev); } - - //! Wait for condition - bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; } - - /*! \brief Wait for condition (for a certain time) - \param time Wait time in seconds - */ - bool TimedWait(float tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; } - - //! Signal condition - bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least - //! Broadcast condition -// int Broadcast() { return pthread_cond_broadcast(&cond); } - protected: - MPEventID ev; - }; -#else -#error "Not implemented" -#endif - - /*! \brief Add current thread to list of active threads - \return true on success - \internal - */ - static bool PushThread(); - - /*! \brief Remove current thread from list of active threads - \internal - */ - static void PopThread(); - - /*! \brief Launch a thread - \remark thr_params *p may be NULL if not needed - */ - static bool LaunchThread(void (*meth)(thr_params *p),thr_params *p); - -//! @} FLEXT_S_THREAD - -#endif // FLEXT_THREADS - -//! @} - -protected: -#ifdef __MRC__ - friend class flext_obj; -#endif - static void Setup(); - - static bool chktilde(const char *objname); -}; - -#endif +/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 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"
+#include <time.h>
+
+class FLEXT_SHARE flext_base;
+
+/*! \brief Flext support class
+ A number of methods (most are static functions) are defined here for convenience.
+ This class doesn't define any data members, hence it can be inherited to all
+ classes (not only PD objects) to profit from the cross-platform functionality.
+ Examples are the overloaded memory allocation, atom and atom list functions,
+ thread functions and classes, the sample buffer class and others.
+*/
+class FLEXT_SHARE flext {
+
+ /*! \defgroup FLEXT_SUPPORT Flext support class
+ @{
+ */
+public:
+
+// --- console output -----------------------------------------------
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! post message to console
+ static void post(const char *s,...);
+ //! post error message to console
+ static void error(const char *s,...);
+#endif
+
+// --- memory -------------------------------------------------------
+
+ /*! \defgroup FLEXT_S_MEMORY Memory allocation functions
+ @{
+ */
+
+ /*! Overloaded new memory allocation method
+ \warning Max/MSP (or MacOS) allows only 16K in overdrive mode!
+ */
+ void *operator new(size_t bytes);
+ //! Overloaded delete method
+ 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
+
+ //! Get an aligned memory block
+ static void *NewAligned(size_t bytes,int bitalign = 128);
+ //! Free an aligned memory block
+ static void FreeAligned(void *blk);
+
+ //! @} FLEXT_S_MEMORY
+
+// --- buffer/array stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_S_BUFFER Buffer handling
+ @{
+ */
+
+// not for Jmax at the moment
+#if FLEXT_SYS != FLEXT_SYS_JMAX
+
+ //! Class for platform independent buffer handling
+ class FLEXT_SHARE buffer
+ {
+ public:
+ /*! \brief Construct buffer.
+ \param s: symbol name, can be NULL
+ \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 if buffer is valid
+ */
+ bool Valid() const;
+
+ /*! \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?GetString(sym):""; }
+
+ /*! \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;
+#if FLEXT_SYS == FLEXT_SYS_PD
+ t_garray *arr;
+ float interval;
+ bool isdirty,ticking;
+ t_clock *tick;
+
+ private:
+ static void cb_tick(buffer *b);
+#endif
+ };
+
+#endif // jmax
+
+//! @} FLEXT_S_BUFFER
+
+// --- utilities --------------------------------------------------
+
+ /*! \defgroup FLEXT_S_UTIL Utility functions
+ @{
+ */
+
+ //! Copy an atom
+ static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
+
+ //! Print an atom
+ static void PrintAtom(const t_atom &a,char *buf,int bufsz = 0);
+ //! Scan an atom
+ static bool ScanAtom(t_atom &a,const char *buf);
+
+ //! 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);
+ static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
+ //! Set a memory region
+ static void ZeroMem(void *dst,int bytes);
+ static void SetSamples(t_sample *dst,int cnt,t_sample s);
+ static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
+
+ //! Sleep for an amount of time
+ static void Sleep(double s);
+
+
+ //! Get a 32 bit hash value frm an atom
+ static unsigned long AtomHash(const t_atom &a);
+
+ /*! \brief Fold value to a number of bits
+ \remark Good for hash tables
+ */
+ static unsigned int FoldBits(unsigned long h,int bits);
+
+ //! \brief How many bits are necessary to represent n
+ static int Int2Bits(unsigned long n);
+
+//! @} FLEXT_S_UTIL
+
+// --- various symbols --------------------------------------------
+
+ /*! \defgroup FLEXT_S_ATOM Atom/list 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;
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ /*! \brief Symbol constant for "signal"
+ \note PD only
+ */
+ static const t_symbol *sym_signal;
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Make a symbol from a string
+ static const t_symbol *MakeSymbol(const char *s) { return ::fts_new_symbol(s); }
+ //! Get symbol string
+ static const char *GetString(const t_symbol *s); // ** TODO **
+#else
+ //! 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; }
+#endif
+ //! Check for symbol and get string
+ static const char *GetAString(const t_symbol *s,const char *def = "") { return s?GetString(s):def; }
+
+// --- atom stuff ----------------------------------------
+
+ //! Set atom from another atom
+ static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Set atom from another atom
+ static int GetType(const t_atom &a); // ** TODO **
+
+ //! Check whether the atom is nothing
+ static bool IsNothing(const t_atom &a) { return fts_is_a(&a,fts_void_class); }
+ //! Set the atom to represent nothing
+ static void SetNothing(t_atom &a) { fts_set_void(&a); }
+
+ //! Check whether the atom is a float
+ static bool IsFloat(const t_atom &a) { return fts_is_a(&a,fts_float_class); }
+#else
+ //! Set atom from another atom
+ static int GetType(const t_atom &a) { return a.a_type; }
+
+ //! 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; }
+#endif
+
+ //! Check whether the atom can be represented as a float
+ static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Access the float value (without type check)
+ static float GetFloat(const t_atom &a) { return fts_get_float(&a); }
+ //! Set the atom to represent a float
+ static void SetFloat(t_atom &a,float v) { fts_set_float(&a,v); }
+
+ //! Check whether the atom is a symbol
+ static bool IsSymbol(const t_atom &a) { return fts_is_a(&a,fts_symbol_class); }
+#else
+ //! 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; }
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_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); }
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_sym; }
+ //! 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_sym = const_cast<t_symbol *>(s); }
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a); // ** TODO **
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { fts_set_symbol(&a,s); }
+#else
+#error
+#endif
+ //! Check for a symbol and get its value
+ static t_symbol *GetASymbol(const t_atom &a,t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
+
+ //! 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,MakeSymbol(c)); }
+
+ //! Check whether the atom can be represented as an integer
+ static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+ //! Set the atom to represent a boolean
+ static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
+ //! 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; }
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
+
+ //! 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,int def = 0) { return (int)GetAFloat(a,(float)def); }
+ //! 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 strictly is a pointer
+ static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
+
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
+
+ //! 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,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
+ //! 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 strictly is a pointer
+ static bool IsPointer(const t_atom &) { return false; }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsInt(a); }
+ //! 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 &a,void *def = NULL) { return IsInt(a)?(void *)GetInt(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { SetInt(a,(int)p); }
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
+
+ //! Check whether the atom is an int
+ static bool IsInt(const t_atom &a) { return fts_is_a(&a,fts_int_class); }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return fts_get_int(&a); }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
+ //! Set the atom to represent an integer
+ static void SetInt(t_atom &a,int v) { fts_set_int(&a,v); }
+
+ //! Check whether the atom strictly is a pointer
+ static bool IsPointer(const t_atom &a) { return fts_is_a(&a,fts_pointer_class); }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &a) { return fts_get_pointer(&a); }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { fts_set_pointer(&a,p); }
+#else
+#error "Platform not supported"
+#endif
+
+// --- atom list stuff -------------------------------------------
+
+ //! Class representing a list of atoms
+ class FLEXT_SHARE 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 &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
+ //! Get list
+ int Get(t_atom *argv,int mxsz = -1) const;
+
+ //! Set list
+ AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
+ //! 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 = NULL);
+ //! 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 = NULL);
+ //! 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 FLEXT_SHARE AtomAnything:
+ public AtomList
+ {
+ public:
+#if FLEXT_SYS != FLEXT_SYS_JMAX
+ //! Construct anything
+ AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL);
+#endif
+ //! Construct anything
+ AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL);
+ //! Construct anything
+ AtomAnything(const AtomAnything &a);
+
+ //! Clear anything
+ AtomAnything &Clear() { return operator()(); }
+
+ //! Get header symbol of anything
+ const t_symbol *Header() const { return hdr; }
+
+ //! Set header symbol of anything
+ void Header(const t_symbol *h) { hdr = h; }
+
+ //! 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;
+ };
+
+//! @} FLEXT_S_ATOM
+
+
+// --- clock stuff ------------------------------------------------
+
+
+ /*! \defgroup FLEXT_S_CLOCK Flext clock functions
+
+ At the moment there are none
+
+ @{
+ */
+
+//! @}
+
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ /*! \defgroup FLEXT_S_THREAD Flext thread handling
+ @{
+ */
+
+ //! thread type
+#if FLEXT_THREADS == FLEXT_THR_MP
+ typedef MPTaskID thrid_t;
+#elif FLEXT_THREADS == FLEXT_THR_POSIX
+ typedef pthread_t thrid_t;
+#else
+#error
+#endif
+
+ /*! \brief Get current thread id
+ */
+ static thrid_t GetThreadId() {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ return pthread_self();
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ return MPCurrentTaskID();
+#else
+#error
+#endif
+ }
+
+ /*! \brief Get system thread id
+ */
+ static thrid_t GetSysThreadId() { return thrid; }
+
+ //! Check if current thread is the realtime system's thread
+ static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ return pthread_equal(ref,t) != 0;
+#else
+ return ref == t;
+#endif
+ }
+
+ //! Check if current thread is the realtime system's thread
+ static bool IsSystemThread() { return IsThread(GetSysThreadId()); }
+
+
+ /*! \brief Thread parameters
+ \internal
+ */
+ class thr_params
+ {
+ public:
+ thr_params(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;
+ };
+
+ /*! \brief This represents an entry to the list of active method threads
+ \internal
+ */
+ class thr_entry
+ {
+ public:
+ thr_entry(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId());
+
+ //! \brief Check if this class represents the current thread
+ bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); }
+
+ flext_base *This() const { return th; }
+ thrid_t Id() const { return thrid; }
+
+ flext_base *th;
+ void (*meth)(thr_params *);
+ thr_params *params;
+ thrid_t thrid;
+ bool active,shouldexit;
+#if FLEXT_THREADS == FLEXT_THR_MP
+ int weight;
+#endif
+ thr_entry *nxt;
+ };
+
+protected:
+
+ static thrid_t thrhelpid;
+ static bool StartHelper();
+ static bool StopHelper();
+ static void ThrHelper(void *);
+
+ //! system's thread id
+ static thrid_t thrid; // the system thread
+
+public:
+
+ /*! \brief Yield to other threads
+ \remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
+ */
+ static void ThrYield() {
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ sched_yield();
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ MPYield();
+#else
+#error
+#endif
+ }
+
+ /*! \brief Query whether task is preemptive
+ */
+ static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
+#if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
+ return true;
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ return MPTaskIsPreemptive(t);
+#else
+#error
+#endif
+ }
+
+
+ /*! \brief Increase/Decrease priority of a thread
+ */
+ static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),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 Thread mutex
+ \sa pthreads documentation
+ */
+ class FLEXT_SHARE ThrMutex
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ {
+ public:
+ //! Construct thread mutex
+ ThrMutex() /*: cnt(0)*/ { pthread_mutex_init(&mutex,NULL); }
+ //! Destroy thread mutex
+ ~ThrMutex() { pthread_mutex_destroy(&mutex); }
+
+ //! Lock thread mutex
+ bool Lock() { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
+ //! Lock thread mutex
+ bool WaitForLock(float tm) { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
+ //! Try to lock, but don't wait
+ bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
+ //! Unlock thread mutex
+ bool Unlock() { /*cnt = 0;*/ return pthread_mutex_unlock(&mutex) == 0; }
+/*
+ //! 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;
+ };
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ {
+ public:
+ //! Construct thread mutex
+ ThrMutex() /*: cnt(0)*/ { MPCreateCriticalRegion(&crit); }
+ //! Destroy thread mutex
+ ~ThrMutex() { MPDeleteCriticalRegion(crit); }
+
+ //! Lock thread mutex
+ bool Lock() { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
+ //! Wait to lock thread mutex
+ bool WaitForLock(float tm) { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
+ //! Try to lock, but don't wait
+ bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
+ //! Unlock thread mutex
+ bool Unlock() { /*cnt = 0;*/ return MPExitCriticalRegion(crit) == noErr; }
+
+ protected:
+ MPCriticalRegionID crit;
+ };
+#else
+#error "Not implemented"
+#endif
+
+ /*! \brief Thread conditional
+ \sa pthreads documentation
+ */
+ class FLEXT_SHARE ThrCond
+#if FLEXT_THREADS == FLEXT_THR_POSIX
+ :public ThrMutex
+ {
+ public:
+ //! Construct thread conditional
+ ThrCond() { pthread_cond_init(&cond,NULL); }
+ //! Destroy thread conditional
+ ~ThrCond() { pthread_cond_destroy(&cond); }
+
+ //! Wait for condition
+ bool Wait() {
+ Lock();
+ bool ret = pthread_cond_wait(&cond,&mutex) == 0;
+ Unlock();
+ return ret;
+ }
+
+ /*! \brief Wait for condition (for a certain time)
+ \param ftime Wait time in seconds
+ \ret 0 = signalled, 1 = timed out
+ \remark Depending on the implementation ftime may not be fractional.
+ \remark So if ftime = 0 this may suck away your cpu if used in a signalled loop.
+ */
+ bool TimedWait(float ftime)
+ {
+ timespec tm;
+#if 0 // find out when the following is defined
+ clock_gettime(CLOCK_REALTIME,tm);
+ tm.tv_nsec += (long)((ftime-(long)ftime)*1.e9);
+ long nns = tm.tv_nsec%1000000000;
+ tm.tv_sec += (long)ftime+(tm.tv_nsec-nns)/1000000000;
+ tm.tv_nsec = nns;
+#else
+ tm.tv_sec = time(NULL)+(long)ftime;
+ tm.tv_nsec = 0;
+#endif
+ Lock();
+ bool ret = pthread_cond_timedwait(&cond,&mutex,&tm) == 0;
+ Unlock();
+ return ret;
+ }
+
+ //! Signal condition
+ bool Signal()
+ {
+ Lock();
+ bool ret = pthread_cond_signal(&cond) == 0;
+ Unlock();
+ return ret;
+ }
+ //! Broadcast condition
+// int Broadcast() { return pthread_cond_broadcast(&cond); }
+ protected:
+ pthread_cond_t cond;
+ };
+#elif FLEXT_THREADS == FLEXT_THR_MP
+ {
+ public:
+ //! Construct thread conditional
+ ThrCond() { MPCreateEvent(&ev); }
+ //! Destroy thread conditional
+ ~ThrCond() { MPDeleteEvent(ev); }
+
+ //! Wait for condition
+ bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
+
+ /*! \brief Wait for condition (for a certain time)
+ \param time Wait time in seconds
+ */
+ bool TimedWait(float tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
+
+ //! Signal condition
+ bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
+ //! Broadcast condition
+// int Broadcast() { return pthread_cond_broadcast(&cond); }
+ protected:
+ MPEventID ev;
+ };
+#else
+#error "Not implemented"
+#endif
+
+ /*! \brief Add current thread to list of active threads
+ \return true on success
+ \internal
+ */
+ static bool PushThread();
+
+ /*! \brief Remove current thread from list of active threads
+ \internal
+ */
+ static void PopThread();
+
+ /*! \brief Launch a thread
+ \remark thr_params *p may be NULL if not needed
+ */
+ static bool LaunchThread(void (*meth)(thr_params *p),thr_params *p);
+
+//! @} FLEXT_S_THREAD
+
+#endif // FLEXT_THREADS
+
+//! @}
+
+protected:
+#ifdef __MRC__
+ friend class flext_obj;
+#endif
+ static void Setup();
+
+ static bool chktilde(const char *objname);
+};
+
+#endif
|