From c3ae6e7ab08db709ffa1975eea70bfc9461f1d6a Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Mon, 3 Mar 2003 07:57:50 +0000 Subject: "" svn path=/trunk/; revision=448 --- externals/grill/flext/flext.cw | Bin 440331 -> 454327 bytes externals/grill/flext/flext.dsp | 8 + externals/grill/flext/flext.pbproj/project.pbxproj | 43 +- externals/grill/flext/make-files.txt | 2 +- externals/grill/flext/makefile.pd-darwin | 3 +- externals/grill/flext/readme.txt | 5 + externals/grill/flext/source/flclass.h | 2 +- externals/grill/flext/source/flcwmax-thr.h | 29 + externals/grill/flext/source/fldefs.h | 8 + externals/grill/flext/source/fldoxygen.h | 16 +- externals/grill/flext/source/flext.h | 128 +- externals/grill/flext/source/flprefix.h | 7 +- externals/grill/flext/source/flsimd.cpp | 291 ++++ externals/grill/flext/source/flsupport.h | 1764 ++++++++++---------- externals/grill/flext/source/fltimer.cpp | 262 +++ externals/grill/flext/source/flutil.cpp | 55 - externals/grill/flext/tutorial/build-pd-bcc.bat | 4 + .../grill/flext/tutorial/config-pd-cygwin.txt | 5 + .../grill/flext/tutorial/config-pd-darwin.txt | 5 + externals/grill/flext/tutorial/config-pd-linux.txt | 5 + externals/grill/flext/tutorial/lib1/lib1.cw | Bin 101183 -> 148873 bytes externals/grill/flext/tutorial/makefile.pd-cygwin | 5 +- externals/grill/flext/tutorial/makefile.pd-darwin | 6 +- externals/grill/flext/tutorial/makefile.pd-linux | 6 +- externals/grill/flext/tutorial/makefile.pd-msvc | 1 + externals/grill/flext/tutorial/maxmsp/ex-timer1 | Bin 0 -> 1247 bytes externals/grill/flext/tutorial/pd/ex-timer1.pd | 64 + externals/grill/flext/tutorial/readme.txt | 9 +- externals/grill/flext/tutorial/timer1/main.cpp | 100 ++ externals/grill/flext/tutorial/timer1/timer1.cw | Bin 0 -> 207765 bytes externals/grill/flext/tutorial/timer1/timer1.dsp | 95 ++ 31 files changed, 1942 insertions(+), 986 deletions(-) create mode 100755 externals/grill/flext/source/flcwmax-thr.h create mode 100755 externals/grill/flext/source/flsimd.cpp create mode 100755 externals/grill/flext/source/fltimer.cpp create mode 100755 externals/grill/flext/tutorial/maxmsp/ex-timer1 create mode 100755 externals/grill/flext/tutorial/pd/ex-timer1.pd create mode 100755 externals/grill/flext/tutorial/timer1/main.cpp create mode 100755 externals/grill/flext/tutorial/timer1/timer1.cw create mode 100755 externals/grill/flext/tutorial/timer1/timer1.dsp (limited to 'externals') diff --git a/externals/grill/flext/flext.cw b/externals/grill/flext/flext.cw index 58c9749b..e33fdf5a 100644 Binary files a/externals/grill/flext/flext.cw and b/externals/grill/flext/flext.cw differ diff --git a/externals/grill/flext/flext.dsp b/externals/grill/flext/flext.dsp index ef145039..f094ea78 100644 --- a/externals/grill/flext/flext.dsp +++ b/externals/grill/flext/flext.dsp @@ -263,6 +263,10 @@ SOURCE=.\source\flmspbuffer.h # End Source File # Begin Source File +SOURCE=.\source\flsimd.cpp +# End Source File +# Begin Source File + SOURCE=.\source\flsupport.cpp # End Source File # Begin Source File @@ -271,6 +275,10 @@ SOURCE=.\source\flsupport.h # End Source File # Begin Source File +SOURCE=.\source\fltimer.cpp +# End Source File +# Begin Source File + SOURCE=.\source\flutil.cpp # End Source File # End Group diff --git a/externals/grill/flext/flext.pbproj/project.pbxproj b/externals/grill/flext/flext.pbproj/project.pbxproj index e4243f9f..b80efb1f 100755 --- a/externals/grill/flext/flext.pbproj/project.pbxproj +++ b/externals/grill/flext/flext.pbproj/project.pbxproj @@ -124,6 +124,7 @@ F504A67103CE39F501A80AC9, F504A67203CE39F501A80AC9, F504A67303CE39F501A80AC9, + F5B1FAC8041191190179CFEF, ); isa = PBXGroup; name = Source; @@ -718,6 +719,7 @@ F504A67903CE3BE101A80AC9, F504A67A03CE3BE201A80AC9, F504A67B03CE3BE301A80AC9, + F5B1FACE0411935C0179CFEF, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -751,7 +753,7 @@ INSTALL_PATH = /usr/local/pd/flext; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O3"; - OTHER_CFLAGS = "-D FLEXT_SYS=2 -Wno-switch"; + OTHER_CFLAGS = "-D FLEXT_SYS=2 -Wno-switch -Wno-long-double"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; @@ -928,7 +930,7 @@ INSTALL_PATH = /usr/local/pd/flext; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O3"; - OTHER_CFLAGS = "-D FLEXT_SYS_PD -D FLEXT_THREADS -Wno-switch"; + OTHER_CFLAGS = "-D FLEXT_SYS_PD -D FLEXT_THREADS -Wno-switch -Wno-long-double"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; @@ -1048,6 +1050,7 @@ F504A68003CE3BEA01A80AC9, F504A68103CE3BEB01A80AC9, F504A68203CE3BEB01A80AC9, + F5B1FACF041193680179CFEF, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -1163,7 +1166,7 @@ INSTALL_PATH = /usr/local/pd/flext; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = "-D FLEXT_SYS=2 -D FLEXT_DEBUG -Wno-switch"; + OTHER_CFLAGS = "-D FLEXT_SYS=2 -D FLEXT_DEBUG -Wno-switch -Wno-long-double"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; @@ -1283,6 +1286,7 @@ F504A68703CE3BF201A80AC9, F504A68803CE3BF201A80AC9, F504A68903CE3BF301A80AC9, + F5B1FAD0041193740179CFEF, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -1398,7 +1402,7 @@ INSTALL_PATH = /usr/local/pd/flext; LIBRARY_STYLE = STATIC; OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = "-D FLEXT_SYS=2 -D FLEXT_THREADS -D FLEXT_DEBUG -Wno-switch"; + OTHER_CFLAGS = "-D FLEXT_SYS=2 -D FLEXT_THREADS -D FLEXT_DEBUG -Wno-switch -Wno-long-double"; OTHER_LDFLAGS = ""; OTHER_LIBTOOL_FLAGS = ""; OTHER_REZFLAGS = ""; @@ -1518,6 +1522,7 @@ F504A69203CE3C1501A80AC9, F504A69303CE3C1601A80AC9, F504A69403CE3C1701A80AC9, + F5B1FACD0411918B0179CFEF, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -2125,6 +2130,36 @@ path = flext.max.a; refType = 3; }; + F5B1FAC8041191190179CFEF = { + isa = PBXFileReference; + name = fltimer.cpp; + path = source/fltimer.cpp; + refType = 4; + }; + F5B1FACD0411918B0179CFEF = { + fileRef = F5B1FAC8041191190179CFEF; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FACE0411935C0179CFEF = { + fileRef = F5B1FAC8041191190179CFEF; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FACF041193680179CFEF = { + fileRef = F5B1FAC8041191190179CFEF; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FAD0041193740179CFEF = { + fileRef = F5B1FAC8041191190179CFEF; + isa = PBXBuildFile; + settings = { + }; + }; F5C204ED03D403B401A80AC9 = { buildPhases = ( F5C204EE03D403B401A80AC9, diff --git a/externals/grill/flext/make-files.txt b/externals/grill/flext/make-files.txt index d477106d..42720544 100644 --- a/externals/grill/flext/make-files.txt +++ b/externals/grill/flext/make-files.txt @@ -1,5 +1,5 @@ SRCS=flbase.cpp flext.cpp flbuf.cpp fldsp.cpp fllib.cpp flxlet.cpp flattr.cpp flsupport.cpp \ -flutil.cpp flatom.cpp flatom_pr.cpp flthr.cpp flout.cpp \ +flutil.cpp flatom.cpp flatom_pr.cpp flthr.cpp fltimer.cpp flsimd.cpp flout.cpp \ flatom_app.cpp flatom_part.cpp flitem.cpp flmeth.cpp flmsg.cpp \ flproxy.cpp flqueue.cpp HDRS=flprefix.h flstdc.h flbase.h flclass.h fldefs.h flext.h flsupport.h fldsp.h flinternal.h diff --git a/externals/grill/flext/makefile.pd-darwin b/externals/grill/flext/makefile.pd-darwin index 62ac9864..eaa68a92 100644 --- a/externals/grill/flext/makefile.pd-darwin +++ b/externals/grill/flext/makefile.pd-darwin @@ -14,7 +14,8 @@ include ${CONFIG} # compiler+linker stuff INCLUDES=${PDPATH} -FLAGS=-DFLEXT_SYS=2 -Wno-unused -Wno-parentheses -Wshadow -Wno-switch -Wstrict-prototypes -fno-exceptions ${UFLAGS} +FLAGS=-DFLEXT_SYS=2 -Wno-unused -Wno-parentheses -Wno-switch -Wstrict-prototypes +FLAGS+=${UFLAGS} -fno-exceptions CFLAGS=-O6 CFLAGS_D=-g CFLAGS_T=-DFLEXT_THREADS diff --git a/externals/grill/flext/readme.txt b/externals/grill/flext/readme.txt index 78d00184..20e62f61 100644 --- a/externals/grill/flext/readme.txt +++ b/externals/grill/flext/readme.txt @@ -114,6 +114,11 @@ see flext.h, fldefs.h and flclass.h for the documented base definitions and clas Version history: +0.4.3: +- added forgotten flext_base::ToQueueString method +- added timer functions and flext::Timer class +- added functions for SIMD support + 0.4.2: - started port for jMax - moved CLASS_MAINSIGNALIN to class scope (fixed "float method overwritten" warning) diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h index 4aa17a7d..17385370 100644 --- a/externals/grill/flext/source/flclass.h +++ b/externals/grill/flext/source/flclass.h @@ -268,7 +268,7 @@ public: //! Output string aka symbol (to appointed outlet) // void ToQueueString(outlet *o,const char *s) const { ToQueueSymbol(o,MakeSymbol(s)); } //! Output string aka symbol (to appointed outlet) - void ToQueueString(int n,const char *s) const; // { ToQueueSymbol(n,MakeSymbol(s)); } + void ToQueueString(int n,const char *s) const { ToQueueSymbol(n,MakeSymbol(s)); } //! Output list (to appointed outlet) // void ToQueueList(outlet *o,int argc,const t_atom *argv) const; diff --git a/externals/grill/flext/source/flcwmax-thr.h b/externals/grill/flext/source/flcwmax-thr.h new file mode 100755 index 00000000..9b3f3096 --- /dev/null +++ b/externals/grill/flext/source/flcwmax-thr.h @@ -0,0 +1,29 @@ +/* + +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. + +*/ + +// This is the prefix file for CodeWarrior projects - threaded version + +#ifndef _FLEXT_CW_MAX_THR_H +#define _FLEXT_CW_MAX_THR_H + +#define FLEXT_THREADS + +/* + old CodeWarrior version (<= 6) don't have sigset_t defined which + is needed for pthreads +*/ +#if defined(__MWERKS__) && (__MWERKS__ <= 0x6000) + typedef unsigned int sigset_t; + #define _CW_NOPRECOMP // no precompiled headers +#endif + +#include "flcwmax.h" + +#endif diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h index dc99a2e7..be7ac879 100644 --- a/externals/grill/flext/source/fldefs.h +++ b/externals/grill/flext/source/fldefs.h @@ -332,6 +332,9 @@ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) \ { FLEXT_CAST(c)->M_FUN(data); return true; } +//! Set up a timer callback +#define FLEXT_CALLBACK_T(M_FUN) FLEXT_CALLBACK_X(M_FUN) + //! Set up a method callback for a boolean argument #define FLEXT_CALLBACK_B(M_FUN) \ static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) \ @@ -758,6 +761,11 @@ FLEXT_CADDMETHOD_3(CL,IX,M_TAG,M_FUN,int,int,int) @{ */ +//! Set timer callback +#define FLEXT_ADDTIMER(TMR,M_FUN) \ +\ +TMR.SetCallback(*this,FLEXT_CALL_PRE(M_FUN)) + //! Enable list element distribution over inlets (if no better handler found) #define FLEXT_ADDDIST() \ \ diff --git a/externals/grill/flext/source/fldoxygen.h b/externals/grill/flext/source/fldoxygen.h index 0c515031..d3574842 100644 --- a/externals/grill/flext/source/fldoxygen.h +++ b/externals/grill/flext/source/fldoxygen.h @@ -16,13 +16,14 @@ Currently there exist two widely used modular systems for real-time audio that c extended by self-written objects (so called "externals"):
Max/MSP (http://www.cycling74.com) and Pure Data (http://www.pure-data.org). -Both come with APIs that are not very different, but as well not quite the same. +Both come with APIs that are not very different (as they share their origins), but as well not quite the same. Flext seeks to provide a unifying interface for the APIs of those real-time systems while also concentrating on making use of the advantages of the object orientation of the C++ language. Consequently, flext allows to write externals (or libraries of a number of these), that can be compiled for both systems (with various compilers on a few platforms) without changes to the source code. +Flext also tries to overcome some limitations of the real-time systems and introduces new features. The advantages of flext are: \section LICENSE License @@ -80,8 +81,12 @@ Alternatively, you can check out the cvs version from http://sourceforge.net/pro \section USAGE Usage -As a developer, you should know the C++ language, how to use a makefile +As a developer, you should know the C++ language, how to use a makefile (especially necessary for linux) and how to steer your compiler.
+Flext can be compiled as a static library which has then to be linked to the code of your external. +For most applications you won't have to use any of the native PD or Max/MSP API functions as they are all +encapsulated by flext. + So let's come to the point... how does a typical flext object look like? This is the object "attr1", one of the flext tutorial examples: @@ -151,7 +156,7 @@ convenient definition. FLEXT_NEW("attr1",attr1) \endverbatim -With FLEXT_NEW the class is instantiated and registered for the real-time system. +With FLEXT_NEW the class is registered for the real-time system. The number of creation arguments and their types must be taken into account here. There are several variants depending on whether a message oriented (see \ref FLEXT_D_NEW) or a DSP object (see \ref FLEXT_D_NEW_DSP) is created and whether it resides in a object library @@ -181,6 +186,9 @@ This is done with the functions in \ref FLEXT_C_IO_ADD. Likewise, every method (called by a message) (see \ref FLEXT_D_ADDMETHOD) and every attribute (see \ref FLEXT_D_ADDATTR) exposed to the system has to be registered. +Here the registration at instance creation is shown - there's another way by registering at +class setup level, which is more efficient but can only be used if the methods or attributes +used are known beforehand (see \ref FLEXT_D_CADDMETHOD and \ref FLEXT_D_CADDATTR). \verbatim void attr1::m_trigger(float f) diff --git a/externals/grill/flext/source/flext.h b/externals/grill/flext/source/flext.h index 8bef1f02..2a8a0119 100644 --- a/externals/grill/flext/source/flext.h +++ b/externals/grill/flext/source/flext.h @@ -1,64 +1,64 @@ -/* - -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 flext.h - \brief This is the main flext include file. - - The basic definitions are set here and the necessary header files are included -*/ - -#ifndef __FLEXT_H -#define __FLEXT_H - - -/*! \defgroup FLEXT_GLOBAL Flext global definitions - @{ -*/ - -//! \brief flext version number -#define FLEXT_VERSION 402 - -//! \brief flext version string -#define FLEXT_VERSTR "0.4.2" - -//! @} - - -// determine System/OS/CPU -#include "flprefix.h" - -// include headers necessary for multi-threading -#ifdef FLEXT_THREADS - #if FLEXT_THREADS == FLEXT_THR_POSIX - extern "C" { - #include - #include - } - #elif FLEXT_THREADS == FLEXT_THR_MP - #include - #elif FLEXT_THREADS == FLEXT_THR_WIN32 - #include - #else - #error "Thread model not supported" - #endif -#endif - -// include all the flext interface definitions -#include "fldefs.h" - -// include the basic flext object classes -#include "flclass.h" - -// include the flext dsp class -#include "fldsp.h" - -#endif // FLEXT_H - - +/* + +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 flext.h + \brief This is the main flext include file. + + The basic definitions are set here and the necessary header files are included +*/ + +#ifndef __FLEXT_H +#define __FLEXT_H + + +/*! \defgroup FLEXT_GLOBAL Flext global definitions + @{ +*/ + +//! \brief flext version number +#define FLEXT_VERSION 403 + +//! \brief flext version string +#define FLEXT_VERSTR "0.4.3pre" + +//! @} + + +// determine System/OS/CPU +#include "flprefix.h" + +// include headers necessary for multi-threading +#ifdef FLEXT_THREADS + #if FLEXT_THREADS == FLEXT_THR_POSIX + extern "C" { + #include + #include + } + #elif FLEXT_THREADS == FLEXT_THR_MP + #include + #elif FLEXT_THREADS == FLEXT_THR_WIN32 + #include + #else + #error "Thread model not supported" + #endif +#endif + +// include all the flext interface definitions +#include "fldefs.h" + +// include the basic flext object classes +#include "flclass.h" + +// include the flext dsp class +#include "fldsp.h" + +#endif // FLEXT_H + + diff --git a/externals/grill/flext/source/flprefix.h b/externals/grill/flext/source/flprefix.h index dce223e7..028c8df9 100755 --- a/externals/grill/flext/source/flprefix.h +++ b/externals/grill/flext/source/flprefix.h @@ -171,10 +171,11 @@ WARRANTIES, see the file, "license.txt," in this distribution. #endif #ifndef FLEXT_OSAPI - #if TARGET_API_MAC_CARBON - #define FLEXT_OSAPI FLEXT_OSAPI_MAC_CARBON - #elif TARGET_API_MAC_OSX + #if TARGET_API_MAC_OSX + // this has the precedence (OSX can also be Carbon, of course) #define FLEXT_OSAPI FLEXT_OSAPI_MAC_OSX + #elif TARGET_API_MAC_CARBON + #define FLEXT_OSAPI FLEXT_OSAPI_MAC_CARBON #else #define FLEXT_OSAPI FLEXT_OSAPI_UNKNOWN #endif diff --git a/externals/grill/flext/source/flsimd.cpp b/externals/grill/flext/source/flsimd.cpp new file mode 100755 index 00000000..756f28c7 --- /dev/null +++ b/externals/grill/flext/source/flsimd.cpp @@ -0,0 +1,291 @@ +/* + +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 flsimd.cpp + \brief flext SIMD support functions +*/ + +#include "flext.h" +#include + +#if FLEXT_OS == FLEXT_OS_WIN +#include +#endif + +#if FLEXT_CPU == FLEXT_CPU_PPC && defined(__MWERKS__) +#include "Altivec.h" +#endif + +#ifdef FLEXT_USE_IPP +#include +#endif + +static unsigned long setsimdcaps(); + +/*! \brief Holds SIMD capability flags + \internal +*/ +unsigned long flext::simdcaps = setsimdcaps(); + + +#if FLEXT_CPU == FLEXT_CPU_INTEL + +#define _CPU_FEATURE_MMX 0x0001 +#define _CPU_FEATURE_SSE 0x0002 +#define _CPU_FEATURE_SSE2 0x0004 +#define _CPU_FEATURE_3DNOW 0x0008 + +typedef struct _processor_info { + int family; // family of the processor + // e.g. 6 = Pentium-Pro architecture + int model; // model of processor + // e.g. 1 = Pentium-Pro for family = 6 + int stepping; // processor revision number + int feature; // processor feature + // (same as return value from _cpuid) + int os_support; // does OS Support the feature? + int checks; // mask of checked bits in feature + // and os_support fields +} _p_info; + +// These are the bit flags that get set on calling cpuid +// with register eax set to 1 +#define _MMX_FEATURE_BIT 0x00800000 +#define _SSE_FEATURE_BIT 0x02000000 +#define _SSE2_FEATURE_BIT 0x04000000 + +// This bit is set when cpuid is called with +// register set to 80000001h (only applicable to AMD) +#define _3DNOW_FEATURE_BIT 0x80000000 + +#ifdef _MSC_VER +static int IsCPUID() +{ + __try { + _asm { + xor eax, eax + cpuid + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + return 0; + } + return 1; +} + +static int _os_support(int feature) +{ + __try { + switch (feature) { + case _CPU_FEATURE_SSE: + __asm { + xorps xmm0, xmm0 // executing SSE instruction + } + break; + case _CPU_FEATURE_SSE2: + __asm { + xorpd xmm0, xmm0 // executing SSE2 instruction + } + break; + case _CPU_FEATURE_3DNOW: + __asm { + pfrcp mm0, mm0 // executing 3DNow! instruction + emms + } + break; + case _CPU_FEATURE_MMX: + __asm { + pxor mm0, mm0 // executing MMX instruction + emms + } + break; + } + } + __except (EXCEPTION_EXECUTE_HANDLER) { + if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) { + return 0; + } + return 0; + } + return 1; +} + +static int _cpuid (_p_info *pinfo) +{ + DWORD dwStandard = 0; + DWORD dwFeature = 0; + DWORD dwMax = 0; + DWORD dwExt = 0; + int feature = 0; + int os_support = 0; + union { + struct { + DWORD dw0; + DWORD dw1; + DWORD dw2; + } s; + } Ident; + + if (!IsCPUID()) { + return 0; + } + + _asm { + push ebx + push ecx + push edx + + // get the vendor string + xor eax, eax + cpuid + mov dwMax, eax + mov Ident.s.dw0, ebx + mov Ident.s.dw1, edx + mov Ident.s.dw2, ecx + + // get the Standard bits + mov eax, 1 + cpuid + mov dwStandard, eax + mov dwFeature, edx + + // get AMD-specials + mov eax, 80000000h + cpuid + cmp eax, 80000000h + jc notamd + mov eax, 80000001h + cpuid + mov dwExt, edx + +notamd: + pop ecx + pop ebx + pop edx + } + + if (dwFeature & _MMX_FEATURE_BIT) { + feature |= _CPU_FEATURE_MMX; + if (_os_support(_CPU_FEATURE_MMX)) + os_support |= _CPU_FEATURE_MMX; + } + if (dwExt & _3DNOW_FEATURE_BIT) { + feature |= _CPU_FEATURE_3DNOW; + if (_os_support(_CPU_FEATURE_3DNOW)) + os_support |= _CPU_FEATURE_3DNOW; + } + if (dwFeature & _SSE_FEATURE_BIT) { + feature |= _CPU_FEATURE_SSE; + if (_os_support(_CPU_FEATURE_SSE)) + os_support |= _CPU_FEATURE_SSE; + } + if (dwFeature & _SSE2_FEATURE_BIT) { + feature |= _CPU_FEATURE_SSE2; + if (_os_support(_CPU_FEATURE_SSE2)) + os_support |= _CPU_FEATURE_SSE2; + } + + if (pinfo) { + memset(pinfo, 0, sizeof(_p_info)); + + pinfo->os_support = os_support; + pinfo->feature = feature; + pinfo->family = (dwStandard >> 8) & 0xF; // retrieve family + if (pinfo->family == 15) { // retrieve extended family + pinfo->family |= (dwStandard >> 16) & 0xFF0; + } + pinfo->model = (dwStandard >> 4) & 0xF; // retrieve model + if (pinfo->model == 15) { // retrieve extended model + pinfo->model |= (dwStandard >> 12) & 0xF; + } + pinfo->stepping = (dwStandard) & 0xF; // retrieve stepping + + pinfo->checks = _CPU_FEATURE_MMX | + _CPU_FEATURE_SSE | + _CPU_FEATURE_SSE2 | + _CPU_FEATURE_3DNOW; + } + + return feature; +} +#else +// not MSVC +static int _cpuid (_p_info *pinfo) +{ + if(pinfo) memset(pinfo,0,sizeof *pinfo); + return 0; +} +#endif + +#endif + + +/*! \brief Determine SIMD capabilities + \internal +*/ +static unsigned long setsimdcaps() +{ + unsigned long simdflags = flext::simd_none; +#if FLEXT_CPU == FLEXT_CPU_INTEL + _p_info cpuinfo; + int feature = _cpuid(&cpuinfo); + if(cpuinfo.os_support&_CPU_FEATURE_MMX) simdflags += flext::simd_mmx; + if(cpuinfo.os_support&_CPU_FEATURE_3DNOW) simdflags += flext::simd_3dnow; + if(cpuinfo.os_support&_CPU_FEATURE_SSE) simdflags += flext::simd_sse; + if(cpuinfo.os_support&_CPU_FEATURE_SSE2) simdflags += flext::simd_sse2; +#endif + return simdflags; +} + + +void flext::CopySamples(t_sample *dst,const t_sample *src,int cnt) +{ +#ifdef FLEXT_USE_IPP + if(sizeof(t_sample) == 4) + ippsCopy_32f((const float *)src,(float *)dst,cnt); + else if(sizeof(t_sample) == 8) + ippsCopy_64f((const double *)src,(double *)dst,cnt); + else + ERRINTERNAL(); +#else + int n = cnt>>3; + cnt -= n<<3; + while(n--) { + dst[0] = src[0]; dst[1] = src[1]; + dst[2] = src[2]; dst[3] = src[3]; + dst[4] = src[4]; dst[5] = src[5]; + dst[6] = src[6]; dst[7] = src[7]; + src += 8,dst += 8; + } + + while(cnt--) *(dst++) = *(src++); +#endif +} + +void flext::SetSamples(t_sample *dst,int cnt,t_sample s) +{ +#ifdef FLEXT_USE_IPP + if(sizeof(t_sample) == 4) + ippsSet_32f((float)s,(float *)dst,cnt); + else if(sizeof(t_sample) == 8) + ippsSet_64f((double)s,(double *)dst,cnt); + else + ERRINTERNAL(); +#else + int n = cnt>>3; + cnt -= n<<3; + while(n--) { + dst[0] = dst[1] = dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = s; + dst += 8; + } + + while(cnt--) *(dst++) = s; +#endif +} diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h index 8202922c..1963e56c 100644 --- a/externals/grill/flext/source/flsupport.h +++ b/externals/grill/flext/source/flsupport.h @@ -1,839 +1,925 @@ -/* - -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 +/* + +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); + //! Copy a sample array + static void CopySamples(t_sample *dst,const t_sample *src,int cnt); + //! Set a memory region + static void ZeroMem(void *dst,int bytes); + //! Set a sample array to a fixed value + static void SetSamples(t_sample *dst,int cnt,t_sample s); + //! Set a sample array to 0 + static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); } + + + //! 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 + + +// --- 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 + // for a preemptive system this should do nothing + 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() { pthread_mutex_init(&mutex,NULL); } + //! Destroy thread mutex + ~ThrMutex() { pthread_mutex_destroy(&mutex); } + + //! Lock thread mutex + bool Lock() { return pthread_mutex_lock(&mutex) == 0; } + /*! \brief Wait to lock thread mutex + \todo Implement! + */ + bool WaitForLock(double tm) { 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() { return pthread_mutex_unlock(&mutex) == 0; } + + protected: + pthread_mutex_t mutex; +// int cnt; + }; +#elif FLEXT_THREADS == FLEXT_THR_MP + { + public: + //! Construct thread mutex + ThrMutex() { MPCreateCriticalRegion(&crit); } + //! Destroy thread mutex + ~ThrMutex() { MPDeleteCriticalRegion(crit); } + + //! Lock thread mutex + bool Lock() { return MPEnterCriticalRegion(crit,kDurationForever) == noErr; } + //! Wait to lock thread mutex + bool WaitForLock(double tm) { 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() { 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(double 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(double 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 + + +// --- timer stuff ----------------------------------------------- + +/*! \defgroup FLEXT_S_TIMER Flext timer handling + @{ + + \remark The clock of the real-time system is used for most of these functions. + \remark Since this clock can be synchronized to an external clock (or e.g. the audio card) + \remark it may differ from the clock of the operating system +*/ + /*! \brief Get time since real-time system startup + \note This is not the time of the operating system but of the real-time system. + \note It depends on the time source the system is synchronized to. + */ + static double GetTime(); + + /*! \brief Get time granularity of the GetTime function + \note This can be zero if not determined. + */ + static double GetTimeGrain(); + + /*! \brief Get operating system time since flext startup + */ + static double GetOSTime(); + + /*! \brief Sleep for an amount of time + \remark The OS clock is used for that + \note Clearly in a real-time system this should only be used in a detached thread + */ + static void Sleep(double s); + + /*! \brief Class encapsulating a timer with callback functionality + This class can either be used with FLEXT_ADDTIMER or used as a base class with an overloaded virtual Work function. + */ + class FLEXT_SHARE Timer + { + public: + Timer(bool queued = false); + ~Timer(); + + //! Set timer callback function + void SetCallback(void (*cb)(void *data)) { clss = NULL,cback = cb; } + //! Set timer callback function (with class pointer) + void SetCallback(flext_base &th,bool (*cb)(flext_base *th,void *data)) { clss = &th,cback = (void (*)(void *))cb; } + + //! Clear timer + bool Reset(); + //! Trigger a one shot at an absolute time + bool At(double tm,void *data = NULL,bool dopast = true); + //! Trigger a one shot interval + bool Delay(double tm,void *data = NULL); + //! Trigger a periodic interval + bool Periodic(double tm,void *data = NULL); + + //! Worker function, called on every timer event + virtual void Work(); + + protected: + static void callback(Timer *tmr); + +#if FLEXT_SYS == FLEXT_SYS_PD + t_clock *clk; +#elif FLEXT_SYS == FLEXT_SYS_MAX + static void queuefun(Timer *tmr); + t_clock *clk; + t_qelem *qelem; +#else +#error Not implemented +#endif + + const bool queued; + void (*cback)(void *data); + flext_base *clss; + void *userdata; + double period; + }; + +//! @} FLEXT_S_TIMER + +// --- SIMD functionality ----------------------------------------------- + +/*! \defgroup FLEXT_S_SIMD Cross platform SIMD support for modern CPUs + @{ +*/ + enum simd_type { + simd_none = 0, + simd_mmx = 0x01, + simd_3dnow = 0x02, + simd_sse = 0x04, + simd_sse2 = 0x08, + simd_altivec = 0x10 + }; + + static unsigned long GetSIMDCapabilities() { return simdcaps; } + +//! @} FLEXT_S_SIMD + + +//! @} FLEXT_SUPPORT + +protected: +#ifdef __MRC__ + friend class flext_obj; +#endif + static void Setup(); + + static bool chktilde(const char *objname); + + static unsigned long simdcaps; +}; + +#endif diff --git a/externals/grill/flext/source/fltimer.cpp b/externals/grill/flext/source/fltimer.cpp new file mode 100755 index 00000000..9b69de2b --- /dev/null +++ b/externals/grill/flext/source/fltimer.cpp @@ -0,0 +1,262 @@ +/* + +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 fltimer.cpp + \brief flext timer functions and classes +*/ + +#include "flext.h" + +#if FLEXT_OS == FLEXT_OS_WIN +#include +#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX +#include +#include +#elif FLEXT_OS == FLEXT_OS_MAC +#include +#include +#endif + + + +double flext::GetTime() +{ +#if FLEXT_SYS == FLEXT_SYS_PD + return clock_gettimesince(0)*0.001; +#elif FLEXT_SYS == FLEXT_SYS_MAX + double tm; + clock_getftime(&tm); + return tm*0.001; +#else + #error Not implemented +#endif +} + +double flext::GetTimeGrain() +{ +#if FLEXT_SYS == FLEXT_SYS_PD + return 0; +#elif FLEXT_SYS == FLEXT_SYS_MAX + return 0.001; +#else + #error Not implemented +#endif +} + +static double getstarttime(); +static double starttime = getstarttime(); + +static double getstarttime() +{ + starttime = 0; + return flext::GetOSTime(); +} + +double flext::GetOSTime() +{ + double tm; + +#if FLEXT_OS == FLEXT_OS_WIN + LARGE_INTEGER frq,cnt; + if(QueryPerformanceFrequency(&frq) && QueryPerformanceCounter(&cnt)) + tm = (double)(cnt.QuadPart)/frq.QuadPart; + else { + SYSTEMTIME systm; + FILETIME fltm; + GetSystemTime(&systm); + SystemTimeToFileTime(&systm,&fltm); + tm = (double)((LARGE_INTEGER *)&fltm)->QuadPart*0.001; + } +#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX // POSIX + timeval tmv; + gettimeofday(&tmv,NULL); + tm = tmv.tv_sec+tmv.tv_usec*1.e-6; +#elif FLEXT_OS == FLEXT_OS_MAC // that's just for OS9 & Carbon! + UnsignedWide tick; + Microseconds(&tick); + tm = (tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo)*1.e-6; +#else + #error Not implemented +#endif + return tm-starttime; +} + +void flext::Sleep(double s) +{ +#if FLEXT_OS == FLEXT_OS_WIN + ::Sleep((long)(s*1000.)); +#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX // POSIX + usleep((long)(s*1000000.)); +#elif FLEXT_OS == FLEXT_OS_MAC // that's just for OS9 & Carbon! + UnsignedWide tick; + Microseconds(&tick); + double target = tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo+s*1.e6; + for(;;) { + // this is just a loop running until the time has passed - stone age (but we yield at least) + Microseconds(&tick); + if(target <= tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo) break; + YieldToAnyThread(); // yielding surely reduces the timing precision (but we're civilized) + } +#else + #error Not implemented +#endif +} + + +/* \param qu determines whether timed messages should be queued (low priority - only when supported by the system). +*/ +flext::Timer::Timer(bool qu): + queued(qu), + clss(NULL),userdata(NULL), + period(0) +{ +#if FLEXT_SYS == FLEXT_SYS_PD + clk = (t_clock *)clock_new(this,(t_method)callback); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clk = (t_clock *)clock_new(this,(t_method)callback); + if(queued) qelem = (t_qelem *)qelem_new(this,(method)queuefun); +#else + #error Not implemented +#endif +} + +flext::Timer::~Timer() +{ +#if FLEXT_SYS == FLEXT_SYS_PD + clock_free(clk); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clock_free(clk); + if(queued) qelem_free(qelem); +#else + #error Not implemented +#endif +} + +bool flext::Timer::Reset() +{ +#if FLEXT_SYS == FLEXT_SYS_PD + clock_unset(clk); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clock_unset(clk); + if(queued) qelem_unset(qelem); +#else + #error Not implemented +#endif + return true; +} + +/*! \param tm absolute time (in seconds) + \param data user data + \param dopast if set events with times lying in the past will be triggered immediately, if not set they are ignored + \return true on success +*/ +bool flext::Timer::At(double tm,void *data,bool dopast) +{ + userdata = data; + period = 0; +#if FLEXT_SYS == FLEXT_SYS_PD + const double ms = tm*1000.; + if(dopast || clock_gettimesince(ms) <= 0) + clock_set(clk,ms); +#elif FLEXT_SYS == FLEXT_SYS_MAX + const double ms = tm*1000.; + double cur; + clock_getftime(&cur); + if(cur <= ms) + clock_fdelay(clk,ms-cur); + else if(dopast) // trigger timer is past + clock_fdelay(clk,0); +#else + #error Not implemented +#endif + return true; +} + +/*! \param tm relative time (in seconds) + \param data user data + \return true on success +*/ +bool flext::Timer::Delay(double tm,void *data) +{ + userdata = data; + period = 0; +#if FLEXT_SYS == FLEXT_SYS_PD + clock_delay(clk,tm*1000); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clock_fdelay(clk,tm*1000.); +#else + #error Not implemented +#endif + return true; +} + +/*! \param tm relative time between periodic events (in seconds) + \param data user data + \return true on success + \note the first event will be delayed by tm +*/ +bool flext::Timer::Periodic(double tm,void *data) +{ + userdata = data; + period = tm; +#if FLEXT_SYS == FLEXT_SYS_PD + clock_delay(clk,tm*1000); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clock_fdelay(clk,tm*1000.); +#else + #error Not implemented +#endif + return true; +} + +/*! \brief Callback function for system clock + \todo Make periodic events scheduled as such +*/ +void flext::Timer::callback(Timer *tmr) +{ + if(tmr->period) { + // clearly it would be more precise if the periodic event is scheduled as such + // and not retriggered every time +#if FLEXT_SYS == FLEXT_SYS_PD + clock_delay(tmr->clk,tmr->period*1000); +#elif FLEXT_SYS == FLEXT_SYS_MAX + clock_fdelay(tmr->clk,tmr->period*1000.); +#else + #error Not implemented +#endif + } + + if(tmr->cback) { +#if FLEXT_SYS == FLEXT_SYS_MAX + if(tmr->queued) + qelem_set(tmr->qelem); + else +#endif + tmr->Work(); + } +} + +#if FLEXT_SYS == FLEXT_SYS_MAX +/*! \brief Callback function for low priority clock (for queued messages) +*/ +void flext::Timer::queuefun(Timer *tmr) { tmr->Work(); } +#endif + +/*! \brief Virtual worker function - by default it calls the user callback function + \remark The respective callback parameter format is chosen depending on whether clss is defined or not. +*/ +void flext::Timer::Work() +{ + if(clss) + ((bool (*)(flext_base *,void *))cback)(clss,userdata); + else + cback(userdata); +} + diff --git a/externals/grill/flext/source/flutil.cpp b/externals/grill/flext/source/flutil.cpp index 9be38cf1..f1035359 100644 --- a/externals/grill/flext/source/flutil.cpp +++ b/externals/grill/flext/source/flutil.cpp @@ -15,15 +15,6 @@ WARRANTIES, see the file, "license.txt," in this distribution. #include "flext.h" #include -#if FLEXT_OS == FLEXT_OS_WIN -#include -#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX -#include -#elif FLEXT_OS == FLEXT_OS_MAC -#include -#include -#endif - void flext::CopyMem(void *dst,const void *src,int bytes) { memcpy(dst,src,bytes); @@ -34,51 +25,5 @@ void flext::ZeroMem(void *dst,int bytes) memset(dst,0,bytes); } -void flext::CopySamples(t_sample *dst,const t_sample *src,int cnt) -{ - int n = cnt>>3; - cnt -= n<<3; - while(n--) { - dst[0] = src[0]; dst[1] = src[1]; - dst[2] = src[2]; dst[3] = src[3]; - dst[4] = src[4]; dst[5] = src[5]; - dst[6] = src[6]; dst[7] = src[7]; - src += 8,dst += 8; - } - - while(cnt--) *(dst++) = *(src++); -} - -void flext::SetSamples(t_sample *dst,int cnt,t_sample s) -{ - int n = cnt>>3; - cnt -= n<<3; - while(n--) { - dst[0] = dst[1] = dst[2] = dst[3] = dst[4] = dst[5] = dst[6] = dst[7] = s; - dst += 8; - } - - while(cnt--) *(dst++) = s; -} -void flext::Sleep(double s) -{ -#if FLEXT_OS == FLEXT_OS_WIN - ::Sleep((long)(s*1000.)); -#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX - usleep((long)(s*1000000.)); -#elif FLEXT_OS == FLEXT_OS_MAC - // that's just for OS9! - UnsignedWide tick; - Microseconds(&tick); - double target = tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo+s*1.e6; - for(;;) { - Microseconds(&tick); - if(target <= tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo) break; - YieldToAnyThread(); // should we really yield? - } -#else -#error -#endif -} diff --git a/externals/grill/flext/tutorial/build-pd-bcc.bat b/externals/grill/flext/tutorial/build-pd-bcc.bat index 5c180607..fd2c9264 100644 --- a/externals/grill/flext/tutorial/build-pd-bcc.bat +++ b/externals/grill/flext/tutorial/build-pd-bcc.bat @@ -36,6 +36,10 @@ @make -f ..\makefile.pd-bcc NAME=attr3 SETUPFUNCTION=attr3_setup @cd .. +@cd timer1 +@make -f ..\makefile.pd-bcc NAME=timer1 SETUPFUNCTION=timer1_setup +@cd .. + @cd signal1 @make -f ..\makefile.pd-bcc NAME=signal1~ SETUPFUNCTION=signal1_tilde_setup @cd .. diff --git a/externals/grill/flext/tutorial/config-pd-cygwin.txt b/externals/grill/flext/tutorial/config-pd-cygwin.txt index 237cd519..82705200 100644 --- a/externals/grill/flext/tutorial/config-pd-cygwin.txt +++ b/externals/grill/flext/tutorial/config-pd-cygwin.txt @@ -21,3 +21,8 @@ FLEXTPATH=${PDPATH}/flext # where should the examples be built? OUTPATH=./pd-cygwin + +# additional compiler flags +# (check if they fit to your system!) +UFLAGS=-mcpu=pentiumpro # gcc 2.95 +#UFLAGS=-mcpu=pentium3 -msse # gcc 3.2 diff --git a/externals/grill/flext/tutorial/config-pd-darwin.txt b/externals/grill/flext/tutorial/config-pd-darwin.txt index eb65fcdf..7990fa2a 100644 --- a/externals/grill/flext/tutorial/config-pd-darwin.txt +++ b/externals/grill/flext/tutorial/config-pd-darwin.txt @@ -30,3 +30,8 @@ OUTPATH=./pd-darwin # where should the examples be installed? # (leave blank to omit installation) INSTPATH=${FLEXTPATH}/tutorial + +# additional compiler flags +# (check if they fit to your system!) +UFLAGS=-malign-power -maltivec + diff --git a/externals/grill/flext/tutorial/config-pd-linux.txt b/externals/grill/flext/tutorial/config-pd-linux.txt index 3c263221..bd16411a 100644 --- a/externals/grill/flext/tutorial/config-pd-linux.txt +++ b/externals/grill/flext/tutorial/config-pd-linux.txt @@ -30,3 +30,8 @@ OUTPATH=./pd-linux # where should the examples be installed? # (leave blank to omit installation) INSTPATH=${FLEXTPATH}/tutorial + +# additional compiler flags +# (check if they fit to your system!) +UFLAGS=-mcpu=pentiumpro # gcc 2.95 +#UFLAGS=-mcpu=pentium3 -msse # gcc 3.2 diff --git a/externals/grill/flext/tutorial/lib1/lib1.cw b/externals/grill/flext/tutorial/lib1/lib1.cw index 8310c18d..afa029c5 100755 Binary files a/externals/grill/flext/tutorial/lib1/lib1.cw and b/externals/grill/flext/tutorial/lib1/lib1.cw differ diff --git a/externals/grill/flext/tutorial/makefile.pd-cygwin b/externals/grill/flext/tutorial/makefile.pd-cygwin index 31224ed3..853abfc6 100644 --- a/externals/grill/flext/tutorial/makefile.pd-cygwin +++ b/externals/grill/flext/tutorial/makefile.pd-cygwin @@ -18,8 +18,7 @@ FLEXTLIB=$(FLEXTPATH)/flext-pdwin.lib INCLUDES=$(PDPATH)/src LIBPATH=$(PDPATH)/bin FLAGS=-DFLEXT_SYS=2 -CFLAGS=-O6 -fno-rtti -CFLAGS+=-mcpu=pentium3 -msse # cygwin gcc 3.2 +CFLAGS=${UFLAGS} -O6 -fno-rtti LIBS=m pd @@ -28,7 +27,7 @@ LIBS=m pd # all the source files from the package -EXAMPLES=simple1 simple2 simple3 adv1 adv2 adv3 attr1 attr2 attr3 signal1~ signal2~ lib1 # thread1 thread2 +EXAMPLES=simple1 simple2 simple3 adv1 adv2 adv3 timer1 attr1 attr2 attr3 signal1~ signal2~ lib1 # thread1 thread2 ifdef SNDOBJ INCLUDES+=$(SNDOBJ) diff --git a/externals/grill/flext/tutorial/makefile.pd-darwin b/externals/grill/flext/tutorial/makefile.pd-darwin index b384d9cc..086d1334 100644 --- a/externals/grill/flext/tutorial/makefile.pd-darwin +++ b/externals/grill/flext/tutorial/makefile.pd-darwin @@ -15,8 +15,8 @@ FLEXTLIB=$(FLEXTPATH)/flext_t.a # take threaded library for all # compiler+linker stuff ### EDIT! ### INCLUDES=$(PDPATH) LIBPATH= -FLAGS=-DFLEXT_SYS=2 -DFLEXT_THREADS -Wno-unused -Wno-parentheses -Wno-switch -Wstrict-prototypes # -maltivec -CFLAGS=-O6 -fno-rtti +FLAGS=-DFLEXT_SYS=2 -DFLEXT_THREADS -Wno-unused -Wno-parentheses -Wno-switch -Wstrict-prototypes -Wno-long-double +CFLAGS=${UFLAGS} -O6 -fno-rtti LIBS=m LDFLAGS=-bundle -bundle_loader $(PD) @@ -25,7 +25,7 @@ LDFLAGS=-bundle -bundle_loader $(PD) # all the source files from the package -EXAMPLES=simple1 simple2 simple3 adv1 adv2 adv3 attr1 attr2 attr3 signal1~ signal2~ lib1 thread1 thread2 +EXAMPLES=simple1 simple2 simple3 timer1 adv1 adv2 adv3 attr1 attr2 attr3 signal1~ signal2~ lib1 thread1 thread2 ifdef SNDOBJ INCLUDES+=$(SNDOBJ) diff --git a/externals/grill/flext/tutorial/makefile.pd-linux b/externals/grill/flext/tutorial/makefile.pd-linux index 3b0bc3d3..b370e59d 100644 --- a/externals/grill/flext/tutorial/makefile.pd-linux +++ b/externals/grill/flext/tutorial/makefile.pd-linux @@ -16,9 +16,7 @@ FLEXTLIB=$(FLEXTPATH)/flext_t.a # take threaded library for all INCLUDES=$(PDPATH)/src LIBPATH= FLAGS=-DFLEXT_SYS=2 -DFLEXT_THREADS -CFLAGS=-O6 -fno-rtti -CFLAGS+=-mcpu=pentiumpro # gcc 2.95 -# CFLAGS+=-mcpu=pentium3 -msse # gcc 3.2 +CFLAGS=${UFLAGS} -O6 -fno-rtti LIBS=m @@ -27,7 +25,7 @@ LIBS=m # all the source files from the package -EXAMPLES=simple1 simple2 simple3 adv1 adv2 adv3 attr1 attr2 attr3 signal1~ signal2~ lib1 thread1 thread2 +EXAMPLES=simple1 simple2 simple3 adv1 adv2 adv3 timer1 attr1 attr2 attr3 signal1~ signal2~ lib1 thread1 thread2 ifdef SNDOBJ INCLUDES+=$(SNDOBJ) diff --git a/externals/grill/flext/tutorial/makefile.pd-msvc b/externals/grill/flext/tutorial/makefile.pd-msvc index 51c3a58b..a5979454 100644 --- a/externals/grill/flext/tutorial/makefile.pd-msvc +++ b/externals/grill/flext/tutorial/makefile.pd-msvc @@ -27,6 +27,7 @@ normal: nmake /f make-sub.pd-msvc NAME=adv1 DIR=adv1 nmake /f make-sub.pd-msvc NAME=adv2 DIR=adv2 nmake /f make-sub.pd-msvc NAME=adv3 DIR=adv3 + nmake /f make-sub.pd-msvc NAME=timer1 DIR=timer1 nmake /f make-sub.pd-msvc NAME=attr1 DIR=attr1 nmake /f make-sub.pd-msvc NAME=attr2 DIR=attr2 nmake /f make-sub.pd-msvc NAME=attr3 DIR=attr3 diff --git a/externals/grill/flext/tutorial/maxmsp/ex-timer1 b/externals/grill/flext/tutorial/maxmsp/ex-timer1 new file mode 100755 index 00000000..d3828986 Binary files /dev/null and b/externals/grill/flext/tutorial/maxmsp/ex-timer1 differ diff --git a/externals/grill/flext/tutorial/pd/ex-timer1.pd b/externals/grill/flext/tutorial/pd/ex-timer1.pd new file mode 100755 index 00000000..7434eb00 --- /dev/null +++ b/externals/grill/flext/tutorial/pd/ex-timer1.pd @@ -0,0 +1,64 @@ +#N canvas 110 259 821 364 12; +#X msg 29 92 help; +#X obj 16 8 cnv 15 550 40 empty empty timer1 10 22 32 24 -260818 -1 +0; +#X text 167 30 http://www.parasitaere-kapazitaeten.net; +#X text 167 10 flext tutorial \, (C)2003 Thomas Grill; +#X obj 241 241 timer1; +#X obj 241 267 print; +#X msg 105 104 resetA; +#X msg 176 104 resetB; +#X msg 260 147 oneshotA \$1; +#X obj 259 124 f 100; +#X obj 303 107 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 32 +10 -262144 -1 -1 0 256; +#X obj 260 105 bng 15 250 50 0 empty empty empty 0 -6 32 8 -24198 -1 +-1; +#X obj 382 124 f 100; +#X obj 426 107 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 32 +10 -262144 -1 -1 0 256; +#X obj 383 105 bng 15 250 50 0 empty empty empty 0 -6 32 8 -24198 -1 +-1; +#X obj 515 124 f 100; +#X obj 559 107 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 32 +10 -262144 -1 -1 0 256; +#X obj 516 105 bng 15 250 50 0 empty empty empty 0 -6 32 8 -24198 -1 +-1; +#X obj 652 123 f 100; +#X obj 696 106 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 32 +10 -262144 -1 -1 0 256; +#X obj 653 104 bng 15 250 50 0 empty empty empty 0 -6 32 8 -24198 -1 +-1; +#X msg 383 147 oneshotB \$1; +#X msg 516 147 periodicA \$1; +#X msg 653 146 periodicB \$1; +#X text 119 82 reset timer; +#X text 275 81 trigger single event; +#X text 523 80 trigger periodic event; +#X msg 30 161 gettime; +#X msg 30 191 getostime; +#X text 106 162 get time; +#X text 127 191 get OS time; +#X connect 0 0 4 0; +#X connect 4 0 5 0; +#X connect 4 1 5 0; +#X connect 6 0 4 0; +#X connect 7 0 4 0; +#X connect 8 0 4 0; +#X connect 9 0 8 0; +#X connect 10 0 9 1; +#X connect 11 0 9 0; +#X connect 12 0 21 0; +#X connect 13 0 12 1; +#X connect 14 0 12 0; +#X connect 15 0 22 0; +#X connect 16 0 15 1; +#X connect 17 0 15 0; +#X connect 18 0 23 0; +#X connect 19 0 18 1; +#X connect 20 0 18 0; +#X connect 21 0 4 0; +#X connect 22 0 4 0; +#X connect 23 0 4 0; +#X connect 27 0 4 0; +#X connect 28 0 4 0; diff --git a/externals/grill/flext/tutorial/readme.txt b/externals/grill/flext/tutorial/readme.txt index 3be656e7..faceaaad 100644 --- a/externals/grill/flext/tutorial/readme.txt +++ b/externals/grill/flext/tutorial/readme.txt @@ -17,12 +17,13 @@ The recommended order to go through the tutorial examples is the following: 1) simple* 2) adv* 3) attr* -4) signal* -5) lib* -6) thread* +4) timer* +5) signal* +6) lib* +7) thread* and, if needed -7) sndobj* and/or stk* +8) sndobj* and/or stk* if you choose to compile with SndObj support you will need the respective library download from: http://www.may.ie/academic/music/musictec/SndObj/main.html diff --git a/externals/grill/flext/tutorial/timer1/main.cpp b/externals/grill/flext/tutorial/timer1/main.cpp new file mode 100755 index 00000000..6388eb4a --- /dev/null +++ b/externals/grill/flext/tutorial/timer1/main.cpp @@ -0,0 +1,100 @@ +/* +flext tutorial - timer 1 + +Copyright (c) 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. + +------------------------------------------------------------------------- + +This is an example of an object using timers +*/ + +// enable flext attributes +#define FLEXT_ATTRIBUTES 1 + +// include flext header +#include + +// check for appropriate flext version +#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 403) +#error You need at least flext version 0.4.3 +#endif + + +// define the class that stands for a pd/Max object + +class timer1: + // inherit from basic flext class + public flext_base +{ + // obligatory flext header (class name,base class name) + FLEXT_HEADER_S(timer1,flext_base,Setup) + +public: + // constructor + timer1(); + +protected: + // timers + Timer tmrA,tmrB; + + void m_getostime(float &f) { f = GetOSTime(); } // method for operating system time attribute + void m_getrttime(float &f) { f = GetTime(); } // method for real-time system time attribute + + void m_timerA(void *) { ToOutString(0,"Timer A"); } // timer A method + void m_timerB(void *) { ToOutString(0,"Timer B"); } // timer B method + + void m_resetA() { tmrA.Reset(); } // timer A reset + void m_resetB() { tmrB.Reset(); } // timer B reset + void m_oneshotA(int del) { tmrA.Delay(del*0.001); } // timer A one shot + void m_oneshotB(int del) { tmrB.Delay(del*0.001); } // timer B one shot + void m_periodicA(int del) { tmrA.Periodic(del*0.001); } // timer A periodic + void m_periodicB(int del) { tmrB.Periodic(del*0.001); } // timer B periodic + +private: + static void Setup(t_classid c); + + // register timer callbacks + FLEXT_CALLBACK_T(m_timerA) + FLEXT_CALLBACK_T(m_timerB) + + // register method callbacks + FLEXT_CALLGET_F(m_getostime) + FLEXT_CALLGET_F(m_getrttime) + FLEXT_CALLBACK(m_resetA) + FLEXT_CALLBACK(m_resetB) + FLEXT_CALLBACK_I(m_oneshotA) + FLEXT_CALLBACK_I(m_oneshotB) + FLEXT_CALLBACK_I(m_periodicA) + FLEXT_CALLBACK_I(m_periodicB) +}; + +// instantiate the class +FLEXT_NEW("timer1",timer1) + +// class setup function +void timer1::Setup(t_classid c) +{ + FLEXT_CADDATTR_GET(c,"ostime",m_getostime); // register attribute for OS time + FLEXT_CADDATTR_GET(c,"time",m_getrttime); // register attribute for RT time + + FLEXT_CADDMETHOD_(c,0,"resetA",m_resetA); // register reset method for timer A + FLEXT_CADDMETHOD_(c,0,"resetB",m_resetB); // register reset method for timer B + FLEXT_CADDMETHOD_(c,0,"oneshotA",m_oneshotA); // register one shot method for timer A + FLEXT_CADDMETHOD_(c,0,"oneshotB",m_oneshotB); // register one shot method for timer B + FLEXT_CADDMETHOD_(c,0,"periodicA",m_periodicA); // register periodic method for timer A + FLEXT_CADDMETHOD_(c,0,"periodicB",m_periodicB); // register periodic method for timer B +} + +// class constructor +timer1::timer1(): + tmrA(false),tmrB(false) +{ + AddInAnything("Control timers"); // add inlet for control commands + AddOutAnything("Timer output"); // add outlet for timer output + + // register methods + FLEXT_ADDTIMER(tmrA,m_timerA); // register method "m_timerA" for timer A + FLEXT_ADDTIMER(tmrB,m_timerB); // register method "m_timerB" for timer B +} diff --git a/externals/grill/flext/tutorial/timer1/timer1.cw b/externals/grill/flext/tutorial/timer1/timer1.cw new file mode 100755 index 00000000..08e05996 Binary files /dev/null and b/externals/grill/flext/tutorial/timer1/timer1.cw differ diff --git a/externals/grill/flext/tutorial/timer1/timer1.dsp b/externals/grill/flext/tutorial/timer1/timer1.dsp new file mode 100755 index 00000000..35716adc --- /dev/null +++ b/externals/grill/flext/tutorial/timer1/timer1.dsp @@ -0,0 +1,95 @@ +# Microsoft Developer Studio Project File - Name="simple1" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=simple1 - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "simple1.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "simple1.mak" CFG="simple1 - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "simple1 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "simple1 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "simple1" +# PROP Scc_LocalPath "." +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "simple1 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "msvc" +# PROP Intermediate_Dir "msvc" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c +# ADD CPP /nologo /W3 /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PD" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc07 /d "NDEBUG" +# ADD RSC /l 0xc07 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib pd.lib flext-pdwin.lib /nologo /dll /machine:I386 /out:"../pd-msvc/simple1.dll" /libpath:"..\..\pd-msvc" + +!ELSEIF "$(CFG)" == "simple1 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "msvc-debug" +# PROP Intermediate_Dir "msvc-debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PD" /Fr /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc07 /d "_DEBUG" +# ADD RSC /l 0xc07 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib pd.lib flext_d-pdwin.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\pd-msvc" + +!ENDIF + +# Begin Target + +# Name "simple1 - Win32 Release" +# Name "simple1 - Win32 Debug" +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# End Target +# End Project -- cgit v1.2.1