aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--externals/grill/flext/flext.cwbin440331 -> 454327 bytes
-rw-r--r--externals/grill/flext/flext.dsp8
-rwxr-xr-xexternals/grill/flext/flext.pbproj/project.pbxproj43
-rw-r--r--externals/grill/flext/make-files.txt2
-rw-r--r--externals/grill/flext/makefile.pd-darwin3
-rw-r--r--externals/grill/flext/readme.txt5
-rw-r--r--externals/grill/flext/source/flclass.h2
-rwxr-xr-xexternals/grill/flext/source/flcwmax-thr.h29
-rw-r--r--externals/grill/flext/source/fldefs.h8
-rw-r--r--externals/grill/flext/source/fldoxygen.h16
-rw-r--r--externals/grill/flext/source/flext.h128
-rwxr-xr-xexternals/grill/flext/source/flprefix.h7
-rwxr-xr-xexternals/grill/flext/source/flsimd.cpp291
-rw-r--r--externals/grill/flext/source/flsupport.h1764
-rwxr-xr-xexternals/grill/flext/source/fltimer.cpp262
-rw-r--r--externals/grill/flext/source/flutil.cpp55
-rw-r--r--externals/grill/flext/tutorial/build-pd-bcc.bat4
-rw-r--r--externals/grill/flext/tutorial/config-pd-cygwin.txt5
-rw-r--r--externals/grill/flext/tutorial/config-pd-darwin.txt5
-rw-r--r--externals/grill/flext/tutorial/config-pd-linux.txt5
-rwxr-xr-xexternals/grill/flext/tutorial/lib1/lib1.cwbin101183 -> 148873 bytes
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-cygwin5
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-darwin6
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-linux6
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-msvc1
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-timer1bin0 -> 1247 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/pd/ex-timer1.pd64
-rw-r--r--externals/grill/flext/tutorial/readme.txt9
-rwxr-xr-xexternals/grill/flext/tutorial/timer1/main.cpp100
-rwxr-xr-xexternals/grill/flext/tutorial/timer1/timer1.cwbin0 -> 207765 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/timer1/timer1.dsp95
31 files changed, 1942 insertions, 986 deletions
diff --git a/externals/grill/flext/flext.cw b/externals/grill/flext/flext.cw
index 58c9749b..e33fdf5a 100644
--- a/externals/grill/flext/flext.cw
+++ b/externals/grill/flext/flext.cw
Binary files 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<thisType *>(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"):<br>
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:
<ul>
@@ -47,7 +48,7 @@ Currently, flext supports
<li>PD on Windows with Microsoft Visual C++, Borland C++ and gcc(cygwin) compilers
<li>PD on Linux with gcc
<li>PD on Mac OSX with gcc (Project Builder to follow soon)
-<li>Max/MSP on Mac OS9 with Metrowerks CodeWarrior
+<li>Max/MSP on Mac OS9 and OSX with Metrowerks CodeWarrior
</ul>
\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.<br>
+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 <pthread.h>
- #include <sched.h>
- }
- #elif FLEXT_THREADS == FLEXT_THR_MP
- #include <multiprocessing.h>
- #elif FLEXT_THREADS == FLEXT_THR_WIN32
- #include <windows.h>
- #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 <pthread.h>
+ #include <sched.h>
+ }
+ #elif FLEXT_THREADS == FLEXT_THR_MP
+ #include <multiprocessing.h>
+ #elif FLEXT_THREADS == FLEXT_THR_WIN32
+ #include <windows.h>
+ #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 <string.h>
+
+#if FLEXT_OS == FLEXT_OS_WIN
+#include <windows.h>
+#endif
+
+#if FLEXT_CPU == FLEXT_CPU_PPC && defined(__MWERKS__)
+#include "Altivec.h"
+#endif
+
+#ifdef FLEXT_USE_IPP
+#include <ipps.h>
+#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 <time.h>
-
-class FLEXT_SHARE flext_base;
-
-/*! \brief Flext support class
- A number of methods (most are static functions) are defined here for convenience.
- This class doesn't define any data members, hence it can be inherited to all
- classes (not only PD objects) to profit from the cross-platform functionality.
- Examples are the overloaded memory allocation, atom and atom list functions,
- thread functions and classes, the sample buffer class and others.
-*/
-class FLEXT_SHARE flext {
-
- /*! \defgroup FLEXT_SUPPORT Flext support class
- @{
- */
-public:
-
-// --- console output -----------------------------------------------
-
-#if FLEXT_SYS == FLEXT_SYS_JMAX
- //! post message to console
- static void post(const char *s,...);
- //! post error message to console
- static void error(const char *s,...);
-#endif
-
-// --- memory -------------------------------------------------------
-
- /*! \defgroup FLEXT_S_MEMORY Memory allocation functions
- @{
- */
-
- /*! Overloaded new memory allocation method
- \warning Max/MSP (or MacOS) allows only 16K in overdrive mode!
- */
- void *operator new(size_t bytes);
- //! Overloaded delete method
- void operator delete(void *blk);
-
- #ifndef __MRC__ // doesn't allow new[] overloading?!
- void *operator new[](size_t bytes) { return operator new(bytes); }
- void operator delete[](void *blk) { operator delete(blk); }
- #endif
-
- //! Get an aligned memory block
- static void *NewAligned(size_t bytes,int bitalign = 128);
- //! Free an aligned memory block
- static void FreeAligned(void *blk);
-
- //! @} FLEXT_S_MEMORY
-
-// --- buffer/array stuff -----------------------------------------
-
- /*! \defgroup FLEXT_S_BUFFER Buffer handling
- @{
- */
-
-// not for Jmax at the moment
-#if FLEXT_SYS != FLEXT_SYS_JMAX
-
- //! Class for platform independent buffer handling
- class FLEXT_SHARE buffer
- {
- public:
- /*! \brief Construct buffer.
- \param s: symbol name, can be NULL
- \param delayed = true: only sets name, needs another Set(NULL) to really initialize the buffer
- \remark As externals can be created prior to the buffer objects they are pointing to, initialization should be done at loadbang!
- */
- buffer(const t_symbol *s = NULL,bool delayed = false);
-
- //! Destroy buffer
- ~buffer();
-
- /*! \brief Check if the data is valid
- */
- bool Ok() const { return sym != NULL && data != NULL; }
-
- /*! \brief Check if buffer is valid
- */
- bool Valid() const;
-
- /*! \brief Check and update if the buffer has been changed (e.g. resized)
- */
- bool Update();
-
- /*! \brief Set to specified buffer.
- \param nameonly: if true sets name only, but doesn't look at buffer actually
- */
- int Set(const t_symbol *s = NULL,bool nameonly = false);
-
- /*! \brief Declare buffer content as dirty.
- \param refr: if true forces immediate graphics refresh
- */
- void Dirty(bool refr = false);
-
- //! Get symbol of buffer
- t_symbol *Symbol() const { return const_cast<t_symbol *>(sym); }
-
- //! Get literal name of buffer
- const char *Name() const { return sym?GetString(sym):""; }
-
- /*! \brief Get pointer to buffer, channel and frame count.
- \remark Channels are interleaved
- */
- t_sample *Data() { return data; }
-
- //! Get channel count
- int Channels() const { return chns; }
- //! Get frame count
- int Frames() const { return frames; }
- //! Set frame count
- void Frames(int fr,bool keep = false);
-
- //! Graphic auto refresh interval
- void SetRefrIntv(float intv);
-
- protected:
- const t_symbol *sym;
- t_sample *data;
- int chns,frames;
-#if FLEXT_SYS == FLEXT_SYS_PD
- t_garray *arr;
- float interval;
- bool isdirty,ticking;
- t_clock *tick;
-
- private:
- static void cb_tick(buffer *b);
-#endif
- };
-
-#endif // jmax
-
-//! @} FLEXT_S_BUFFER
-
-// --- utilities --------------------------------------------------
-
- /*! \defgroup FLEXT_S_UTIL Utility functions
- @{
- */
-
- //! Copy an atom
- static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
-
- //! Print an atom
- static void PrintAtom(const t_atom &a,char *buf,int bufsz = 0);
- //! Scan an atom
- static bool ScanAtom(t_atom &a,const char *buf);
-
- //! Copy a list of atoms
- static t_atom *CopyList(int argc,const t_atom *argv);
- //! Copy a memory region
- static void CopyMem(void *dst,const void *src,int bytes);
- static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
- //! Set a memory region
- static void ZeroMem(void *dst,int bytes);
- static void SetSamples(t_sample *dst,int cnt,t_sample s);
- static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
-
- //! Sleep for an amount of time
- static void Sleep(double s);
-
-
- //! Get a 32 bit hash value frm an atom
- static unsigned long AtomHash(const t_atom &a);
-
- /*! \brief Fold value to a number of bits
- \remark Good for hash tables
- */
- static unsigned int FoldBits(unsigned long h,int bits);
-
- //! \brief How many bits are necessary to represent n
- static int Int2Bits(unsigned long n);
-
-//! @} FLEXT_S_UTIL
-
-// --- various symbols --------------------------------------------
-
- /*! \defgroup FLEXT_S_ATOM Atom/list handling
- @{
- */
-
- //! Symbol constant for "float"
- static const t_symbol *sym_float;
- //! Symbol constant for "symbol"
- static const t_symbol *sym_symbol;
- //! Symbol constant for "bang"
- static const t_symbol *sym_bang;
- //! Symbol constant for "list"
- static const t_symbol *sym_list;
- //! Symbol constant for "anything"
- static const t_symbol *sym_anything;
-
- /*! \brief Symbol constant for "int"
- \note Only the Max/MSP system has this defined as an internal type
- */
- static const t_symbol *sym_int;
-
- /*! Symbol constant for "pointer"
- \note Only PD has this defined as an internal type
- */
- static const t_symbol *sym_pointer;
-
-#if FLEXT_SYS == FLEXT_SYS_PD
- /*! \brief Symbol constant for "signal"
- \note PD only
- */
- static const t_symbol *sym_signal;
-#endif
-
-#if FLEXT_SYS == FLEXT_SYS_JMAX
- //! Make a symbol from a string
- static const t_symbol *MakeSymbol(const char *s) { return ::fts_new_symbol(s); }
- //! Get symbol string
- static const char *GetString(const t_symbol *s); // ** TODO **
-#else
- //! Make a symbol from a string
- static const t_symbol *MakeSymbol(const char *s) { return ::gensym(const_cast<char *>(s)); }
- //! Get symbol string
- static const char *GetString(const t_symbol *s) { return s->s_name; }
-#endif
- //! Check for symbol and get string
- static const char *GetAString(const t_symbol *s,const char *def = "") { return s?GetString(s):def; }
-
-// --- atom stuff ----------------------------------------
-
- //! Set atom from another atom
- static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
-
-#if FLEXT_SYS == FLEXT_SYS_JMAX
- //! Set atom from another atom
- static int GetType(const t_atom &a); // ** TODO **
-
- //! Check whether the atom is nothing
- static bool IsNothing(const t_atom &a) { return fts_is_a(&a,fts_void_class); }
- //! Set the atom to represent nothing
- static void SetNothing(t_atom &a) { fts_set_void(&a); }
-
- //! Check whether the atom is a float
- static bool IsFloat(const t_atom &a) { return fts_is_a(&a,fts_float_class); }
-#else
- //! Set atom from another atom
- static int GetType(const t_atom &a) { return a.a_type; }
-
- //! Check whether the atom is nothing
- static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
- //! Set the atom to represent nothing
- static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
-
- //! Check whether the atom is a float
- static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
-#endif
-
- //! Check whether the atom can be represented as a float
- static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
-
-#if FLEXT_SYS == FLEXT_SYS_JMAX
- //! Access the float value (without type check)
- static float GetFloat(const t_atom &a) { return fts_get_float(&a); }
- //! Set the atom to represent a float
- static void SetFloat(t_atom &a,float v) { fts_set_float(&a,v); }
-
- //! Check whether the atom is a symbol
- static bool IsSymbol(const t_atom &a) { return fts_is_a(&a,fts_symbol_class); }
-#else
- //! Access the float value (without type check)
- static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
- //! Set the atom to represent a float
- static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
-
- //! Check whether the atom is a symbol
- static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
-#endif
-
-#if FLEXT_SYS == FLEXT_SYS_PD
- //! Access the symbol value (without type check)
- static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_symbol; }
- //! Set the atom to represent a symbol
- static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast<t_symbol *>(s); }
-#elif FLEXT_SYS == FLEXT_SYS_MAX
- //! Access the symbol value (without type check)
- static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_sym; }
- //! Set the atom to represent a symbol
- static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_sym = const_cast<t_symbol *>(s); }
-#elif FLEXT_SYS == FLEXT_SYS_JMAX
- //! Access the symbol value (without type check)
- static t_symbol *GetSymbol(const t_atom &a); // ** TODO **
- //! Set the atom to represent a symbol
- static void SetSymbol(t_atom &a,const t_symbol *s) { fts_set_symbol(&a,s); }
-#else
-#error
-#endif
- //! Check for a symbol and get its value
- static t_symbol *GetASymbol(const t_atom &a,t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
-
- //! Check whether the atom is a string
- static bool IsString(const t_atom &a) { return IsSymbol(a); }
- //! Access the string value (without type check)
- static const char *GetString(const t_atom &a) { t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
- //! Check for a string and get its value
- static void GetAString(const t_atom &a,char *buf,int szbuf);
- //! Set the atom to represent a string
- static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
-
- //! Check whether the atom can be represented as an integer
- static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
-
- //! Set the atom to represent a boolean
- static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
- //! Check whether the atom can be represented as a boolean
- static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
- //! Check for an boolean and get its value
- static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
-
-#if FLEXT_SYS == FLEXT_SYS_PD
- //! Check for a float and get its value
- static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
-
- //! Check whether the atom is an integer
- static bool IsInt(const t_atom &) { return false; }
- //! Access the integer value (without type check)
- static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
- //! Check for an integer and get its value
- static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
- //! Set the atom to represent a integer (depending on the system)
- static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
-
- //! Check whether the atom strictly is a pointer
- static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
- //! Check whether the atom can be a pointer
- static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
- //! Access the pointer value (without type check)
- static void *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
- //! Check for a pointer and get its value
- static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
- //! Set the atom to represent a pointer
- static void SetPointer(t_atom &a,void *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
-
-#elif FLEXT_SYS == FLEXT_SYS_MAX
- //! Check for a float and get its value
- static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
-
- //! Check whether the atom is an int
- static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
- //! Access the integer value (without type check)
- static int GetInt(const t_atom &a) { return a.a_w.w_long; }
- //! Check for an integer and get its value
- static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
- //! Set the atom to represent an integer
- static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
-
- //! Check whether the atom strictly is a pointer
- static bool IsPointer(const t_atom &) { return false; }
- //! Check whether the atom can be a pointer
- static bool CanbePointer(const t_atom &a) { return IsInt(a); }
- //! Access the pointer value (without type check)
- static void *GetPointer(const t_atom &) { return NULL; }
- //! Check for a pointer and get its value
- static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsInt(a)?(void *)GetInt(a):def; }
- //! Set the atom to represent a pointer
- static void SetPointer(t_atom &a,void *p) { SetInt(a,(int)p); }
-#elif FLEXT_SYS == FLEXT_SYS_JMAX
- //! Check for a float and get its value
- static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
-
- //! Check whether the atom is an int
- static bool IsInt(const t_atom &a) { return fts_is_a(&a,fts_int_class); }
- //! Access the integer value (without type check)
- static int GetInt(const t_atom &a) { return fts_get_int(&a); }
- //! Check for an integer and get its value
- static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
- //! Set the atom to represent an integer
- static void SetInt(t_atom &a,int v) { fts_set_int(&a,v); }
-
- //! Check whether the atom strictly is a pointer
- static bool IsPointer(const t_atom &a) { return fts_is_a(&a,fts_pointer_class); }
- //! Check whether the atom can be a pointer
- static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
- //! Access the pointer value (without type check)
- static void *GetPointer(const t_atom &a) { return fts_get_pointer(&a); }
- //! Check for a pointer and get its value
- static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
- //! Set the atom to represent a pointer
- static void SetPointer(t_atom &a,void *p) { fts_set_pointer(&a,p); }
-#else
-#error "Platform not supported"
-#endif
-
-// --- atom list stuff -------------------------------------------
-
- //! Class representing a list of atoms
- class FLEXT_SHARE AtomList
- {
- public:
- //! Construct list
- AtomList(int argc = 0,const t_atom *argv = NULL);
- //! Construct list
- AtomList(const AtomList &a);
- //! Destroy list
- ~AtomList();
-
- //! Clear list
- AtomList &Clear() { return operator()(); }
-
- //! Set list
- AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
- //! Get list
- int Get(t_atom *argv,int mxsz = -1) const;
-
- //! Set list
- AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
- //! Set list by another AtomList
- AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
-
- //! Get number of atoms in the list
- int Count() const { return cnt; }
- //! Get a reference to an indexed atom
- t_atom &operator [](int ix) { return lst[ix]; }
- //! Get a reference to an indexed atom
- const t_atom &operator [](int ix) const { return lst[ix]; }
-
- //! Get a pointer to the list of atoms
- t_atom *Atoms() { return lst; }
- //! Get a pointer to the list of atoms
- const t_atom *Atoms() const { return lst; }
-
- //! Append an atom to the list
- AtomList &Append(const t_atom &a);
- //! Append an atom list to the list
- AtomList &Append(int argc,const t_atom *argv = NULL);
- //! Append an atom list to the list
- AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
- //! Prepend an atom to the list
- AtomList &Prepend(const t_atom &a);
- //! Prepend an atom list to the list
- AtomList &Prepend(int argc,const t_atom *argv = NULL);
- //! Prepend an atom list to the list
- AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
-
- //! Get a part of the list
- AtomList GetPart(int offs,int len) const;
- //! Set to a part of the list
- AtomList &Part(int offs,int len) { return (*this = GetPart(offs,len)); }
-
- protected:
- int cnt;
- t_atom *lst;
- };
-
-
- //! Class representing an "anything"
- class FLEXT_SHARE AtomAnything:
- public AtomList
- {
- public:
-#if FLEXT_SYS != FLEXT_SYS_JMAX
- //! Construct anything
- AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL);
-#endif
- //! Construct anything
- AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL);
- //! Construct anything
- AtomAnything(const AtomAnything &a);
-
- //! Clear anything
- AtomAnything &Clear() { return operator()(); }
-
- //! Get header symbol of anything
- const t_symbol *Header() const { return hdr; }
-
- //! Set header symbol of anything
- void Header(const t_symbol *h) { hdr = h; }
-
- //! Set anything
- AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
- {
- hdr = h; AtomList::operator()(argc,argv);
- return *this;
- }
-
- //! Set list by another AtomAnything
- AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
-
- protected:
- const t_symbol *hdr;
- };
-
-//! @} FLEXT_S_ATOM
-
-
-// --- clock stuff ------------------------------------------------
-
-
- /*! \defgroup FLEXT_S_CLOCK Flext clock functions
-
- At the moment there are none
-
- @{
- */
-
-//! @}
-
-
-// --- thread stuff -----------------------------------------------
-
-#ifdef FLEXT_THREADS
- /*! \defgroup FLEXT_S_THREAD Flext thread handling
- @{
- */
-
- //! thread type
-#if FLEXT_THREADS == FLEXT_THR_MP
- typedef MPTaskID thrid_t;
-#elif FLEXT_THREADS == FLEXT_THR_POSIX
- typedef pthread_t thrid_t;
-#else
-#error
-#endif
-
- /*! \brief Get current thread id
- */
- static thrid_t GetThreadId() {
-#if FLEXT_THREADS == FLEXT_THR_POSIX
- return pthread_self();
-#elif FLEXT_THREADS == FLEXT_THR_MP
- return MPCurrentTaskID();
-#else
-#error
-#endif
- }
-
- /*! \brief Get system thread id
- */
- static thrid_t GetSysThreadId() { return thrid; }
-
- //! Check if current thread is the realtime system's thread
- static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
-#if FLEXT_THREADS == FLEXT_THR_POSIX
- return pthread_equal(ref,t) != 0;
-#else
- return ref == t;
-#endif
- }
-
- //! Check if current thread is the realtime system's thread
- static bool IsSystemThread() { return IsThread(GetSysThreadId()); }
-
-
- /*! \brief Thread parameters
- \internal
- */
- class thr_params
- {
- public:
- thr_params(int n = 1);
- ~thr_params();
-
- void set_any(const t_symbol *s,int argc,const t_atom *argv);
- void set_list(int argc,const t_atom *argv);
-
- flext_base *cl;
- union _data {
- bool _bool;
- float _float;
- int _int;
- t_symptr _t_symptr;
- struct { AtomAnything *args; } _any;
- struct { AtomList *args; } _list;
- struct { void *data; } _ext;
- } *var;
- };
-
- /*! \brief This represents an entry to the list of active method threads
- \internal
- */
- class thr_entry
- {
- public:
- thr_entry(void (*m)(thr_params *),thr_params *p,thrid_t id = GetThreadId());
-
- //! \brief Check if this class represents the current thread
- bool Is(thrid_t id = GetThreadId()) const { return IsThread(thrid,id); }
-
- flext_base *This() const { return th; }
- thrid_t Id() const { return thrid; }
-
- flext_base *th;
- void (*meth)(thr_params *);
- thr_params *params;
- thrid_t thrid;
- bool active,shouldexit;
-#if FLEXT_THREADS == FLEXT_THR_MP
- int weight;
-#endif
- thr_entry *nxt;
- };
-
-protected:
-
- static thrid_t thrhelpid;
- static bool StartHelper();
- static bool StopHelper();
- static void ThrHelper(void *);
-
- //! system's thread id
- static thrid_t thrid; // the system thread
-
-public:
-
- /*! \brief Yield to other threads
- \remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
- */
- static void ThrYield() {
-#if FLEXT_THREADS == FLEXT_THR_POSIX
- sched_yield();
-#elif FLEXT_THREADS == FLEXT_THR_MP
- MPYield();
-#else
-#error
-#endif
- }
-
- /*! \brief Query whether task is preemptive
- */
- static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
-#if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
- return true;
-#elif FLEXT_THREADS == FLEXT_THR_MP
- return MPTaskIsPreemptive(t);
-#else
-#error
-#endif
- }
-
-
- /*! \brief Increase/Decrease priority of a thread
- */
- static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),thrid_t thr = GetThreadId());
-
- /*! \brief Get priority of a thread
- */
- static int GetPriority(thrid_t thr = GetThreadId());
-
- /*! \brief Set priority of a thread
- */
- static bool SetPriority(int p,thrid_t thr = GetThreadId());
-
- /*! \brief Thread mutex
- \sa pthreads documentation
- */
- class FLEXT_SHARE ThrMutex
-#if FLEXT_THREADS == FLEXT_THR_POSIX
- {
- public:
- //! Construct thread mutex
- ThrMutex() /*: cnt(0)*/ { pthread_mutex_init(&mutex,NULL); }
- //! Destroy thread mutex
- ~ThrMutex() { pthread_mutex_destroy(&mutex); }
-
- //! Lock thread mutex
- bool Lock() { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
- //! Lock thread mutex
- bool WaitForLock(float tm) { /*cnt = 1;*/ return pthread_mutex_lock(&mutex) == 0; }
- //! Try to lock, but don't wait
- bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
- //! Unlock thread mutex
- bool Unlock() { /*cnt = 0;*/ return pthread_mutex_unlock(&mutex) == 0; }
-/*
- //! Lock thread mutex (increase lock count by one)
- void Push() { if(!cnt++) Lock(); }
- //! Unlock thread mutex if lock count reaches zero
- void Pop() { if(!--cnt) Unlock(); }
-*/
- protected:
- pthread_mutex_t mutex;
-// int cnt;
- };
-#elif FLEXT_THREADS == FLEXT_THR_MP
- {
- public:
- //! Construct thread mutex
- ThrMutex() /*: cnt(0)*/ { MPCreateCriticalRegion(&crit); }
- //! Destroy thread mutex
- ~ThrMutex() { MPDeleteCriticalRegion(crit); }
-
- //! Lock thread mutex
- bool Lock() { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
- //! Wait to lock thread mutex
- bool WaitForLock(float tm) { /*cnt = 1;*/ return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
- //! Try to lock, but don't wait
- bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
- //! Unlock thread mutex
- bool Unlock() { /*cnt = 0;*/ return MPExitCriticalRegion(crit) == noErr; }
-
- protected:
- MPCriticalRegionID crit;
- };
-#else
-#error "Not implemented"
-#endif
-
- /*! \brief Thread conditional
- \sa pthreads documentation
- */
- class FLEXT_SHARE ThrCond
-#if FLEXT_THREADS == FLEXT_THR_POSIX
- :public ThrMutex
- {
- public:
- //! Construct thread conditional
- ThrCond() { pthread_cond_init(&cond,NULL); }
- //! Destroy thread conditional
- ~ThrCond() { pthread_cond_destroy(&cond); }
-
- //! Wait for condition
- bool Wait() {
- Lock();
- bool ret = pthread_cond_wait(&cond,&mutex) == 0;
- Unlock();
- return ret;
- }
-
- /*! \brief Wait for condition (for a certain time)
- \param ftime Wait time in seconds
- \ret 0 = signalled, 1 = timed out
- \remark Depending on the implementation ftime may not be fractional.
- \remark So if ftime = 0 this may suck away your cpu if used in a signalled loop.
- */
- bool TimedWait(float ftime)
- {
- timespec tm;
-#if 0 // find out when the following is defined
- clock_gettime(CLOCK_REALTIME,tm);
- tm.tv_nsec += (long)((ftime-(long)ftime)*1.e9);
- long nns = tm.tv_nsec%1000000000;
- tm.tv_sec += (long)ftime+(tm.tv_nsec-nns)/1000000000;
- tm.tv_nsec = nns;
-#else
- tm.tv_sec = time(NULL)+(long)ftime;
- tm.tv_nsec = 0;
-#endif
- Lock();
- bool ret = pthread_cond_timedwait(&cond,&mutex,&tm) == 0;
- Unlock();
- return ret;
- }
-
- //! Signal condition
- bool Signal()
- {
- Lock();
- bool ret = pthread_cond_signal(&cond) == 0;
- Unlock();
- return ret;
- }
- //! Broadcast condition
-// int Broadcast() { return pthread_cond_broadcast(&cond); }
- protected:
- pthread_cond_t cond;
- };
-#elif FLEXT_THREADS == FLEXT_THR_MP
- {
- public:
- //! Construct thread conditional
- ThrCond() { MPCreateEvent(&ev); }
- //! Destroy thread conditional
- ~ThrCond() { MPDeleteEvent(ev); }
-
- //! Wait for condition
- bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
-
- /*! \brief Wait for condition (for a certain time)
- \param time Wait time in seconds
- */
- bool TimedWait(float tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
-
- //! Signal condition
- bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
- //! Broadcast condition
-// int Broadcast() { return pthread_cond_broadcast(&cond); }
- protected:
- MPEventID ev;
- };
-#else
-#error "Not implemented"
-#endif
-
- /*! \brief Add current thread to list of active threads
- \return true on success
- \internal
- */
- static bool PushThread();
-
- /*! \brief Remove current thread from list of active threads
- \internal
- */
- static void PopThread();
-
- /*! \brief Launch a thread
- \remark thr_params *p may be NULL if not needed
- */
- static bool LaunchThread(void (*meth)(thr_params *p),thr_params *p);
-
-//! @} FLEXT_S_THREAD
-
-#endif // FLEXT_THREADS
-
-//! @}
-
-protected:
-#ifdef __MRC__
- friend class flext_obj;
-#endif
- static void Setup();
-
- static bool chktilde(const char *objname);
-};
-
-#endif
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001-2003 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flsupport.h
+ \brief flext support functions and classes
+*/
+
+#ifndef __FLSUPPORT_H
+#define __FLSUPPORT_H
+
+#include "flstdc.h"
+#include <time.h>
+
+class FLEXT_SHARE flext_base;
+
+/*! \brief Flext support class
+ A number of methods (most are static functions) are defined here for convenience.
+ This class doesn't define any data members, hence it can be inherited to all
+ classes (not only PD objects) to profit from the cross-platform functionality.
+ Examples are the overloaded memory allocation, atom and atom list functions,
+ thread functions and classes, the sample buffer class and others.
+*/
+class FLEXT_SHARE flext {
+
+ /*! \defgroup FLEXT_SUPPORT Flext support class
+ @{
+ */
+public:
+
+// --- console output -----------------------------------------------
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! post message to console
+ static void post(const char *s,...);
+ //! post error message to console
+ static void error(const char *s,...);
+#endif
+
+// --- memory -------------------------------------------------------
+
+ /*! \defgroup FLEXT_S_MEMORY Memory allocation functions
+ @{
+ */
+
+ /*! Overloaded new memory allocation method
+ \warning Max/MSP (or MacOS) allows only 16K in overdrive mode!
+ */
+ void *operator new(size_t bytes);
+ //! Overloaded delete method
+ void operator delete(void *blk);
+
+ #ifndef __MRC__ // doesn't allow new[] overloading?!
+ void *operator new[](size_t bytes) { return operator new(bytes); }
+ void operator delete[](void *blk) { operator delete(blk); }
+ #endif
+
+ //! Get an aligned memory block
+ static void *NewAligned(size_t bytes,int bitalign = 128);
+ //! Free an aligned memory block
+ static void FreeAligned(void *blk);
+
+ //! @} FLEXT_S_MEMORY
+
+// --- buffer/array stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_S_BUFFER Buffer handling
+ @{
+ */
+
+// not for Jmax at the moment
+#if FLEXT_SYS != FLEXT_SYS_JMAX
+
+ //! Class for platform independent buffer handling
+ class FLEXT_SHARE buffer
+ {
+ public:
+ /*! \brief Construct buffer.
+ \param s: symbol name, can be NULL
+ \param delayed = true: only sets name, needs another Set(NULL) to really initialize the buffer
+ \remark As externals can be created prior to the buffer objects they are pointing to, initialization should be done at loadbang!
+ */
+ buffer(const t_symbol *s = NULL,bool delayed = false);
+
+ //! Destroy buffer
+ ~buffer();
+
+ /*! \brief Check if the data is valid
+ */
+ bool Ok() const { return sym != NULL && data != NULL; }
+
+ /*! \brief Check if buffer is valid
+ */
+ bool Valid() const;
+
+ /*! \brief Check and update if the buffer has been changed (e.g. resized)
+ */
+ bool Update();
+
+ /*! \brief Set to specified buffer.
+ \param nameonly: if true sets name only, but doesn't look at buffer actually
+ */
+ int Set(const t_symbol *s = NULL,bool nameonly = false);
+
+ /*! \brief Declare buffer content as dirty.
+ \param refr: if true forces immediate graphics refresh
+ */
+ void Dirty(bool refr = false);
+
+ //! Get symbol of buffer
+ t_symbol *Symbol() const { return const_cast<t_symbol *>(sym); }
+
+ //! Get literal name of buffer
+ const char *Name() const { return sym?GetString(sym):""; }
+
+ /*! \brief Get pointer to buffer, channel and frame count.
+ \remark Channels are interleaved
+ */
+ t_sample *Data() { return data; }
+
+ //! Get channel count
+ int Channels() const { return chns; }
+ //! Get frame count
+ int Frames() const { return frames; }
+ //! Set frame count
+ void Frames(int fr,bool keep = false);
+
+ //! Graphic auto refresh interval
+ void SetRefrIntv(float intv);
+
+ protected:
+ const t_symbol *sym;
+ t_sample *data;
+ int chns,frames;
+#if FLEXT_SYS == FLEXT_SYS_PD
+ t_garray *arr;
+ float interval;
+ bool isdirty,ticking;
+ t_clock *tick;
+
+ private:
+ static void cb_tick(buffer *b);
+#endif
+ };
+
+#endif // jmax
+
+//! @} FLEXT_S_BUFFER
+
+// --- utilities --------------------------------------------------
+
+ /*! \defgroup FLEXT_S_UTIL Utility functions
+ @{
+ */
+
+ //! Copy an atom
+ static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
+
+ //! Print an atom
+ static void PrintAtom(const t_atom &a,char *buf,int bufsz = 0);
+ //! Scan an atom
+ static bool ScanAtom(t_atom &a,const char *buf);
+
+ //! Copy a list of atoms
+ static t_atom *CopyList(int argc,const t_atom *argv);
+ //! Copy a memory region
+ static void CopyMem(void *dst,const void *src,int bytes);
+ //! 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<char *>(s)); }
+ //! Get symbol string
+ static const char *GetString(const t_symbol *s) { return s->s_name; }
+#endif
+ //! Check for symbol and get string
+ static const char *GetAString(const t_symbol *s,const char *def = "") { return s?GetString(s):def; }
+
+// --- atom stuff ----------------------------------------
+
+ //! Set atom from another atom
+ static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Set atom from another atom
+ static int GetType(const t_atom &a); // ** TODO **
+
+ //! Check whether the atom is nothing
+ static bool IsNothing(const t_atom &a) { return fts_is_a(&a,fts_void_class); }
+ //! Set the atom to represent nothing
+ static void SetNothing(t_atom &a) { fts_set_void(&a); }
+
+ //! Check whether the atom is a float
+ static bool IsFloat(const t_atom &a) { return fts_is_a(&a,fts_float_class); }
+#else
+ //! Set atom from another atom
+ static int GetType(const t_atom &a) { return a.a_type; }
+
+ //! Check whether the atom is nothing
+ static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
+ //! Set the atom to represent nothing
+ static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
+
+ //! Check whether the atom is a float
+ static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
+#endif
+
+ //! Check whether the atom can be represented as a float
+ static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+#if FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Access the float value (without type check)
+ static float GetFloat(const t_atom &a) { return fts_get_float(&a); }
+ //! Set the atom to represent a float
+ static void SetFloat(t_atom &a,float v) { fts_set_float(&a,v); }
+
+ //! Check whether the atom is a symbol
+ static bool IsSymbol(const t_atom &a) { return fts_is_a(&a,fts_symbol_class); }
+#else
+ //! Access the float value (without type check)
+ static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
+ //! Set the atom to represent a float
+ static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
+
+ //! Check whether the atom is a symbol
+ static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
+#endif
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_symbol; }
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast<t_symbol *>(s); }
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_sym; }
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_sym = const_cast<t_symbol *>(s); }
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a); // ** TODO **
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { fts_set_symbol(&a,s); }
+#else
+#error
+#endif
+ //! Check for a symbol and get its value
+ static t_symbol *GetASymbol(const t_atom &a,t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
+
+ //! Check whether the atom is a string
+ static bool IsString(const t_atom &a) { return IsSymbol(a); }
+ //! Access the string value (without type check)
+ static const char *GetString(const t_atom &a) { t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
+ //! Check for a string and get its value
+ static void GetAString(const t_atom &a,char *buf,int szbuf);
+ //! Set the atom to represent a string
+ static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
+
+ //! Check whether the atom can be represented as an integer
+ static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+ //! Set the atom to represent a boolean
+ static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
+ //! Check whether the atom can be represented as a boolean
+ static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
+ //! Check for an boolean and get its value
+ static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
+
+#if FLEXT_SYS == FLEXT_SYS_PD
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
+
+ //! Check whether the atom is an integer
+ static bool IsInt(const t_atom &) { return false; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
+ //! Set the atom to represent a integer (depending on the system)
+ static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
+
+ //! Check whether the atom strictly is a pointer
+ static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
+
+#elif FLEXT_SYS == FLEXT_SYS_MAX
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
+
+ //! Check whether the atom is an int
+ static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return a.a_w.w_long; }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
+ //! Set the atom to represent an integer
+ static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
+
+ //! Check whether the atom strictly is a pointer
+ static bool IsPointer(const t_atom &) { return false; }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsInt(a); }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &) { return NULL; }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsInt(a)?(void *)GetInt(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { SetInt(a,(int)p); }
+#elif FLEXT_SYS == FLEXT_SYS_JMAX
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
+
+ //! Check whether the atom is an int
+ static bool IsInt(const t_atom &a) { return fts_is_a(&a,fts_int_class); }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return fts_get_int(&a); }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
+ //! Set the atom to represent an integer
+ static void SetInt(t_atom &a,int v) { fts_set_int(&a,v); }
+
+ //! Check whether the atom strictly is a pointer
+ static bool IsPointer(const t_atom &a) { return fts_is_a(&a,fts_pointer_class); }
+ //! Check whether the atom can be a pointer
+ static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &a) { return fts_get_pointer(&a); }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &a,void *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,void *p) { fts_set_pointer(&a,p); }
+#else
+#error "Platform not supported"
+#endif
+
+// --- atom list stuff -------------------------------------------
+
+ //! Class representing a list of atoms
+ class FLEXT_SHARE AtomList
+ {
+ public:
+ //! Construct list
+ AtomList(int argc = 0,const t_atom *argv = NULL);
+ //! Construct list
+ AtomList(const AtomList &a);
+ //! Destroy list
+ ~AtomList();
+
+ //! Clear list
+ AtomList &Clear() { return operator()(); }
+
+ //! Set list
+ AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
+ //! Get list
+ int Get(t_atom *argv,int mxsz = -1) const;
+
+ //! Set list
+ AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
+ //! Set list by another AtomList
+ AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
+
+ //! Get number of atoms in the list
+ int Count() const { return cnt; }
+ //! Get a reference to an indexed atom
+ t_atom &operator [](int ix) { return lst[ix]; }
+ //! Get a reference to an indexed atom
+ const t_atom &operator [](int ix) const { return lst[ix]; }
+
+ //! Get a pointer to the list of atoms
+ t_atom *Atoms() { return lst; }
+ //! Get a pointer to the list of atoms
+ const t_atom *Atoms() const { return lst; }
+
+ //! Append an atom to the list
+ AtomList &Append(const t_atom &a);
+ //! Append an atom list to the list
+ AtomList &Append(int argc,const t_atom *argv = NULL);
+ //! Append an atom list to the list
+ AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
+ //! Prepend an atom to the list
+ AtomList &Prepend(const t_atom &a);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(int argc,const t_atom *argv = NULL);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
+
+ //! Get a part of the list
+ AtomList GetPart(int offs,int len) const;
+ //! Set to a part of the list
+ AtomList &Part(int offs,int len) { return (*this = GetPart(offs,len)); }
+
+ protected:
+ int cnt;
+ t_atom *lst;
+ };
+
+
+ //! Class representing an "anything"
+ class FLEXT_SHARE AtomAnything:
+ public AtomList
+ {
+ public:
+#if FLEXT_SYS != FLEXT_SYS_JMAX
+ //! Construct anything
+ AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL);
+#endif
+ //! Construct anything
+ AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL);
+ //! Construct anything
+ AtomAnything(const AtomAnything &a);
+
+ //! Clear anything
+ AtomAnything &Clear() { return operator()(); }
+
+ //! Get header symbol of anything
+ const t_symbol *Header() const { return hdr; }
+
+ //! Set header symbol of anything
+ void Header(const t_symbol *h) { hdr = h; }
+
+ //! Set anything
+ AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
+ {
+ hdr = h; AtomList::operator()(argc,argv);
+ return *this;
+ }
+
+ //! Set list by another AtomAnything
+ AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
+
+ protected:
+ const t_symbol *hdr;
+ };
+
+//! @} FLEXT_S_ATOM
+
+
+// --- 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 <windows.h>
+#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX
+#include <unistd.h>
+#include <sys/time.h>
+#elif FLEXT_OS == FLEXT_OS_MAC
+#include <Timer.h>
+#include <Threads.h>
+#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 <string.h>
-#if FLEXT_OS == FLEXT_OS_WIN
-#include <windows.h>
-#elif FLEXT_OS == FLEXT_OS_LINUX || FLEXT_OS == FLEXT_OS_IRIX || FLEXT_OSAPI == FLEXT_OSAPI_MAC_OSX
-#include <unistd.h>
-#elif FLEXT_OS == FLEXT_OS_MAC
-#include <Timer.h>
-#include <Threads.h>
-#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
--- a/externals/grill/flext/tutorial/lib1/lib1.cw
+++ b/externals/grill/flext/tutorial/lib1/lib1.cw
Binary files 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
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-timer1
Binary files 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 <flext.h>
+
+// 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
--- /dev/null
+++ b/externals/grill/flext/tutorial/timer1/timer1.cw
Binary files 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