From 34ce52e8bec33c97e9413917f0f4b221fa0c6734 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Thu, 13 Feb 2003 04:37:27 +0000 Subject: "" svn path=/trunk/; revision=395 --- externals/grill/flext/source/flatom_pr.cpp | 156 ++- externals/grill/flext/source/fldsp.cpp | 420 +++---- externals/grill/flext/source/flstdc.h | 424 +++---- externals/grill/flext/source/flstk.cpp | 12 - externals/grill/flext/source/flstk.h | 19 +- externals/grill/flext/source/flsupport.cpp | 313 +++--- externals/grill/flext/source/flsupport.h | 1678 ++++++++++++++-------------- 7 files changed, 1501 insertions(+), 1521 deletions(-) (limited to 'externals/grill/flext/source') 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 -#include -#include -#include - -#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 +#include +#include +#include + +#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 - - - -// === 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 + + + +// === 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 // for easier debugging - #else - #include - #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 -#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 - - // 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 // for easier debugging + #else + #include + #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 +#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 + + // 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((reinterpret_cast(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(&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<>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((reinterpret_cast(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(&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<>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 - -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(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(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(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(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 + +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(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(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(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(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 -- cgit v1.2.1