aboutsummaryrefslogtreecommitdiff
path: root/externals/grill
diff options
context:
space:
mode:
authorThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:07:10 +0000
committerThomas Grill <xovo@users.sourceforge.net>2002-10-22 23:07:10 +0000
commitd62e56f4df9594f72ce501f5e19c974fd18e7295 (patch)
tree635d4af7a7c2425098e60ca277086ec436b617f7 /externals/grill
parentc6f373c281ecb5cd1f4aa7a070e15cc61ab8793c (diff)
This commit was generated by cvs2svn to compensate for changes in r186,
which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=187
Diffstat (limited to 'externals/grill')
-rw-r--r--externals/grill/flext/build-pd-bcc.bat3
-rw-r--r--externals/grill/flext/build-pd-cygwin.sh10
-rw-r--r--externals/grill/flext/build-pd-darwin.sh12
-rw-r--r--externals/grill/flext/build-pd-linux.sh11
-rw-r--r--externals/grill/flext/build-pd-msvc.bat4
-rw-r--r--externals/grill/flext/config-pd-bcc.txt24
-rw-r--r--externals/grill/flext/config-pd-cygwin.txt19
-rw-r--r--externals/grill/flext/config-pd-darwin.txt20
-rw-r--r--externals/grill/flext/config-pd-linux.txt26
-rw-r--r--externals/grill/flext/config-pd-msvc.txt24
-rw-r--r--externals/grill/flext/flext.cwbin0 -> 84286 bytes
-rw-r--r--externals/grill/flext/flext.doxy192
-rw-r--r--externals/grill/flext/flext.dsp238
-rw-r--r--externals/grill/flext/flext.mpw78
-rw-r--r--externals/grill/flext/gpl.txt346
-rw-r--r--externals/grill/flext/license.txt49
-rw-r--r--externals/grill/flext/make-files.txt4
-rw-r--r--externals/grill/flext/make-inc.pd-msvc99
-rw-r--r--externals/grill/flext/makefile.pd-bcc87
-rw-r--r--externals/grill/flext/makefile.pd-cygwin108
-rw-r--r--externals/grill/flext/makefile.pd-darwin103
-rw-r--r--externals/grill/flext/makefile.pd-linux96
-rw-r--r--externals/grill/flext/makefile.pd-msvc31
-rw-r--r--externals/grill/flext/readme.txt262
-rw-r--r--externals/grill/flext/source/flatom.cpp139
-rw-r--r--externals/grill/flext/source/flattr.cpp190
-rw-r--r--externals/grill/flext/source/flbase.cpp118
-rw-r--r--externals/grill/flext/source/flbase.h426
-rw-r--r--externals/grill/flext/source/flbuf.cpp255
-rw-r--r--externals/grill/flext/source/flclass.h599
-rwxr-xr-xexternals/grill/flext/source/flcwmax-thr.h20
-rw-r--r--externals/grill/flext/source/flcwmax.h26
-rw-r--r--externals/grill/flext/source/fldefs.h912
-rw-r--r--externals/grill/flext/source/fldoxygen.h22
-rw-r--r--externals/grill/flext/source/fldsp.cpp119
-rw-r--r--externals/grill/flext/source/fldsp.h140
-rw-r--r--externals/grill/flext/source/flext.cpp748
-rw-r--r--externals/grill/flext/source/flext.h45
-rw-r--r--externals/grill/flext/source/flinternal.h111
-rwxr-xr-xexternals/grill/flext/source/fllib.cpp386
-rwxr-xr-xexternals/grill/flext/source/flmspbuffer.h83
-rw-r--r--externals/grill/flext/source/flout.cpp201
-rw-r--r--externals/grill/flext/source/flsndobj.cpp107
-rw-r--r--externals/grill/flext/source/flsndobj.h83
-rw-r--r--externals/grill/flext/source/flstdc.h163
-rw-r--r--externals/grill/flext/source/flsupport.cpp58
-rw-r--r--externals/grill/flext/source/flsupport.h438
-rw-r--r--externals/grill/flext/source/flthr.cpp237
-rw-r--r--externals/grill/flext/source/flutil.cpp68
-rwxr-xr-xexternals/grill/flext/source/flxlet.cpp88
-rwxr-xr-xexternals/grill/flext/tutorial/adv1/adv1.cwbin0 -> 98601 bytes
-rw-r--r--externals/grill/flext/tutorial/adv1/adv1.dsp96
-rwxr-xr-xexternals/grill/flext/tutorial/adv1/main.cpp104
-rw-r--r--externals/grill/flext/tutorial/build-pd-bcc.bat27
-rw-r--r--externals/grill/flext/tutorial/build-pd-cygwin.sh3
-rw-r--r--externals/grill/flext/tutorial/build-pd-linux.sh4
-rw-r--r--externals/grill/flext/tutorial/build-pd-msvc.bat11
-rw-r--r--externals/grill/flext/tutorial/config-pd-bcc.txt21
-rw-r--r--externals/grill/flext/tutorial/config-pd-cygwin.txt13
-rw-r--r--externals/grill/flext/tutorial/config-pd-linux.txt19
-rw-r--r--externals/grill/flext/tutorial/config-pd-msvc.txt16
-rwxr-xr-xexternals/grill/flext/tutorial/gpl.txt346
-rwxr-xr-xexternals/grill/flext/tutorial/license.txt50
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-bcc75
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-cygwin58
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-linux57
-rw-r--r--externals/grill/flext/tutorial/makefile.pd-msvc48
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-adv1bin0 -> 265 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-signal1bin0 -> 331 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-signal2bin0 -> 410 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-simple1bin0 -> 404 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-simple2bin0 -> 303 bytes
-rwxr-xr-xexternals/grill/flext/tutorial/maxmsp/ex-simple3bin0 -> 381 bytes
-rw-r--r--externals/grill/flext/tutorial/pd/ex-adv1.pd14
-rw-r--r--externals/grill/flext/tutorial/pd/ex-signal1.pd16
-rw-r--r--externals/grill/flext/tutorial/pd/ex-signal2.pd17
-rw-r--r--externals/grill/flext/tutorial/pd/ex-simple1.pd10
-rw-r--r--externals/grill/flext/tutorial/pd/ex-simple2.pd13
-rw-r--r--externals/grill/flext/tutorial/pd/ex-simple3.pd18
-rw-r--r--externals/grill/flext/tutorial/pd/ex-thread1.pd34
-rw-r--r--externals/grill/flext/tutorial/pd/ex-thread2.pd40
-rw-r--r--externals/grill/flext/tutorial/readme.txt36
-rw-r--r--externals/grill/flext/tutorial/signal1/main.cpp129
-rw-r--r--externals/grill/flext/tutorial/signal1/signal1.cwbin0 -> 102333 bytes
-rw-r--r--externals/grill/flext/tutorial/signal1/signal1.dsp95
-rw-r--r--externals/grill/flext/tutorial/signal2/main.cpp80
-rw-r--r--externals/grill/flext/tutorial/signal2/signal2.cwbin0 -> 104217 bytes
-rw-r--r--externals/grill/flext/tutorial/signal2/signal2.dsp95
-rwxr-xr-xexternals/grill/flext/tutorial/simple1/main.cpp78
-rwxr-xr-xexternals/grill/flext/tutorial/simple1/simple1.cwbin0 -> 94211 bytes
-rw-r--r--externals/grill/flext/tutorial/simple1/simple1.dsp95
-rwxr-xr-xexternals/grill/flext/tutorial/simple2/main.cpp80
-rwxr-xr-xexternals/grill/flext/tutorial/simple2/simple2.cwbin0 -> 98601 bytes
-rw-r--r--externals/grill/flext/tutorial/simple2/simple2.dsp95
-rw-r--r--externals/grill/flext/tutorial/simple3/main.cpp90
-rw-r--r--externals/grill/flext/tutorial/simple3/simple3.cwbin0 -> 102333 bytes
-rw-r--r--externals/grill/flext/tutorial/simple3/simple3.dsp95
-rw-r--r--externals/grill/flext/tutorial/thread1/main.cpp79
-rw-r--r--externals/grill/flext/tutorial/thread1/thread1.cwbin0 -> 89119 bytes
-rw-r--r--externals/grill/flext/tutorial/thread1/thread1.dsp104
-rw-r--r--externals/grill/flext/tutorial/thread2/main.cpp132
-rwxr-xr-xexternals/grill/flext/tutorial/thread2/thread2.cwbin0 -> 89119 bytes
-rw-r--r--externals/grill/flext/tutorial/thread2/thread2.dsp95
-rw-r--r--externals/grill/flext/tutorial/tutorial.dsw161
104 files changed, 10277 insertions, 0 deletions
diff --git a/externals/grill/flext/build-pd-bcc.bat b/externals/grill/flext/build-pd-bcc.bat
new file mode 100644
index 00000000..b1e6eaf4
--- /dev/null
+++ b/externals/grill/flext/build-pd-bcc.bat
@@ -0,0 +1,3 @@
+@echo --- Building flext with BorlandC++ ---
+
+make -f makefile.pd-bcc
diff --git a/externals/grill/flext/build-pd-cygwin.sh b/externals/grill/flext/build-pd-cygwin.sh
new file mode 100644
index 00000000..8eb7bcab
--- /dev/null
+++ b/externals/grill/flext/build-pd-cygwin.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+. config-pd-cygwin.txt
+
+make -f makefile.pd-cygwin &&
+{
+ if [ $INSTALL = "yes" ]; then
+ make -f makefile.pd-cygwin install
+ fi
+}
diff --git a/externals/grill/flext/build-pd-darwin.sh b/externals/grill/flext/build-pd-darwin.sh
new file mode 100644
index 00000000..57bb9a68
--- /dev/null
+++ b/externals/grill/flext/build-pd-darwin.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+. config-pd-darwin.txt
+
+make -f makefile.pd-darwin &&
+{
+ if [ $INSTALL = "yes" ]; then
+# echo Now install as root
+# sudo make -f makefile.pd-darwin install
+ make -f makefile.pd-darwin install
+ fi
+}
diff --git a/externals/grill/flext/build-pd-linux.sh b/externals/grill/flext/build-pd-linux.sh
new file mode 100644
index 00000000..90e4a04a
--- /dev/null
+++ b/externals/grill/flext/build-pd-linux.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+. config-pd-linux.txt
+
+make -f makefile.pd-linux &&
+{
+ if [ $INSTALL = "yes" ]; then
+ echo Now install as root
+ su -c "make -f makefile.pd-linux install"
+ fi
+}
diff --git a/externals/grill/flext/build-pd-msvc.bat b/externals/grill/flext/build-pd-msvc.bat
new file mode 100644
index 00000000..addd399f
--- /dev/null
+++ b/externals/grill/flext/build-pd-msvc.bat
@@ -0,0 +1,4 @@
+@echo --- Building flext with MS Visual C++ ---
+
+nmake -f makefile.pd-msvc clean
+nmake -f makefile.pd-msvc
diff --git a/externals/grill/flext/config-pd-bcc.txt b/externals/grill/flext/config-pd-bcc.txt
new file mode 100644
index 00000000..e4582bca
--- /dev/null
+++ b/externals/grill/flext/config-pd-bcc.txt
@@ -0,0 +1,24 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=c:\programme\audio\pd
+
+# where is BorlandC++?
+BCCPATH=c:\programme\prog\bcc55
+
+# where is the SndObj include directory? (leave blank to disable SndObj support)
+SNDOBJ=f:\prog\packs\sndobj\include
+
+# build directory for flext libraries?
+OUTPATH=.\pd-bcc
+
+# should the flext stuff be installed? (yes/no)
+INSTALL=yes
+
+# where should flext libraries be installed?
+INSTDIR=$(PDPATH)\flext
+
+
+
diff --git a/externals/grill/flext/config-pd-cygwin.txt b/externals/grill/flext/config-pd-cygwin.txt
new file mode 100644
index 00000000..0ec5840d
--- /dev/null
+++ b/externals/grill/flext/config-pd-cygwin.txt
@@ -0,0 +1,19 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=/cygdrive/c/programme/audio/pd
+
+# where is the SndObj include directory? (leave blank to disable SndObj support)
+SNDOBJ=/cygdrive/f/prog/packs/sndobj/include
+
+# where should flext libraries be built?
+TARGDIR=./pd-cygwin
+
+# should the flext stuff be installed? (yes/no)
+INSTALL=yes
+
+# where should flext libraries be installed?
+INSTDIR=${PDPATH}/flext
+
diff --git a/externals/grill/flext/config-pd-darwin.txt b/externals/grill/flext/config-pd-darwin.txt
new file mode 100644
index 00000000..bb2d86c0
--- /dev/null
+++ b/externals/grill/flext/config-pd-darwin.txt
@@ -0,0 +1,20 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where are the PD header files?
+PDPATH=/usr/local/pd/src
+
+# where is the SndObj include directory? (leave blank to disable SndObj support)
+# SNDOBJ=/usr/src/sndobj/include
+
+# where should flext libraries be built?
+TARGDIR=./pd-darwin
+
+# should the flext stuff be installed? (yes/no)
+INSTALL=yes
+
+# where should flext libraries be installed?
+INSTDIR=/usr/local/pd/flext
+
+
diff --git a/externals/grill/flext/config-pd-linux.txt b/externals/grill/flext/config-pd-linux.txt
new file mode 100644
index 00000000..e6fa653f
--- /dev/null
+++ b/externals/grill/flext/config-pd-linux.txt
@@ -0,0 +1,26 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# your c++ compiler (normally g++)
+CXX=g++ #-3.2
+
+# where are the PD header files?
+# if it is a system include path (like /usr/local/include)
+# you should leave it blank (as e.g. g++ 3.2 complains about it)
+PDPATH=
+
+# where is the SndObj include directory? (leave blank to disable SndObj support)
+SNDOBJ=/usr/local/include/SndObj
+
+# where should flext libraries be built?
+TARGDIR=./pd-linux
+
+# should the flext stuff be installed? (yes/no)
+INSTALL=yes
+
+# where should flext libraries be installed?
+INSTDIR=/usr/local/lib/pd/flext
+
+
+
diff --git a/externals/grill/flext/config-pd-msvc.txt b/externals/grill/flext/config-pd-msvc.txt
new file mode 100644
index 00000000..55702a90
--- /dev/null
+++ b/externals/grill/flext/config-pd-msvc.txt
@@ -0,0 +1,24 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=c:\programme\audio\pd
+
+# where is MS VC++?
+MSVCPATH="c:\programme\prog\microsoft visual studio\VC98"
+
+# where is the SndObj include directory? (leave blank to disable SndObj support)
+SNDOBJ=f:\prog\packs\sndobj\include
+
+# where should flext libraries be built?
+# object files will be placed in subfolders
+OUTPATH=".\pd-msvc"
+
+# should the flext stuff be installed? (yes/no)
+INSTALL=yes
+
+# where should flext libraries be installed?
+INSTDIR=$(PDPATH)\flext
+
+
diff --git a/externals/grill/flext/flext.cw b/externals/grill/flext/flext.cw
new file mode 100644
index 00000000..06d4f14e
--- /dev/null
+++ b/externals/grill/flext/flext.cw
Binary files differ
diff --git a/externals/grill/flext/flext.doxy b/externals/grill/flext/flext.doxy
new file mode 100644
index 00000000..9c581158
--- /dev/null
+++ b/externals/grill/flext/flext.doxy
@@ -0,0 +1,192 @@
+# Doxyfile 1.2.13-20020210
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME = flext
+PROJECT_NUMBER = "version 0.4.0"
+OUTPUT_DIRECTORY = f:/prog/max/flext/doc/
+OUTPUT_LANGUAGE = English
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+EXTRACT_STATIC = NO
+EXTRACT_LOCAL_CLASSES = YES
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = NO
+STRIP_FROM_PATH =
+INTERNAL_DOCS = YES
+STRIP_CODE_COMMENTS = YES
+CASE_SENSE_NAMES = YES
+SHORT_NAMES = NO
+HIDE_SCOPE_NAMES = NO
+VERBATIM_HEADERS = NO
+SHOW_INCLUDE_FILES = YES
+JAVADOC_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = YES
+INHERIT_DOCS = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+DISTRIBUTE_GROUP_DOC = NO
+TAB_SIZE = 8
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+ALIASES =
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+OPTIMIZE_OUTPUT_FOR_C = YES
+OPTIMIZE_OUTPUT_JAVA = NO
+SHOW_USED_FILES = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = f:/prog/max/flext/source/
+FILE_PATTERNS =
+RECURSIVE = NO
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS =
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = YES
+INLINE_SOURCES = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = YES
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+CHM_FILE = ..\flext.chm
+HHC_LOCATION = "c:\programme\prog\html help workshop\hhc.exe"
+GENERATE_CHI = NO
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NO
+TREEVIEW_WIDTH = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = NO
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = NO
+USE_PDFLATEX = NO
+LATEX_BATCHMODE = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = NO
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED = FLEXT_THREADS \
+ MAXMSP \
+ NT \
+ PD \
+ unix
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE =
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+TEMPLATE_RELATIONS = YES
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+GRAPHICAL_HIERARCHY = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+MAX_DOT_GRAPH_WIDTH = 1024
+MAX_DOT_GRAPH_HEIGHT = 1024
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
+CGI_NAME = search.cgi
+CGI_URL =
+DOC_URL =
+DOC_ABSPATH =
+BIN_ABSPATH = /usr/local/bin/
+EXT_DOC_PATHS =
diff --git a/externals/grill/flext/flext.dsp b/externals/grill/flext/flext.dsp
new file mode 100644
index 00000000..ab1c4dd9
--- /dev/null
+++ b/externals/grill/flext/flext.dsp
@@ -0,0 +1,238 @@
+# Microsoft Developer Studio Project File - Name="flext" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=flext - Win32 Threads 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 "flext.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 "flext.mak" CFG="flext - Win32 Threads Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "flext - Win32 Release" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE "flext - Win32 Debug" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE "flext - Win32 Threads Debug" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE "flext - Win32 Threads Release" (basierend auf "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "max/flext"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "flext - 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 "pd-msvc\s"
+# PROP Intermediate_Dir "pd-msvc\s"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /G6 /W3 /O2 /I "c:\programme\audio\pd\src" /I "f:\prog\packs\sndobj\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "NOPTHREAD" /YX /FD /c
+# ADD BASE RSC /l 0xc07 /d "NDEBUG"
+# ADD RSC /l 0xc07 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"pd-msvc/flext-pdwin.lib"
+
+!ELSEIF "$(CFG)" == "flext - 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 "pd-msvc\sd"
+# PROP Intermediate_Dir "pd-msvc\sd"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /ZI /Od /I "c:\programme\audio\pd\src" /I "f:\prog\packs\sndobj\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "NOPTHREAD" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0xc07 /d "_DEBUG"
+# ADD RSC /l 0xc07 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"pd-msvc/flext_d-pdwin.lib"
+
+!ELSEIF "$(CFG)" == "flext - Win32 Threads Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "flext___Win32_Threads_Debug"
+# PROP BASE Intermediate_Dir "flext___Win32_Threads_Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "pd-msvc\td"
+# PROP Intermediate_Dir "pd-msvc\td"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GR /ZI /Od /I "c:\programme\audio\pd\src" /I "." /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "FLEXT_THREADS" /FR /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /ZI /Od /I "c:\programme\audio\pd\src" /I "f:\prog\packs\sndobj\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "FLEXT_THREADS" /FR /YX /FD /GZ /c
+# ADD BASE RSC /l 0xc07 /d "_DEBUG"
+# ADD RSC /l 0xc07 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"msvc-debug\flext-pdwin.lib"
+# ADD LIB32 /nologo /out:"pd-msvc/flext_td-pdwin.lib"
+
+!ELSEIF "$(CFG)" == "flext - Win32 Threads Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "flext___Win32_Threads_Release"
+# PROP BASE Intermediate_Dir "flext___Win32_Threads_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "pd-msvc\t"
+# PROP Intermediate_Dir "pd-msvc\t"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GR /O2 /I "c:\programme\audio\pd\src" /I "." /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "FLEXT_THREADS" /YX /FD /c
+# ADD CPP /nologo /G6 /MT /W3 /O2 /I "c:\programme\audio\pd\src" /I "f:\prog\packs\sndobj\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "PD" /D "NT" /D "FLEXT_THREADS" /YX /FD /c
+# ADD BASE RSC /l 0xc07 /d "NDEBUG"
+# ADD RSC /l 0xc07 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"msvc/flext-pdwin.lib"
+# ADD LIB32 /nologo /out:"pd-msvc/flext_t-pdwin.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "flext - Win32 Release"
+# Name "flext - Win32 Debug"
+# Name "flext - Win32 Threads Debug"
+# Name "flext - Win32 Threads Release"
+# Begin Group "doc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\source\fldoxygen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\readme.txt
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\source\flatom.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flattr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flbase.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flbase.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flbuf.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\fldefs.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\fldsp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\fldsp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flext.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flext.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flinternal.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\fllib.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flmspbuffer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flout.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flsndobj.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flsndobj.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flstdc.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flsupport.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flsupport.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flthr.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flutil.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\source\flxlet.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/flext.mpw b/externals/grill/flext/flext.mpw
new file mode 100644
index 00000000..a287b220
--- /dev/null
+++ b/externals/grill/flext/flext.mpw
@@ -0,0 +1,78 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for Apple MPW-PR
+#
+# usage: make -f flext.mpw
+#
+# ---------------------------------------------
+
+MAKEFILE = flext.mpw
+¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified
+
+Name = flext
+
+ObjDir = :MPW:
+MaxSDK = Daten:Prog Stuff:Max/MSP SDK:SDK Examples
+Includes = -i :,"{MaxSDK}:Max Includes","{MaxSDK}:MSP Includes"
+Defines = -d MAXMSP
+
+Sym-PPC = -sym off
+Flags = -bool on -enum int -includes unix -opt speed,unroll,unswitch
+WarnOff = -w 35 # arg not used
+
+PPCCPlusOptions = {Includes} {Sym-PPC} {Defines} {Flags} {WarnOff}
+
+
+### Source Files ###
+
+Headers = flstdc.h flbase.h fldefs.h flext.h flclass.h fldsp.h flthr.h flmspbuffer.h flinternal.h
+SrcFiles = flbase.cpp flbuf.cpp flext.cpp fllib.cpp fldsp.cpp flatom.cpp flsetup.cpp flthr.cpp flutil.cpp flxlet.cpp
+
+SrcDir = :source:
+
+### Object Files ###
+
+ObjFiles-PPC = ¶
+ "{ObjDir}flbase.cpp.x" ¶
+ "{ObjDir}flbuf.cpp.x" ¶
+ "{ObjDir}flext.cpp.x" ¶
+ "{ObjDir}fllib.cpp.x" ¶
+ "{ObjDir}fldsp.cpp.x" ¶
+ "{ObjDir}flatom.cpp.x" ¶
+ "{ObjDir}flsetup.cpp.x" ¶
+ "{ObjDir}flthr.cpp.x" ¶
+ "{ObjDir}flutil.cpp.x" ¶
+ "{ObjDir}flxlet.cpp.x"
+
+### Libraries ###
+
+LibFiles-PPC =
+
+
+### Default Rules ###
+
+{ObjDir} Ä {SrcDir}
+
+.cpp.x Ä .cpp {¥MondoBuild¥} {Headers}
+ {PPCCPlus} {depDir}{default}.cpp -o {targDir}{default}.cpp.x {PPCCPlusOptions}
+
+
+### Build Rules ###
+
+all Ä Folder {ObjDir}{Name}.o
+
+Folder Ä
+ if !`Exists {ObjDir}` ; NewFolder {ObjDir} ; end
+
+{ObjDir}{Name}.o ÄÄ {ObjFiles-PPC} {LibFiles-PPC}
+ PPCLink ¶
+ -o {Targ} ¶
+ {Deps} ¶
+ {Sym-PPC} ¶
+ -mf -d ¶
+ -t 'XCOF' ¶
+ -c 'MPS ' ¶
+ -xm l
+
+
diff --git a/externals/grill/flext/gpl.txt b/externals/grill/flext/gpl.txt
new file mode 100644
index 00000000..5ea29a7d
--- /dev/null
+++ b/externals/grill/flext/gpl.txt
@@ -0,0 +1,346 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
diff --git a/externals/grill/flext/license.txt b/externals/grill/flext/license.txt
new file mode 100644
index 00000000..1e0de2f2
--- /dev/null
+++ b/externals/grill/flext/license.txt
@@ -0,0 +1,49 @@
+flext - C++ layer for Max/MSP and pd (pure data) externals
+Copyright (C) 2001,2002 Thomas Grill
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+In the official flext distribution, the GNU General Public License is
+in the file gpl.txt
+
+---------------------------------------------------------
+
+ OTHER COPYRIGHT NOTICES
+
+---------------------------------------------------------
+This package uses a lot of code from GEM by Mark Danks
+See the license text below:
+
+--- GEM --------------------------------------
+GEM - Graphics Environment for Multimedia
+Copyright (C) 1997-2000 Mark Danks
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+In the official GEM distribution, the GNU General Public License is
+in the file GnuGPL.LICENSE
+
diff --git a/externals/grill/flext/make-files.txt b/externals/grill/flext/make-files.txt
new file mode 100644
index 00000000..68780d76
--- /dev/null
+++ b/externals/grill/flext/make-files.txt
@@ -0,0 +1,4 @@
+SRCS=flbase.cpp flext.cpp flbuf.cpp fldsp.cpp fllib.cpp flxlet.cpp flattr.cpp flsupport.cpp \
+flutil.cpp flatom.cpp flthr.cpp flout.cpp
+HDRS=flstdc.h flbase.h flclass.h fldefs.h flext.h flsupport.h fldsp.h flinternal.h
+IHDRS=
diff --git a/externals/grill/flext/make-inc.pd-msvc b/externals/grill/flext/make-inc.pd-msvc
new file mode 100644
index 00000000..2bd528d9
--- /dev/null
+++ b/externals/grill/flext/make-inc.pd-msvc
@@ -0,0 +1,99 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# ----- for internal use ----------------------
+#
+
+!include config-pd-msvc.txt
+
+# source files
+SOURCE=source
+
+# includes
+INCPATH=/I$(MSVCPATH)\include /I$(PDPATH)\src /I$(SOURCE)
+
+!ifdef SNDOBJ
+INCPATH=$(INCPATH) /I$(SNDOBJ)
+!endif
+
+# compiler definitions and flags
+DEFS=/DPD /DNT
+
+CFLAGS=/GR /GD /G6
+OFLAGS=/Ox
+DFLAGS=/Od /Zi
+
+TARGET=pdwin # appendix to lib name
+
+
+!ifdef FLEXT_THREADS
+DEFS=$(DEFS) /DFLEXT_THREADS
+
+!ifndef _DEBUG
+CFLAGS=$(CFLAGS) $(OFLAGS) /MT
+OBJPATH=t
+!else
+CFLAGS=$(CFLAGS) $(DFLAGS) /MTd
+OBJPATH=td
+!endif
+
+!else
+
+!ifndef _DEBUG
+CFLAGS=$(CFLAGS) $(OFLAGS) /ML
+OBJPATH=s
+!else
+CFLAGS=$(CFLAGS) $(DFLAGS) /MLd
+OBJPATH=sd
+!endif
+
+!endif
+
+
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+!include make-files.txt
+
+!ifdef SNDOBJ
+SRCS=$(SRCS) flsndobj.cpp
+HDRS=$(HDRS) flsndobj.h
+!endif
+
+#default target
+all: $(OUTPATH)\$(NAME)-$(TARGET).lib
+
+# remove build
+clean:
+ -cd $(OUTPATH)
+ -del /s /q $(OBJPATH) > nul
+ -rmdir $(OBJPATH)
+ -cd ..
+ -del /q $(OUTPATH)\$(NAME)-$(TARGET).lib > nul
+ -rmdir $(OUTPATH)
+
+# -----------------------------------------------
+
+OBJS= $(SRCS:.cpp=.obj)
+
+{$(SOURCE)\}.cpp.obj:
+ @-if not exist $(OUTPATH) mkdir $(OUTPATH)
+ @cd $(OUTPATH)
+ @-if not exist $(OBJPATH) mkdir $(OBJPATH)
+ @cd ..
+ cl /c $(CFLAGS) $(DEFS) $(INCPATH) /Fo$(OUTPATH)\$(OBJPATH)\$@ $<
+
+$(OUTPATH)\$(NAME)-$(TARGET).lib: $(OBJS)
+ @cd $(OUTPATH)\$(OBJPATH)
+ lib /OUT:..\$(NAME)-$(TARGET).lib $**
+ @cd ..\..
+!ifdef INSTALL
+!if "$(INSTALL)" == "yes"
+ @-if not exist $(OBJPATH) mkdir $(INSTDIR)
+ copy $(OUTPATH)\$(NAME)-$(TARGET).lib $(INSTDIR) > nul
+ copy $(SOURCE)\*.h $(INSTDIR) > nul
+!endif
+!endif
+
diff --git a/externals/grill/flext/makefile.pd-bcc b/externals/grill/flext/makefile.pd-bcc
new file mode 100644
index 00000000..f03c6f6b
--- /dev/null
+++ b/externals/grill/flext/makefile.pd-bcc
@@ -0,0 +1,87 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for BorlandC++
+#
+# usage: make -f makefile.bcc
+#
+# ---------------------------------------------
+#
+# note: no threading support for BorlandC++
+#
+# ---------------------------------------------
+
+!include config-pd-bcc.txt
+
+SOURCE=source
+
+NAME=flext
+TARGET=pdwin # appendix to lib name
+
+# includes
+INCPATH=-I$(BCCPATH)\include -I$(PDPATH)\src -I$(SOURCE)
+
+!ifdef SNDOBJ
+INCPATH=$(INCPATH) -I$(SNDOBJ)
+!endif
+
+# compiler definitions and flags
+DEFS=-DPD -DNT -DNOPTHREAD
+CFLAGS=-6 -O2 -OS -ff -tWD
+
+
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+!include make-files.txt
+
+!ifdef SNDOBJ
+SRCS=$(SRCS) flsndobj.cpp
+HDRS=$(HDRS) flsndobj.h
+!endif
+
+#default target
+all: $(OUTPATH)\$(NAME)-$(TARGET).lib
+
+# remove build
+clean:
+ -del /s /q $(OUTPATH) > nul
+ rmdir $(OUTPATH)
+
+# -----------------------------------------------
+
+OBJS= $(SRCS:.cpp=.obj)
+
+#.PATH.obj=$(OUTPATH)
+
+{$(SOURCE)}.cpp.obj:
+ bcc32 -c $(CFLAGS) $(DEFS) $(INCPATH) -n$(OUTPATH) $<
+
+$(OUTPATH):
+ @if not exist $< mkdir $<
+
+$(OUTPATH)\$(NAME)-$(TARGET).lib:: $(OUTPATH)
+
+$(OUTPATH)\$(NAME)-$(TARGET).lib:: $(OBJS)
+ @-del "$<"
+ cd $(OUTPATH)
+ tlib "..\$<" +$(**: = +)
+ cd ..
+!ifdef INSTALL
+!if "$(INSTALL)" == "yes"
+ @-if not exist $(INSTDIR) mkdir $(INSTDIR)
+ copy $< $(INSTDIR) >nul
+ copy $(SOURCE)\*.h $(INSTDIR) >nul
+!endif
+!endif
+
+
+
+
+
+
+
+
+
diff --git a/externals/grill/flext/makefile.pd-cygwin b/externals/grill/flext/makefile.pd-cygwin
new file mode 100644
index 00000000..92d2def2
--- /dev/null
+++ b/externals/grill/flext/makefile.pd-cygwin
@@ -0,0 +1,108 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for gcc @ cygwin
+#
+# usage:
+# to build run "make -f makefile.pd-cygwin"
+#
+# ---------------------------------------------
+#
+# compiling for threaded usage is not supported
+#
+
+CONFIG=config-pd-cygwin.txt
+
+include $(CONFIG)
+
+
+# compiler+linker stuff
+INCLUDES=$(PDPATH)/src $(SNDOBJ)
+FLAGS=-DPD -DNT -DNOPTHREAD
+CFLAGS=-O6 -mcpu=pentiumpro
+CFLAGS_D=-mcpu=pentiumpro -g
+CFLAGS_T=-DFLEXT_THREADS
+LIBS=
+
+INSTDIR=$(PDPATH)/flext
+
+# ----------------------------------------------
+# the rest can stay untouched
+# ----------------------------------------------
+
+NAME=flext
+
+# all the source files from the package
+include make-files.txt
+
+ifdef SNDOBJ
+_SRCS=$(SRCS) flsndobj.cpp
+_HDRS=$(HDRS) flsndobj.h
+else
+_SRCS=$(SRCS)
+_HDRS=$(HDRS)
+endif
+
+MAKEFILE=makefile.pd-cygwin
+TARGET=$(TARGDIR)/$(NAME)-pdwin.lib
+TARGET_D=$(TARGDIR)/$(NAME)_d-pdwin.lib
+TARGET_T=$(TARGDIR)/$(NAME)_t-pdwin.lib
+TARGET_TD=$(TARGDIR)/$(NAME)_td-pdwin.lib
+
+all: $(TARGDIR) $(TARGET) $(TARGET_D) # $(TARGET_T) $(TARGET_TD)
+
+$(TARGDIR):
+ -mkdir $(TARGDIR)
+
+$(SRCS): $(_HDRS) $(IHDRS) $(MAKEFILE) $(CONFIG)
+ touch $@
+
+$(TARGDIR)/%.o : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.do : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.to : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.tdo : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGET) : $(patsubst %.cpp,$(TARGDIR)/%.o,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_D) : $(patsubst %.cpp,$(TARGDIR)/%.do,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_T) : $(patsubst %.cpp,$(TARGDIR)/%.to,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_TD) : $(patsubst %.cpp,$(TARGDIR)/%.tdo,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+.PHONY: clean install
+clean:
+ rm -f $(TARGDIR)/*.o $(TARGET) $(TARGET_D)
+
+$(INSTDIR):
+ -mkdir $(INSTDIR)
+
+install:: $(INSTDIR)
+
+install:: $(TARGET) $(TARGET_D) $(patsubst %,source/%,$(_HDRS)) # $(TARGET_T) $(TARGET_TD)
+ cp $^ $(INSTDIR)
+
+
+
+
+
+
+
+
+
+
diff --git a/externals/grill/flext/makefile.pd-darwin b/externals/grill/flext/makefile.pd-darwin
new file mode 100644
index 00000000..e22176f0
--- /dev/null
+++ b/externals/grill/flext/makefile.pd-darwin
@@ -0,0 +1,103 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for gcc @ darwin
+#
+# usage:
+# to build run "make -f makefile.pd-darwin"
+# to install (as root), do "make -f makefile.pd-darwin install"
+#
+
+CONFIG=config-pd-darwin.txt
+
+include $(CONFIG)
+
+# compiler+linker stuff
+INCLUDES=$(PDPATH) $(SNDOBJ)
+FLAGS=-DPD -Dunix -DMACOSX -maltivec -Wno-unused -Wno-parentheses -Wno-switch -Wstrict-prototypes
+CFLAGS=-O6
+CFLAGS_D=-g -Wshadow
+CFLAGS_T=-DFLEXT_THREADS
+LIBS=
+
+
+# ----------------------------------------------
+# the rest can stay untouched
+# ----------------------------------------------
+
+NAME=flext
+
+# all the source files from the package
+include make-files.txt
+
+ifdef SNDOBJ
+_SRCS=$(SRCS) flsndobj.cpp
+_HDRS=$(HDRS) flsndobj.h
+else
+_SRCS=$(SRCS)
+_HDRS=$(HDRS)
+endif
+
+MAKEFILE=makefile.pd-darwin
+TARGET=$(TARGDIR)/$(NAME).a
+TARGET_D=$(TARGDIR)/$(NAME)_d.a
+TARGET_T=$(TARGDIR)/$(NAME)_t.a
+TARGET_TD=$(TARGDIR)/$(NAME)_td.a
+
+all: $(TARGDIR) $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD)
+
+$(TARGDIR):
+ mkdir $(TARGDIR)
+
+$(patsubst %,source/%,$(_SRCS)): $(patsubst %,source/%,$(HDRS)) $(patsubst %,source/%,$(IHDRS)) $(MAKEFILE) $(CONFIG)
+ touch $@
+
+$(TARGDIR)/%.o : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.do : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.to : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.tdo : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGET) : $(patsubst %.cpp,$(TARGDIR)/%.o,$(_SRCS))
+ libtool -static -o $@ $^
+
+$(TARGET_D) : $(patsubst %.cpp,$(TARGDIR)/%.do,$(_SRCS))
+ libtool -static -o $@ $^
+
+$(TARGET_T) : $(patsubst %.cpp,$(TARGDIR)/%.to,$(_SRCS))
+ libtool -static -o $@ $^
+
+$(TARGET_TD) : $(patsubst %.cpp,$(TARGDIR)/%.tdo,$(_SRCS))
+ libtool -static -o $@ $^
+
+.PHONY: clean install
+
+clean:
+ rm -f $(TARGDIR)/*.{o,do,to,tdo} $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD)
+
+$(INSTDIR):
+ -mkdir $(INSTDIR)
+
+install:: $(INSTDIR)
+
+install:: $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD) $(patsubst %,source/%,$(_HDRS))
+ cp $^ $(INSTDIR)
+ ranlib $(INSTDIR)/*.a # have to rerun ranlib at install dir ?!
+# chmod 755 $(patsubst %,$(INSTDIR)/%,$(notdir $^))
+# chgrp admin $(patsubst %,$(INSTDIR)/%,$(notdir $^))
+
+
+
+
+
+
+
+
+
+
diff --git a/externals/grill/flext/makefile.pd-linux b/externals/grill/flext/makefile.pd-linux
new file mode 100644
index 00000000..501399bd
--- /dev/null
+++ b/externals/grill/flext/makefile.pd-linux
@@ -0,0 +1,96 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for gcc @ linux
+#
+# usage:
+# to build run "make -f makefile.pd-linux"
+# to install (as root), do "make -f makefile.pd-linux install"
+#
+
+CONFIG=config-pd-linux.txt
+
+include $(CONFIG)
+
+# compiler+linker stuff
+INCLUDES=$(PDPATH) $(SNDOBJ)
+FLAGS=-DPD
+CFLAGS=-O6 -mcpu=pentiumpro
+CFLAGS_D=-mcpu=pentiumpro -g
+CFLAGS_T=-DFLEXT_THREADS
+LIBS=
+
+# ----------------------------------------------
+# the rest can stay untouched
+# ----------------------------------------------
+
+NAME=flext
+
+# all the source files from the package
+include make-files.txt
+
+ifdef SNDOBJ
+_SRCS=$(SRCS) flsndobj.cpp
+_HDRS=$(HDRS) flsndobj.h
+else
+_SRCS=$(SRCS)
+_HDRS=$(HDRS)
+endif
+
+MAKEFILE=makefile.pd-linux
+TARGET=$(TARGDIR)/$(NAME).a
+TARGET_D=$(TARGDIR)/$(NAME)_d.a
+TARGET_T=$(TARGDIR)/$(NAME)_t.a
+TARGET_TD=$(TARGDIR)/$(NAME)_td.a
+
+all: $(TARGDIR) $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD)
+
+$(TARGDIR):
+ mkdir $(TARGDIR)
+
+$(patsubst %,source/%,$(_SRCS)): $(patsubst %,source/%,$(_HDRS)) $(patsubst %,source/%,$(IHDRS)) $(MAKEFILE) $(CONFIG)
+ touch $@
+
+$(TARGDIR)/%.o : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.do : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.to : source/%.cpp
+ $(CXX) -c $(CFLAGS) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGDIR)/%.tdo : source/%.cpp
+ $(CXX) -c $(CFLAGS_D) $(CFLAGS_T) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) source) $< -o $@
+
+$(TARGET) : $(patsubst %.cpp,$(TARGDIR)/%.o,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_D) : $(patsubst %.cpp,$(TARGDIR)/%.do,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_T) : $(patsubst %.cpp,$(TARGDIR)/%.to,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+$(TARGET_TD) : $(patsubst %.cpp,$(TARGDIR)/%.tdo,$(_SRCS))
+ ar rc $@ $^
+ chmod 755 $@
+
+.PHONY: clean install
+
+clean:
+ rm -f $(TARGDIR)/*.{o,do,to,tdo} $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD)
+
+$(INSTDIR):
+ -mkdir $(INSTDIR)
+
+install:: $(INSTDIR)
+
+install:: $(TARGET) $(TARGET_D) $(TARGET_T) $(TARGET_TD) $(patsubst %,source/%,$(_HDRS))
+ cp $^ $(INSTDIR)
+ chmod 755 $(patsubst %,$(INSTDIR)/%,$(notdir $^))
+ chown root.users $(patsubst %,$(INSTDIR)/%,$(notdir $^))
+
diff --git a/externals/grill/flext/makefile.pd-msvc b/externals/grill/flext/makefile.pd-msvc
new file mode 100644
index 00000000..d775ab08
--- /dev/null
+++ b/externals/grill/flext/makefile.pd-msvc
@@ -0,0 +1,31 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for MSVC++
+#
+#
+# IMPORTANT: Adjust some of the paths also in makefile-inc.msvc
+#
+# usage: make -f makefile.pd-msvc
+#
+# ---------------------------------------------------------------
+
+!include config-pd-msvc.txt
+
+all: flext flext_t flext_d flext_td
+
+flext:
+ nmake /f make-inc.pd-msvc NAME=$*
+
+flext_d:
+ nmake /f make-inc.pd-msvc NAME=$* _DEBUG=1
+
+flext_t:
+ nmake /f make-inc.pd-msvc NAME=$* FLEXT_THREADS=1
+
+flext_td:
+ nmake /f make-inc.pd-msvc NAME=$* FLEXT_THREADS=1 _DEBUG=1
+
+
+clean:
+ nmake /f make-inc.pd-msvc clean
diff --git a/externals/grill/flext/readme.txt b/externals/grill/flext/readme.txt
new file mode 100644
index 00000000..81972a93
--- /dev/null
+++ b/externals/grill/flext/readme.txt
@@ -0,0 +1,262 @@
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+This package seeks to encourage the development of open source software
+for the pd and Max/MSP platforms.
+
+Donations for further development of the package are highly appreciated.
+
+----------------------------------------------------------------------------
+
+Package files:
+- readme.txt: this one
+- gpl.txt,license.txt: GPL license stuff
+- flext.h: main include file
+- flstdc.h: Basic definitions in classic C - some common vocabulary for the different platforms
+- flbase.h,flbase.cpp: GEM-like C++ interface
+- flclass.h,flext.cpp: actual base classes for message (flext_base) and dsp (flext_dsp) processing
+- fldsp.h,fldsp.cpp: code for signal externals
+- flthr.h,flthr.cpp: code for threaded methods
+- flsupport.h,flsupport.cpp: various flext support functions and classes
+- flatom.cpp: code for functions dealing with lists of atoms
+- flutil.cpp: additional utility functions
+- flxlet.cpp: code for variable inlet/outlet stuff
+- flattr.cpp: code for attribute stuff
+- flinternals.h: internal definitions for flext library
+- flbuf.cpp: buffer object handling for base classes
+- fllib.cpp: code for handling external libraries in MaxMSP
+- fldefs.h: definitions for internal flext use
+- flcwmax.h: trivial prefix header file for Max/MSP CodeWarrior projects
+- flmspbuffer.h: MaxMSP's inofficial buffer.h included here for conveniance
+
+> for PD you need the pd source code (which is most likely part of the distribution)
+> for Max/MSP you will also need the Max/MSP SDK (and for threading the GUSI library)
+
+----------------------------------------------------------------------------
+
+The package should at least compile (and is tested) with the following compilers:
+
+pd - Windows:
+-------------
+o Borland C++ 5.5 (free): edit "config-pd-bcc.txt" & run "build-pd-bcc.bat"
+
+o Microsoft Visual C++ 6: edit "config-pd-msvc.txt" & run "build-pd-msvc.bat"
+
+o Cygwin: edit "config-pd-cygwin.txt" & run "sh build-pd-cygwin.sh"
+
+pd - linux:
+-----------
+o GCC: edit "config-pd-linux.txt" & run "sh build-pd-linux.sh"
+
+Max/MSP - MacOS 9:
+------------------
+o Metrowerks CodeWarrior V6: edit & use the "flext.cw" project file
+
+o Apple MPW-PR: edit & use the "flext.mpw" makefile
+
+----------------------------------------------------------------------------
+
+Goals/features of the package:
+
+pros:
+- better readability of code compared to straight C externals
+- faster development, more robust coding
+- sharing of common methods and data by using base classes
+- any input to any inlet (with the exception of signal streams)
+- transparent use of threads for methods
+- libraries of externals in MaxMSP
+- more than 3 typed creation arguments possible for MaxMSP
+
+cons:
+- introduces a small overhead to speed of message handling
+- overhead in object size (due to possibly unneeded code)
+
+see flext.h, fldefs.h and flclass.h for the documented base definitions and classes
+
+----------------------------------------------------------------------------
+
+Version history:
+
+0.4.0:
+- introduced Max/Jitter-like attribute functionality ("@value" command line, "getvalue" get and "value" set functions)
+- introduced a flext static class for general flext functions (to clean up the flext_base class)
+- creation argument handling is now done by flext
+ no more weird PD re-ordering of arguments
+- calling SetupInOut() has become obsolete - flext creates all inlets/outlets by itself at the right time
+- completely redesigned FLEXT_NEW macros, usage of dynamic classes (in fllib.cpp)
+- added ToQueue* functions - like ToOut* but messages or not directly sent (well suited for deadlock situations)
+- fixed potentially dangerous typo in flext.cpp - (was: FLEXT_THREAD instead of FLEXT_THREADS)
+- added OSX/darwin support (originally done by Adam T. Lindsay)
+- SndObj interface now also available for cygwin and BCC
+- added prepend and append functions to AtomList class
+- added IsNothing, SetNothing, CanbeBool and GetABool functions
+- deprecated the remaining Get*Flint and Set*Flint functions
+
+0.3.3:
+- PD: fixed bug for DSP objects having no signal inlets
+ this also enables floats into a non-signal leftmost inlet
+- revisited priority stuff for detached threads
+- Bind/unbind functions for flext classes (in MaxMSP only one object can be bound)
+- made "t_symtype" another synonym for "t_symbol *"
+- added forgotten dsp_free function for MaxMSP
+- fixed forgotten __class__ member for MaxMSP libraries
+- changed basic MaxMSP object to t_pxbox (ok, a bit more memory is used....)
+- MaxMSP library can now be loaded from startup folder (but can't use aliases)
+- if no handler is found for pure anything (just symbol, no args...) try list handler
+- added interface for SndObj (http://www.may.ie/academic/music/musictec/SndObj/ )
+
+0.3.2:
+- Doxygen generated inline documentation / functional reference
+- added some more functionality to the AtomAnything class
+- bugfix for threaded methods with var list or anything arguments
+- added threaded method for arbitrary (void *) data structs
+- ThrMutex: added lock count functions Push() and Pop()
+- eliminated potentially dangerous SetThing,GetThing and introduced DoBind,DoUnbind,GetBound instead
+- fixed severe bug with the current threads list
+- add path specification possibility for help symbols (in FLEXT_NEW*)
+- use pthread_attr and DETACHED flag
+
+0.3.1:
+- added some more functionality to the AtomList class
+- fixed forgotten Sleep implementation in pd@unix
+- reorganized file structure and config/make procedures
+
+0.3.0:
+- added CYGWIN support
+
+- added threaded methods along with a message queue for ToOut* functions (very unstable for MaxMSP!)
+ to use threads compile flext with FLEXT_THREADS definition
+- check/update function for buffer change (resize etc.)
+- description text for inlets/outlets (e.g. for MaxMSPs assist function) - not fully implemented
+- added buffer resize functions flext_base::buffer::Frames(int,bool)
+- added some utility functions: Sleep, CopyAtom, CopyList
+- added List manipulation classes: AtomList, AtomAnything
+- Alias object names (simply specify with FLEXT_NEW*, separated by whitespace)
+- float messages - int method is called if there is no float method
+- MaxMSP: int messages - float method is called if there is no int method
+- fixed type warning for class constructors with int arguments in PD
+- fixed severe bug concerning symbol methods
+- MaxMSP: use critical sections for message output (for more safety in overdrive mode)
+- PD: default/manual definition of help file by flext_base::DefineHelp
+- added GetThing/SetThing to access t_symbol's s_thing data member
+
+- introduced FLEXT_NEW_DSP* and FLEXT_LIB_DSP* for FLEXT_NEW_TILDE* and FLEXT_LIB_TILDE* (the latter become deprecated)
+- all variable argument defs (aka gimme) now have a V instead of G (e.g. FLEXT_NEW_V)
+
+0.2.3:
+- restructured files and started usable inline documentation
+- found that there was no method to output a bang?! Ugh! -> corrected
+- finally eliminated awful t_flint type and all other schizophrenic flint functions (float and int exist now equally)
+- now (finally) using type t_sample for sample values (should just be identical to float)
+- added AddInBang/AddOutBang (same as Add*Symbol - unchecked)
+- buffer class: added "bool Ok()" check function
+- switched on error posting for unhandled messages
+- added XletCode and AddInlets/AddOutlets for multiple Inlet/Outlet addition (max. 9 inlets/outlets)
+- if float or int message is not handled explicitly then [list float/int( is tried
+
+0.2.2:
+- added xgimme argument type (supplies method handlers with symbol+gimme)
+- more information on DSP system with flext_dsp object (block size,number of audio inputs and outputs)
+- cleaner gcc makefile
+- made NewAligned/FreeAligned static functions
+- introduced FLEXT(_TILDE)_SETUP for class setup in a library setup function
+- introduced external libraries for MaxMSP, changed library setup behavior (now via FLEXT_LIB_SETUP)
+- included MaxMsp's inofficial buffer.h with consent by David Zicarelli
+- changed dynamic casts in callback functions to static as gcc 3.0.4 has obvious bugs
+
+0.2.1:
+- fixed bug in message parsing code (anything messages were not correctly mapped to inlets)
+- changed t_symtype to t_symptr (= t_symbol *), needed for method argument lists
+- eliminated flint type (t_flint remains)
+
+0.2.0:
+- internal proxy objects for any non-leftmost inlets
+- Max/MSP: all signal inlets can receive messages
+- method/argument parsing is done by flext - float/int are not distinguished, the first handler wins
+- integrated more system functions into flext_base & eliminated superfluous #defines
+- distribute list (into inlet 0) elements over inlets (right to left)
+- added outlets for anythings
+- defines for callback-to-method functions and method setup (FLEXT_CALLBACK*, FLEXT_ADD*)
+- uses PD's or Max's memory allocation functions (for safety in Max's overdrive)
+- no support for default arguments (A_DEFFLOAT and A_DEFSYMBOL).. use GIMME instead!
+- better graphics update behavior for PD
+- improved behavior for invalid/undefined buffers/arrays
+- use MaxMSP internal z_disabled flag with flext_dsp for pausing/resuming dsp processing
+- included CHECK_TILDE, a test whether a tilde object (defined as FLEXT_TILDE_*) has a trailing ~. (debug mode only)
+- changed notation of flext functions from to_out_float like to ToOutFloat like
+- eliminated trivial shortcuts (F,I,V,...) for built-in types
+- MaxMSP is only capable of 3 creation arguments... that should be sufficient - otherwise use GIMME
+- Methods for aligned memory (NewAligned, FreeAligned)
+
+0.1.1:
+- documentation for flext.h
+- more emancipation from GEM code
+- virtually everything renamed
+- abstraction for dsp processing
+- makefile for BCC
+- manual call of extern_setup or main unnecessary for single objects - only in pd libraries
+- delayed buffer init (only name is set beforehand)
+- loadbang also in PD
+- introduced "compatibility mode" which denies platform-specific features
+- fixed severe dsp bug (symptom: "float method overwritten" warning in pd)
+- fixed bug: wrong return code from buffer::Set
+
+0.1.0:
+- max-pd 0.2 becomes flext 0.1.0
+- heavy usage of unchanged GEM code
+
+
+----------------------------------------------------------------------------
+
+Notes:
+- no support for default object arguments (A_DEFFLOAT, A_DEFSYMBOL) -> use variable argument lists instead
+
+Platform specific:
+- PD does not allow signal and message to go into the same inlet
+
+Restrictions in compatibility mode:
+- Max allows only 9 float/int inlets
+
+Porting to new compilers/platforms:
+- enums must be int-sized
+- compiler must support bool type
+- no need of C++ exceptions or RTTI (RTTI only for GUI objects)
+
+----------------------------------------------------------------------------
+
+TODO list:
+
+general:
+- documentation
+- add log messages for debugging version
+- where to put flext source/lib in linux: /usr/local/lib,/usr/local/include ?
+- clean up headers (eliminate flstdc.h?)
+- check that SetupInOut is only called once
+- feed assist function with in/outlet description
+- MaxMSP: how to call separate help files for objects in a library?
+
+bugs:
+- PD: problems with timed buffer redrawing (takes a lot of cpu time)
+- hard thread termination upon object destruction doesn't seem to work properly -> crash
+- Max rounding bug (at least version 4.0.5) ... buffer resize could be one sample less!
+- flext_dsp: Max/MSP doesn't correctly report in/out channel counts
+
+tests:
+- PD: figure out what "pointer" messages do and where they occur
+- some more mutexes needed for thread safety?
+- buffer resize: flext_base::buffer::Frames(): should we use buffer or system sample rate?
+- what about FLEXT_ADDMETHOD_V (for var arg lists) and FLEXT_ADDMETHOD_A (anythings)... nonsense?
+- queued messages... triggering timer should not be necessary for MaxMSP qmsg
+
+features:
+- abstraction for clock functions
+- manage running threads individually (stop, isrunning?, priority etc.)
+
+premature thoughts:
+- GUI objects
+
+
+
diff --git a/externals/grill/flext/source/flatom.cpp b/externals/grill/flext/source/flatom.cpp
new file mode 100644
index 00000000..705fc9e6
--- /dev/null
+++ b/externals/grill/flext/source/flatom.cpp
@@ -0,0 +1,139 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flatom.cpp
+ \brief Definitions for handling the t_atom type and lists thereof.
+*/
+
+#include "flext.h"
+
+//namespace flext {
+
+flext::AtomList::AtomList(int argc,const t_atom *argv):
+ lst(NULL),cnt(0)
+{
+ operator()(argc,argv);
+}
+
+flext::AtomList::AtomList(const AtomList &a):
+ lst(NULL),cnt(0)
+{
+ operator =(a);
+}
+
+flext::AtomList::~AtomList() { Clear(); }
+
+flext::AtomList &flext::AtomList::operator()(int argc,const t_atom *argv)
+{
+ if(lst && cnt != argc) { delete[] lst; lst = NULL; cnt = 0; }
+
+ if(argc) {
+ cnt = argc;
+ lst = new t_atom[cnt];
+
+ if(argv) {
+ for(int i = 0; i < argc; ++i) SetAtom(lst[i],argv[i]);
+/*
+ {
+ switch(lst[i].a_type = argv[i].a_type) {
+ case A_FLOAT:
+ lst[i].a_w.w_float = argv[i].a_w.w_float;
+ break;
+#ifdef MAXMSP
+ case A_LONG:
+ lst[i].a_w.w_int = argv[i].a_w.w_int;
+ break;
+#endif
+ case A_SYMBOL:
+ lst[i].a_w.w_symbol = argv[i].a_w.w_symbol;
+ break;
+#ifdef PD
+ case A_POINTER:
+ lst[i].a_w.w_gpointer = argv[i].a_w.w_gpointer;
+ break;
+#endif
+ default:
+ post("AtomList - atom type (%i) not supported",lst[i].a_type);
+ lst[i].a_type = A_NULL;
+ break;
+ }
+ }
+*/
+ }
+ }
+ return *this;
+}
+
+
+flext::AtomList &flext::AtomList::Append(const t_atom &a)
+{
+ t_atom *nlst = new t_atom[cnt+1];
+ for(int i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]);
+ SetAtom(nlst[cnt],a);
+
+ if(lst) delete[] lst;
+ lst = nlst;
+ ++cnt;
+
+ return *this;
+}
+
+flext::AtomList &flext::AtomList::Append(int argc,const t_atom *argv)
+{
+ t_atom *nlst = new t_atom[cnt+argc];
+ int i;
+ for(i = 0; i < cnt; ++i) SetAtom(nlst[i],lst[i]);
+ for(i = 0; i < argc; ++i) SetAtom(nlst[cnt+i],argv[i]);
+
+ if(lst) delete[] lst;
+ lst = nlst;
+ cnt += argc;
+
+ return *this;
+}
+
+flext::AtomList &flext::AtomList::Prepend(const t_atom &a)
+{
+ t_atom *nlst = new t_atom[cnt+1];
+ for(int i = 0; i < cnt; ++i) SetAtom(nlst[i+1],lst[i]);
+ SetAtom(nlst[0],a);
+
+ if(lst) delete[] lst;
+ lst = nlst;
+ ++cnt;
+
+ return *this;
+}
+
+flext::AtomList &flext::AtomList::Prepend(int argc,const t_atom *argv)
+{
+ t_atom *nlst = new t_atom[cnt+argc];
+ int i;
+ for(i = 0; i < argc; ++i) SetAtom(nlst[i],argv[i]);
+ for(i = 0; i < cnt; ++i) SetAtom(nlst[argc+i],lst[i]);
+
+ if(lst) delete[] lst;
+ lst = nlst;
+ cnt += argc;
+
+ return *this;
+}
+
+flext::AtomList flext::AtomList::GetPart(int offs,int len) const
+{
+ if(offs+len > Count()) {
+ len = Count()-offs;
+ if(len < 0) len = 0;
+ }
+
+ return AtomList(len,Atoms()+offs);
+}
+
+//} // namespace flext
diff --git a/externals/grill/flext/source/flattr.cpp b/externals/grill/flext/source/flattr.cpp
new file mode 100644
index 00000000..20b06e41
--- /dev/null
+++ b/externals/grill/flext/source/flattr.cpp
@@ -0,0 +1,190 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flattr.cpp
+ \brief Attribute handling for the flext base class
+*/
+
+#include "flext.h"
+#include <string.h>
+#include <stdio.h>
+
+flext_base::attritem::attritem(const t_symbol *t,const t_symbol *gt,metharg tp,methfun gf,methfun sf):
+ tag(t),gtag(gt),argtp(tp),gfun(gf),sfun(sf),nxt(NULL)
+{}
+
+flext_base::attritem::~attritem()
+{
+ if(nxt) delete nxt;
+}
+
+void flext_base::AddAttrItem(attritem *m)
+{
+ if(attrhead) {
+ attritem *mi;
+ for(mi = attrhead; mi->nxt; mi = mi->nxt) {}
+ mi->nxt = m;
+ }
+ else
+ attrhead = m;
+ attrcnt++;
+}
+
+void flext_base::AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun)
+{
+ if(procattr) {
+ char tmp[1024];
+ sprintf(tmp,"get%s",attr);
+ AddAttrItem(new attritem(MakeSymbol(attr),MakeSymbol(tmp),tp,gfun,sfun));
+
+ AddMethod(0,attr,(methfun)cb_SetAttrib,a_any,a_null);
+ AddMethod(0,tmp,(methfun)cb_GetAttrib,a_any,a_null);
+ }
+ else
+ error("%s - attribute procession is not enabled!",thisName());
+}
+
+int flext_base::CheckAttrib(int argc,const t_atom *argv)
+{
+ int offs = 0;
+ for(; offs < argc; ++offs)
+ if(IsString(argv[offs]) && *GetString(argv[offs]) == '@') break;
+ return offs;
+}
+
+bool flext_base::InitAttrib(int argc,const t_atom *argv)
+{
+ int cur,nxt;
+ for(cur = 0; cur < argc; cur = nxt) {
+ // find next @symbol
+ for(nxt = cur+1; nxt < argc; ++nxt)
+ if(IsString(argv[nxt]) && *GetString(argv[nxt]) == '@') break;
+
+ const t_symbol *tag = MakeSymbol(GetString(argv[cur])+1);
+ SetAttrib(tag,nxt-cur-1,argv+cur+1);
+ }
+ return true;
+}
+
+bool flext_base::ListAttrib()
+{
+ if(outattr) {
+ AtomList la(attrcnt);
+ attritem *a = attrhead;
+ for(int i = 0; i < attrcnt; ++i,a = a->nxt) SetSymbol(la[i],a->tag);
+
+ ToOutAnything(outattr,thisTag(),la.Count(),la.Atoms());
+ return true;
+ }
+ else
+ return false;
+}
+
+bool flext_base::SetAttrib(const t_symbol *tag,int argc,const t_atom *argv)
+{
+ attritem *a = attrhead;
+ for(; a && a->tag != tag; a = a->nxt) {}
+
+ if(a) {
+ if(a->sfun) {
+ bool ok = true;
+
+ AtomList la;
+ t_any any;
+ switch(a->argtp) {
+ case a_float:
+ if(argc == 1 && CanbeFloat(argv[0])) {
+ any.ft = GetAFloat(argv[0]);
+ ((methfun_1)a->sfun)(this,any);
+ }
+ else ok = false;
+ break;
+ case a_int:
+ if(argc == 1 && CanbeInt(argv[0])) {
+ any.it = GetAInt(argv[0]);
+ ((methfun_1)a->sfun)(this,any);
+ }
+ else ok = false;
+ break;
+ case a_symbol:
+ if(argc == 1 && IsSymbol(argv[0])) {
+ any.st = GetSymbol(argv[0]);
+ ((methfun_1)a->sfun)(this,any);
+ }
+ else ok = false;
+ break;
+ case a_LIST:
+ any.vt = &(la(argc,argv));
+ ((methfun_1)a->sfun)(this,any);
+ break;
+ default:
+ ERRINTERNAL();
+ }
+
+ if(!ok)
+ post("%s - wrong arguments for attribute %s",thisName(),GetString(tag));
+ }
+ else
+ post("%s - attribute %s has no get method",thisName(),GetString(tag));
+ }
+ else
+ error("%s - %s: attribute not found",thisName(),tag);
+ return true;
+}
+
+bool flext_base::GetAttrib(const t_symbol *tag,int argc,const t_atom *argv)
+{
+ if(argc)
+ post("%s - %s: arguments ignored",thisName(),GetString(tag));
+
+ attritem *a = attrhead;
+ for(; a && a->gtag != tag; a = a->nxt) {}
+
+ if(a) {
+ if(a->gfun) {
+ AtomList la;
+ t_any any;
+ switch(a->argtp) {
+ case a_float: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetFloat(la[0],any.ft);
+ break;
+ }
+ case a_int: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetInt(la[0],any.it);
+ break;
+ }
+ case a_symbol: {
+ ((methfun_1)a->gfun)(this,any);
+ la(1);
+ SetSymbol(la[0],any.st);
+ break;
+ }
+ case a_LIST: {
+ any.vt = &la;
+ ((methfun_1)a->gfun)(this,any);
+ break;
+ }
+ default:
+ ERRINTERNAL();
+ }
+ ToOutAnything(outattr,a->tag,la.Count(),la.Atoms());
+ }
+ else
+ post("%s - attribute %s has no set method",thisName(),GetString(tag));
+ }
+ else
+ error("%s - %s: attribute not found",thisName(),tag);
+ return true;
+}
+
diff --git a/externals/grill/flext/source/flbase.cpp b/externals/grill/flext/source/flbase.cpp
new file mode 100644
index 00000000..97fed291
--- /dev/null
+++ b/externals/grill/flext/source/flbase.cpp
@@ -0,0 +1,118 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flbase.cpp
+ \brief Implementation of the internal flext base classes.
+
+ \remark This is all derived from GEM by Mark Danks
+*/
+
+#include "flbase.h"
+#include "flinternal.h"
+#include <string.h>
+
+/////////////////////////////////////////////////////////
+//
+// flext_obj
+//
+/////////////////////////////////////////////////////////
+
+flext_hdr *flext_obj::m_holder = NULL;
+const t_symbol *flext_obj::m_holdname = NULL;
+bool flext_obj::m_holdattr = false;
+bool flext_obj::process_attributes = false;
+
+/////////////////////////////////////////////////////////
+// Constructor
+//
+/////////////////////////////////////////////////////////
+flext_obj :: flext_obj()
+ : x_obj(m_holder)
+ , m_name(m_holdname)
+ , procattr(m_holdattr)
+ , init_ok(true)
+{
+#ifdef PD
+ m_canvas = canvas_getcurrent();
+#elif defined(MAXMSP)
+ m_canvas = (t_patcher *)gensym("#P")->s_thing;
+ x_obj->curinlet = 0;
+#endif
+}
+
+/////////////////////////////////////////////////////////
+// Destructor
+//
+/////////////////////////////////////////////////////////
+flext_obj :: ~flext_obj() {}
+
+
+void flext_obj::DefineHelp(t_class *c,const char *ref,const char *dir,bool addtilde)
+{
+#ifdef PD
+ char tmp[256];
+ if(dir) {
+ strcpy(tmp,dir);
+ strcat(tmp,"/");
+ strcat(tmp,ref);
+ if(addtilde) strcat(tmp,"~");
+ }
+ else
+ strcpy(tmp,ref);
+ ::class_sethelpsymbol(c,gensym(const_cast<char *>(tmp)));
+#else
+ // no solution for MaxMSP yet
+#endif
+}
+
+
+/////////////////////////////////////////////////////////
+// overloaded new/delete memory allocation methods
+//
+/////////////////////////////////////////////////////////
+
+void *flext_obj::operator new(size_t bytes)
+{
+ bytes += sizeof(size_t);
+ char *blk = (char *)getbytes(bytes);
+ *(size_t *)blk = bytes;
+ return blk+sizeof(size_t);
+}
+
+void flext_obj::operator delete(void *blk)
+{
+ char *ori = (char *)blk-sizeof(size_t);
+ size_t bytes = *(size_t *)ori;
+ freebytes(ori,bytes);
+}
+
+void *flext_obj::NewAligned(size_t bytes,int bitalign)
+{
+ const size_t ovh = sizeof(size_t)+sizeof(char *);
+ const unsigned long alignovh = bitalign/8-1;
+ bytes += ovh+alignovh;
+ char *blk = (char *)getbytes(bytes);
+ char *ablk = reinterpret_cast<char *>((reinterpret_cast<unsigned long>(blk)+ovh+alignovh) & ~alignovh);
+ *(char **)(ablk-sizeof(size_t)-sizeof(char *)) = blk;
+ *(size_t *)(ablk-sizeof(size_t)) = bytes;
+ return ablk;
+}
+
+void flext_obj::FreeAligned(void *blk)
+{
+ char *ori = *(char **)((char *)blk-sizeof(size_t)-sizeof(char *));
+ size_t bytes = *(size_t *)((char *)blk-sizeof(size_t));
+ freebytes(ori,bytes);
+}
+
+
+
+
+
diff --git a/externals/grill/flext/source/flbase.h b/externals/grill/flext/source/flbase.h
new file mode 100644
index 00000000..f3f8b647
--- /dev/null
+++ b/externals/grill/flext/source/flbase.h
@@ -0,0 +1,426 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flbase.h
+ \brief Internal flext base classes
+
+ \remark This is all derived from GEM by Mark Danks
+*/
+
+#ifndef __FLEXT_BASE_H
+#define __FLEXT_BASE_H
+
+#include "flstdc.h"
+#include "flsupport.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#endif
+
+class flext_obj;
+
+// ----------------------------------------------------------------------------
+/*! \struct flext_hdr
+ \brief The obligatory PD or Max/MSP object header
+ \internal
+
+ This is in a separate struct to assure that obj is the very first thing.
+ If it were the first thing in flext_obj, then there could be problems with
+ the virtual table of the C++ class.
+*/
+// ----------------------------------------------------------------------------
+
+struct FLEXT_EXT flext_hdr
+{
+ /*! \brief The obligatory object header
+ MUST reside at memory offset 0 (no virtual table possible)
+ */
+ t_sigobj obj;
+
+#ifdef PD
+ //! PD only: float signal holder for pd
+ float defsig;
+#endif
+
+#if defined(MAXMSP)
+ //! MaxMSP only: current inlet used by proxy objects
+ long curinlet;
+#endif
+
+ /*! \brief This points to flext object class
+ This points to the actual polymorphic C++ class
+ */
+ flext_obj *data;
+};
+
+
+// ----------------------------------------------------------------------------
+/*! \class flext_obj
+ \brief The mother of base classes for all flext externs
+ \internal
+
+ Each extern which is written in C++ needs to use the #defines at the
+ end of this header file.
+
+ The define
+
+ FLEXT_HEADER(NEW_CLASS, PARENT_CLASS)
+
+ should be somewhere in your header file.
+ One of the defines like
+
+ FLEXT_NEW(NEW_CLASS)
+ FLEXT_NEW_2(NEW_CLASS, float, float)
+
+ should be the first thing in your implementation file.
+ NEW_CLASS is the name of your class and PARENT_CLASS is the
+ parent of your class.
+*/
+// ----------------------------------------------------------------------------
+
+class FLEXT_EXT flext_obj:
+ public flext
+{
+ public:
+
+ // --- overloading of new/delete memory allocation methods ----
+ // MaxMSP allows only 16K in overdrive mode!
+
+ void *operator new(size_t bytes);
+ void operator delete(void *blk);
+
+ #ifndef __MRC__ // doesn't allow new[] overloading?!
+ void *operator new[](size_t bytes) { return operator new(bytes); }
+ void operator delete[](void *blk) { operator delete(blk); }
+ #endif
+
+ // these are aligned
+ static void *NewAligned(size_t bytes,int bitalign = 128);
+ static void FreeAligned(void *blk);
+
+ // ---------------------
+
+ //! Constructor
+ flext_obj();
+
+ //! Destructor
+ virtual ~flext_obj() = 0;
+
+ //! Get the object's canvas
+ t_canvas *thisCanvas() { return(m_canvas); }
+
+ t_sigobj *thisHdr() { return &x_obj->obj; }
+ const t_sigobj *thisHdr() const { return &x_obj->obj; }
+ const char *thisName() const { return GetString(m_name); }
+ const t_symbol *thisNameSym() const { return m_name; }
+
+#ifdef PD
+ t_class *thisClass() { return (t_class *)((t_object *)(x_obj))->te_g.g_pd; }
+#elif defined(MAXMSP)
+ t_class *thisClass() { return (t_class *)(((t_tinyobject *)x_obj)->t_messlist-1); }
+#endif
+
+ void InitProblem() { init_ok = false; }
+
+ static void ProcessAttributes(bool attr) { process_attributes = attr; }
+
+ // this also guarantees that there are no instances of flext_obj
+ virtual bool Init() = 0;
+ virtual void Exit() {}
+
+// --- help -------------------------------------------------------
+
+ /*! \defgroup FLEXT_C_HELP Flext help/assistance functionality
+
+ @{
+ */
+
+ static void DefineHelp(t_class *c,const char *ref,const char *dir = NULL,bool addtilde = false);
+ void DefineHelp(const char *ref,const char *dir = NULL,bool addtilde = false) { DefineHelp(thisClass(),ref,dir,addtilde); }
+
+ //! @}
+
+
+ protected:
+
+ //! The object header
+ flext_hdr *x_obj;
+
+ //! Flag for attribute procession
+ bool procattr;
+
+ static bool process_attributes;
+
+ private:
+
+ //! The canvas (patcher) that the object is in
+ t_canvas *m_canvas;
+
+ //! Flag for successful object construction
+ bool init_ok;
+
+ public:
+
+ //! Creation callback
+ static void __setup__(t_class *) { flext::Setup(); }
+
+ /*! \brief This is a temporary holder
+ \warning don't touch it!
+ */
+ static flext_hdr *m_holder;
+ //! Hold object's name during construction
+ static const t_symbol *m_holdname;
+
+ static bool m_holdattr;
+
+ //! The object's name in the patcher
+ const t_symbol *m_name;
+
+ //! Check whether construction was successful
+ bool InitOk() const { return init_ok; }
+
+ //@{
+ //! Definitions for library objects
+
+ static void lib_init(const char *name,void setupfun(),bool attr);
+ static void obj_add(bool lib,bool dsp,bool attr,const char *idname,const char *names,void setupfun(t_class *),flext_obj *(*newfun)(int,t_atom *),void (*freefun)(flext_hdr *),int argtp1,...);
+ static flext_hdr *obj_new(const t_symbol *s,int argc,t_atom *argv);
+ static void obj_free(flext_hdr *o);
+ //@}
+};
+
+
+// max. 4 creation args (see the following macros)
+#define FLEXT_MAXNEWARGS 4
+
+// max. 5 method args (see the following macros)
+#define FLEXT_MAXMETHARGS 5
+
+// prefixes for the macro generated handler functions
+#define FLEXT_CALL_PRE(F) flext_c_##F
+#define FLEXT_THR_PRE(F) flext_t_##F
+#define FLEXT_GET_PRE(F) flext_g_##F
+#define FLEXT_SET_PRE(F) flext_s_##F
+
+
+#ifndef FLEXT_ATTRIBUTES
+#define FLEXT_ATTRIBUTES 0
+#endif
+
+// ----------------------------------------
+// These should be used in the header
+// ----------------------------------------
+
+
+#define FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) \
+public: \
+typedef NEW_CLASS thisType; \
+static flext_obj *__init__(int argc,t_atom *argv); \
+static void __free__(flext_hdr *hdr) \
+{ flext_obj *mydata = hdr->data; delete mydata; \
+ hdr->flext_hdr::~flext_hdr(); } \
+static void __setup__(t_class *classPtr) { \
+ PARENT_CLASS::__setup__(classPtr); } \
+protected: \
+static inline NEW_CLASS *thisObject(void *c) { return FLEXT_CAST<NEW_CLASS *>(((flext_hdr *)c)->data); }
+
+
+#define FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
+public: \
+typedef NEW_CLASS thisType; \
+static flext_obj *__init__(int argc,t_atom *argv); \
+static void __free__(flext_hdr *hdr) \
+{ flext_obj *mydata = hdr->data; delete mydata; \
+ hdr->flext_hdr::~flext_hdr(); } \
+static void __setup__(t_class *classPtr) \
+{ PARENT_CLASS::__setup__(classPtr); \
+ NEW_CLASS::SETUPFUN(classPtr); } \
+protected: \
+static inline NEW_CLASS *thisObject(void *c) { return FLEXT_CAST<NEW_CLASS *>(((flext_hdr *)c)->data); }
+
+
+// generate name of dsp/non-dsp setup function
+#define FLEXT_STPF_0(NAME) NAME##_setup
+#define FLEXT_STPF_1(NAME) NAME##_tilde_setup
+#define FLEXT_STPF_(DSP) FLEXT_STPF_##DSP
+#define FLEXT_STPF(NAME,DSP) FLEXT_STPF_(DSP)(NAME)
+
+
+
+// --------------------------------------------------------------------------------------
+
+
+
+// these can be used in library setup functions
+// to register the individual objects in the library
+
+#define FLEXT_SETUP(cl) \
+extern void cl##_setup(); \
+cl##_setup()
+
+#define FLEXT_DSP_SETUP(cl) \
+extern void cl##_tilde_setup(); \
+cl##_tilde_setup()
+
+// deprecated
+#define FLEXT_TILDE_SETUP FLEXT_DSP_SETUP
+
+
+// specify that to define the library itself
+
+#ifdef PD
+#define FLEXT_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT void NAME##_setup() { flext_obj::lib_init(#NAME,SETUPFUN,FLEXT_ATTRIBUTES); }
+#else // MAXMSP
+#define FLEXT_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT int main() { flext_obj::lib_init(#NAME,SETUPFUN,FLEXT_ATTRIBUTES); return 0; }
+#endif
+
+
+// --------------------------------------------------
+
+
+#define FLEXT_EXP_0 extern "C" FLEXT_EXT
+#define FLEXT_EXP_1
+#define FLEXT_EXP(LIB) FLEXT_EXP_##LIB
+
+#ifdef PD
+#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP)
+#else // MAXMSP
+#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP) extern "C" FLEXT_EXT int main() { FLEXT_STPF(NEW_CLASS,DSP)(); return 0; }
+#endif
+#define FLEXT_OBJ_SETUP_1(NEW_CLASS,DSP)
+
+#define FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) FLEXT_OBJ_SETUP_##LIB(NEW_CLASS,DSP)
+
+
+
+// ----------------------------------------
+// These definitions are used below
+// ----------------------------------------
+
+// Shortcuts for PD/Max type arguments
+#define FLEXTTYPE_void A_NULL
+#define CALLBTYPE_void void
+#define FLEXTTYPE_float A_FLOAT
+#define CALLBTYPE_float float
+#define FLEXTTYPE_t_float A_FLOAT
+#define CALLBTYPE_t_float t_float
+
+//* #define FLEXTTYPE_t_flint A_FLINT
+
+#ifdef PD
+#define FLEXTTYPE_int A_FLOAT
+#define CALLBTYPE_int float
+#else
+#define FLEXTTYPE_int A_INT
+#define CALLBTYPE_int int
+#endif
+
+#define FLEXTTYPE_t_symptr A_SYMBOL
+#define CALLBTYPE_t_symptr t_symptr
+#define FLEXTTYPE_t_symtype A_SYMBOL
+#define CALLBTYPE_t_symtype t_symptr
+#define FLEXTTYPE_t_ptrtype A_POINTER
+#define CALLBTYPE_t_ptrtype t_ptrtype
+
+#define FLEXTTP(TP) FLEXTTYPE_ ## TP
+#define CALLBTP(TP) CALLBTYPE_ ## TP
+
+
+#define ARGMEMBER_int(a) GetInt(a)
+#define ARGMEMBER_float(a) GetFloat(a)
+#define ARGMEMBER_t_symptr(a) GetSymbol(a)
+#define ARGMEMBER_t_symtype(a) GetSymbol(a)
+#define ARGCAST(arg,tp) ARGMEMBER_##tp(arg)
+
+
+#define REAL_NEW(NAME,NEW_CLASS,DSP,LIB) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS; \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,A_NULL); \
+}
+
+#define REAL_NEW_V(NAME,NEW_CLASS,DSP,LIB) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(argc,argv); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,A_GIMME,A_NULL); \
+}
+
+#define REAL_NEW_1(NAME,NEW_CLASS,DSP,LIB, TYPE1) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),A_NULL); \
+}
+
+#define REAL_NEW_2(NAME,NEW_CLASS,DSP,LIB, TYPE1,TYPE2) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),A_NULL); \
+}
+
+#define REAL_NEW_3(NAME,NEW_CLASS,DSP,LIB, TYPE1, TYPE2, TYPE3) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),A_NULL); \
+}
+
+#define REAL_NEW_4(NAME,NEW_CLASS,DSP,LIB, TYPE1,TYPE2, TYPE3, TYPE4) \
+FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) \
+flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
+{ \
+ return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3),ARGCAST(argv[3],TYPE4)); \
+} \
+FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
+{ \
+ flext_obj::obj_add(LIB,DSP,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),FLEXTTP(TYPE4),A_NULL); \
+}
+
+
+// Shortcuts for method arguments:
+#define FLEXTARG_float a_float
+#define FLEXTARG_int a_int
+#define FLEXTARG_bool a_int
+#define FLEXTARG_t_float a_float
+#define FLEXTARG_t_symtype a_symbol
+#define FLEXTARG_t_symptr a_symbol
+#define FLEXTARG_t_ptrtype a_pointer
+
+#define FLEXTARG(TP) FLEXTARG_ ## TP
+
+
+#endif
+
+
+
+
diff --git a/externals/grill/flext/source/flbuf.cpp b/externals/grill/flext/source/flbuf.cpp
new file mode 100644
index 00000000..dc5704c0
--- /dev/null
+++ b/externals/grill/flext/source/flbuf.cpp
@@ -0,0 +1,255 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flbuf.cpp
+ \brief Implementation of the buffer abstraction class.
+*/
+
+#include "flext.h"
+
+#ifdef MAXMSP
+#include "flmspbuffer.h" // include inofficial buffer.h
+#endif
+
+#ifdef PD
+#define DIRTY_INTERVAL 0 // buffer dirty check in msec
+#endif
+
+
+
+flext::buffer::buffer(const t_symbol *bn,bool delayed):
+ sym(NULL),data(NULL),
+ chns(0),frames(0)
+{
+#ifdef PD
+ arr = NULL;
+ interval = DIRTY_INTERVAL;
+ isdirty = false;
+ ticking = false;
+ tick = clock_new(this,(t_method)cb_tick);
+#endif
+
+ if(bn) Set(bn,delayed);
+}
+
+flext::buffer::~buffer()
+{
+#ifdef PD
+ clock_free(tick);
+#endif
+}
+
+int flext::buffer::Set(const t_symbol *s,bool nameonly)
+{
+ int ret = 0;
+ bool valid = data != NULL; // valid now? (before change)
+
+ if(s && sym != s) {
+ ret = -1;
+ data = NULL;
+ frames = 0;
+ chns = 0;
+ }
+
+ if(s && *s->s_name) sym = s;
+
+ if(!sym) {
+ if(valid) ret = -1;
+ }
+ else if(!nameonly) {
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+
+ arr = (t_garray *)pd_findbyclass(const_cast<t_symbol *>(sym), garray_class);
+ if(!arr)
+ {
+ if (*sym->s_name) error("buffer: no such array '%s'",sym->s_name);
+ sym = NULL;
+ if(valid) ret = -1;
+ }
+ else if(!garray_getfloatarray(arr, &frames1, &data1))
+ {
+ error("buffer: bad template '%s'", sym->s_name);
+ data = NULL;
+ frames = 0;
+ if(valid) ret = -1;
+ }
+ else {
+ garray_usedindsp(arr);
+ if(frames != frames1) { frames = frames1; if(!ret) ret = 1; }
+ if(data != data1) { data = data1; if(!ret) ret = 1; }
+ chns = 1;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ if(valid) ret = -1;
+ }
+ else {
+#ifdef DEBUG
+ post("%s: buffer object '%s' - valid:%i samples:%i channels:%i frames:%i",thisName(),bufname->s_name,p->b_valid,p->b_frames,p->b_nchans,p->b_frames);
+#endif
+ if(data != p->b_samples) { data = p->b_samples; if(!ret) ret = 1; }
+ if(chns != p->b_nchans) { chns = p->b_nchans; if(!ret) ret = 1; }
+ if(frames != p->b_frames) { frames = p->b_frames; if(!ret) ret = 1; }
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined", sym->s_name);
+ if(valid) ret = -1;
+ }
+#endif
+ }
+
+ return ret;
+}
+
+bool flext::buffer::Update()
+{
+ if(!Ok()) return false;
+
+#ifdef PD
+ int frames1;
+ t_sample *data1;
+ if(!garray_getfloatarray(arr, &frames1, &data1)) {
+ frames = 0;
+ data = NULL;
+ chns = 0;
+ return true;
+ }
+ else if(data != data1 || frames != frames1) {
+ frames = frames1;
+ data = data1;
+ return true;
+ }
+ else
+ return false;
+#else // MAXMSP
+ if(!sym->s_thing)
+ return false;
+ else {
+ const _buffer *p = (const _buffer *)sym->s_thing;
+ if(data != p->b_samples || chns != p->b_nchans || frames != p->b_frames) {
+ data = p->b_samples;
+ chns = p->b_nchans;
+ frames = p->b_frames;
+ return true;
+ }
+ else
+ return false;
+ }
+#endif
+}
+
+void flext::buffer::Frames(int fr,bool keep)
+{
+#ifdef PD
+ ::garray_resize(arr,(float)fr);
+ Update();
+#else
+ t_sample *tmp = NULL;
+ int sz = frames;
+ if(fr < sz) sz = fr;
+
+ if(keep) {
+ // copy buffer data to tmp storage
+ tmp = new t_sample[sz];
+ if(tmp)
+ BlockMoveData(data,tmp,sizeof(t_sample)*sz);
+ else
+ error("flext::buffer - not enough memory for keeping buffer~ contents");
+ }
+
+ t_atom msg;
+ _buffer *buf = (_buffer *)sym->s_thing;
+ // b_msr reflects buffer sample rate... is this what we want?
+ // Max bug: adding small value 0.001 to get right sample count
+ float ms = fr/buf->b_msr+0.001;
+
+ SetFloat(msg,ms);
+ ::typedmess((object *)buf,gensym("size"),1,&msg);
+
+ Update();
+
+ if(tmp) {
+ // copy data back
+ BlockMoveData(tmp,data,sizeof(t_sample)*sz);
+ delete[] tmp;
+ }
+#endif
+}
+
+
+#ifdef PD
+void flext::buffer::SetRefrIntv(float intv)
+{
+ interval = intv;
+ if(interval == 0 && ticking) {
+ clock_unset(tick);
+ ticking = false;
+ }
+}
+#else
+void flext::buffer::SetRefrIntv(float) {}
+#endif
+
+
+void flext::buffer::Dirty(bool force)
+{
+ if(sym) {
+#ifdef PD
+ if((!ticking) && (interval || force)) {
+ ticking = true;
+ cb_tick(this); // immediately redraw
+ }
+ else {
+ if(force) clock_delay(tick,0);
+ isdirty = true;
+ }
+#elif defined(MAXMSP)
+ if(sym->s_thing) {
+ _buffer *p = (_buffer *)sym->s_thing;
+
+ if(NOGOOD(p)) {
+ post("buffer: buffer object '%s' no good",sym->s_name);
+ }
+ else {
+ p->b_modtime = gettime();
+ }
+ }
+ else {
+ error("buffer: symbol '%s' not defined",sym->s_name);
+ }
+#endif
+ }
+}
+
+#ifdef PD
+void flext::buffer::cb_tick(buffer *b)
+{
+ if(b->arr) garray_redraw(b->arr);
+#ifdef _DEBUG
+ else error("buffer: array is NULL");
+#endif
+
+ if(b->isdirty && b->interval) {
+ b->isdirty = false;
+ b->ticking = true;
+ clock_delay(b->tick,b->interval);
+ }
+ else
+ b->ticking = false;
+}
+#endif
+
diff --git a/externals/grill/flext/source/flclass.h b/externals/grill/flext/source/flclass.h
new file mode 100644
index 00000000..5c67dde9
--- /dev/null
+++ b/externals/grill/flext/source/flclass.h
@@ -0,0 +1,599 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flclass.h
+ \brief User accessible flext base classes
+
+*/
+
+#ifndef __FLCLASS_H
+#define __FLCLASS_H
+
+// include the header file declaring the base classes
+#include "flbase.h"
+#include "flsupport.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#include <sched.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#ifdef __BORLANDC__
+#pragma warn -8008 // Condition is always false
+#pragma warn -8057 // Parameter is never used
+#pragma warn -8066 // Unreachable code
+#endif
+
+
+// === flext_base ==================================================
+
+//class qmsg;
+//class thr_entry;
+
+/*! \brief Flext message only base object
+*/
+
+
+class flext_base:
+ public flext_obj
+{
+ FLEXT_HEADER_S(flext_base,flext_obj,Setup)
+
+ friend class flext_obj;
+
+public:
+
+ /*! \defgroup FLEXT_C_BASE Flext basic class functionality
+
+ @{
+ */
+
+// --- compatibility mode ----------------------------------------
+
+ /*! \brief Cross-platform compatibility flag.
+ If set flext allows only operations valid for all platforms.
+ Set to true by default!
+ */
+ static bool compatibility;
+
+// --- inheritable virtual methods --------------------------------
+
+ /*! \defgroup FLEXT_C_VIRTUAL Flext virtual base class functions
+
+ @{
+ */
+
+ //! called on "help" message: should post some text
+ virtual void m_help();
+
+ //! called on patcher load (not on mere object creation!)
+ virtual void m_loadbang() {}
+
+ //! quickhelp for inlets/outlets (gets calles in MaxMSP only)
+ virtual void m_assist(long /*msg*/,long /*arg*/,char * /*s*/) {}
+
+ /*! \brief Called for every incoming message.
+ All method handling is done in there
+ \return True if a handler was found and called
+ */
+ virtual bool m_methodmain(int inlet,const t_symbol *s,int argc,t_atom *argv);
+
+ //! called for every unhandled message (by m_methodmain)
+ virtual bool m_method_(int inlet,const t_symbol *s,int argc,t_atom *argv);
+
+//! @}
+
+
+// --- inlet/outlet stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_C_INOUT Flext in-/outlet functions
+ \note These must be called in the class' constructor
+ \note All (also default) inlets must be defined
+
+ @{
+ */
+
+ // argument m specifies multiple inlet/outlet count
+
+// void AddInDef() { AddInlet(xlet::tp_def,1); }
+
+ /*! \brief Add inlet(s) for anythings
+ That's the one to choose for the left-most (first) inlet unless it's a signal inlet.
+ */
+ void AddInAnything(int m = 1) { AddInlet(xlet::tp_any,m); } // leftmost or via proxy
+ void AddInAnything(const char *desc,int m = 1) { AddInlet(xlet::tp_any,m,desc); } // leftmost or via proxy
+ //! Add inlet(s) for floats
+ void AddInFloat(int m = 1) { AddInlet(xlet::tp_float,m); }
+ void AddInFloat(const char *desc,int m = 1) { AddInlet(xlet::tp_float,m,desc); }
+ //! Add inlet(s) for ints
+ void AddInInt(int m = 1) { AddInlet(xlet::tp_int,m); }
+ void AddInInt(const char *desc,int m = 1) { AddInlet(xlet::tp_int,m,desc); }
+ //! Add inlet(s) for symbols
+ void AddInSymbol(int m = 1) { AddInlet(xlet::tp_sym,m); }
+ void AddInSymbol(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
+ //! Add inlet(s) for bang
+ void AddInBang(int m = 1) { AddInlet(xlet::tp_sym,m); }
+ void AddInBang(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
+ //! Add inlet(s) for lists
+ void AddInList(int m = 1) { AddInlet(xlet::tp_list,m); } // via proxy
+ void AddInList(const char *desc,int m = 1) { AddInlet(xlet::tp_list,m,desc); } // via proxy
+
+ //! Add outlet(s) for anythings
+ void AddOutAnything(int m = 1) { AddOutlet(xlet::tp_any,m); }
+ void AddOutAnything(const char *desc,int m = 1) { AddOutlet(xlet::tp_any,m,desc); }
+ //! Add outlet(s) for floats
+ void AddOutFloat(int m = 1) { AddOutlet(xlet::tp_float,m); }
+ void AddOutFloat(const char *desc,int m = 1) { AddOutlet(xlet::tp_float,m,desc); }
+ //! Add outlet(s) for ints
+ void AddOutInt(int m = 1) { AddOutlet(xlet::tp_int,m); }
+ void AddOutInt(const char *desc,int m = 1) { AddOutlet(xlet::tp_int,m,desc); }
+ //! Add outlet(s) for symbols
+ void AddOutSymbol(int m = 1) { AddOutlet(xlet::tp_sym,m); }
+ void AddOutSymbol(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
+ //! Add outlet(s) for bangs
+ void AddOutBang(int m = 1) { AddOutlet(xlet::tp_sym,m); }
+ void AddOutBang(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
+ //! Add outlet(s) for lists
+ void AddOutList(int m = 1) { AddOutlet(xlet::tp_list,m); }
+ void AddOutList(const char *desc,int m = 1) { AddOutlet(xlet::tp_list,m,desc); }
+
+ /*! \brief Set up inlets and outlets
+ \note this is deprecated... inlets and outlets are now set up automatically
+ */
+ bool SetupInOut() { return true; }
+
+ //! Get number of inlets
+ int CntIn() const { return incnt; }
+ //! Get number of outlets
+ int CntOut() const { return outcnt; }
+ //! Get number of signal inlets
+ int CntInSig() const { return insigs; }
+ //! Get number of signal outlets
+ int CntOutSig() const { return outsigs; }
+
+
+ class outlet;
+// class AtomList;
+// class AtomAnything;
+
+ //! Retrieve currently processed message tag (NULL if no message processing)
+ const t_symbol *thisTag() const { return curtag; }
+
+ //! Get pointer to outlet (_after_ calling setup_inout()!)
+ outlet *GetOut(int ix) { return (outlets && ix < outcnt)?outlets[ix]:NULL; }
+
+ // output messages
+
+ void ToOutBang(outlet *o);
+ //! Output bang (index n starts with 0)
+ void ToOutBang(int n) { outlet *o = GetOut(n); if(o) ToOutBang(o); }
+
+ void ToOutFloat(outlet *o,float f);
+ //! Output float (index n starts with 0)
+ void ToOutFloat(int n,float f) { outlet *o = GetOut(n); if(o) ToOutFloat(o,f); }
+
+ void ToOutInt(outlet *o,int f);
+ //! Output int (index n starts with 0)
+ void ToOutInt(int n,int f) { outlet *o = GetOut(n); if(o) ToOutInt(o,f); }
+
+ void ToOutSymbol(outlet *o,const t_symbol *s);
+ //! Output symbol (index n starts with 0)
+ void ToOutSymbol(int n,const t_symbol *s) { outlet *o = GetOut(n); if(o) ToOutSymbol(o,s); }
+
+ void ToOutString(outlet *o,const char *s) { ToOutSymbol(o,MakeSymbol(s)); }
+ //! Output string (index n starts with 0)
+ void ToOutString(int n,const char *s) { outlet *o = GetOut(n); if(o) ToOutString(o,s); }
+
+ void ToOutList(outlet *o,int argc,const t_atom *argv);
+ //! Output list (index n starts with 0)
+ void ToOutList(int n,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToOutList(o,argc,argv); }
+ //! Output list (index n starts with 0)
+ void ToOutList(int n,const AtomList &list) { ToOutList(n,list.Count(),list.Atoms()); }
+
+ void ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv);
+ //! Output anything (index n starts with 0)
+ void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToOutAnything(o,const_cast<t_symbol *>(s),argc,argv); }
+ //! Output anything (index n starts with 0)
+ void ToOutAnything(int n,const AtomAnything &any) { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); }
+
+ void ToQueueBang(outlet *o);
+ void ToQueueBang(int n) { outlet *o = GetOut(n); if(o) ToQueueBang(o); }
+ void ToQueueFloat(outlet *o,float f);
+ void ToQueueFloat(int n,float f) { outlet *o = GetOut(n); if(o) ToQueueFloat(o,f); }
+ void ToQueueInt(outlet *o,int f);
+ void ToQueueInt(int n,int f) { outlet *o = GetOut(n); if(o) ToQueueInt(o,f); }
+ void ToQueueSymbol(outlet *o,const t_symbol *s);
+ void ToQueueSymbol(int n,const t_symbol *s) { outlet *o = GetOut(n); if(o) ToQueueSymbol(o,s); }
+ void ToQueueString(int n,const char *s) { ToQueueSymbol(n,MakeSymbol(s)); }
+ void ToQueueList(outlet *o,int argc,const t_atom *argv);
+ void ToQueueList(int n,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToQueueList(o,argc,argv); }
+ void ToQueueList(int n,const AtomList &list) { ToQueueList(n,list.Count(),list.Atoms()); }
+ void ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv);
+ void ToQueueAnything(int n,const t_symbol *s,int argc,const t_atom *argv) { outlet *o = GetOut(n); if(o) ToQueueAnything(o,s,argc,argv); }
+ void ToQueueAnything(int n,const AtomAnything &any) { ToQueueAnything(n,any.Header(),any.Count(),any.Atoms()); }
+
+//! @}
+
+
+// --- message handling -------------------------------------------
+
+ enum metharg {
+ a_null = 0,
+ a_float,a_int,
+ a_symbol,a_pointer,
+ a_list,a_any,
+ a_LIST,a_ANY
+ };
+
+ typedef bool (*methfun)(flext_base *c);
+
+ /*! \defgroup FLEXT_C_ADDMETHOD Flext method handling
+ \internal
+
+ @{
+ */
+
+ void AddMethodDef(int inlet,const char *tag = NULL); // call virtual function for tag && inlet
+ void AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...);
+
+ void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_list,a_null); }
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,tag,(methfun)m,a_null); } // pure method
+ void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_any,a_null); } // anything
+ void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol
+ void AddMethod(int inlet,bool (*m)(flext_base *,float &)) { AddMethod(inlet,"float",(methfun)m,a_float,a_null); } // single float
+ void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_null); } // list of 2 floats
+ void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats
+#ifdef PD
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"float",(methfun)m,a_int,a_null); } // single float
+#else
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"int",(methfun)m,a_int,a_null); } // single float
+#endif
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_null); } // list of 2 floats
+ void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_any,a_null); } // method+gimme
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(inlet,tag,(methfun)m,a_float,a_null); } // method+float
+ void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(inlet,tag,(methfun)m,a_int,a_null); } // method+int
+
+ //! Set MaxMSP style of distributing list elements over (message) inlets
+ void SetDist(bool d = true) { distmsgs = d; }
+
+//! @}
+
+// --- bind/unbind ---------------------------------------
+
+#ifdef PD
+ //! Bind object to a symbol
+ bool Bind(const t_symbol *s) { pd_bind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
+ //! Unbind object from a symbol
+ bool Unbind(const t_symbol *s) { pd_unbind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
+#else
+ //! Bind object to a symbol
+ bool Bind(const t_symbol *s) { if(s->s_thing) return false; else { const_cast<t_symbol *>(s)->s_thing = (t_object *)thisHdr(); return true; } }
+ //! Unbind object from a symbol
+ bool Unbind(const t_symbol *s) { if(s->s_thing != (t_object *)thisHdr()) return false; else { const_cast<t_symbol *>(s)->s_thing = NULL; return true; } }
+#endif
+ //! Bind object to a symbol (as string)
+ bool Bind(const char *c) { return Bind(MakeSymbol(c)); }
+ //! Unbind object from a symbol (as string)
+ bool Unbind(const char *c) { return Unbind(MakeSymbol(c)); }
+
+/*
+ // Low level
+
+ //! Bind object to a symbol
+ static void DoUnbind(t_symbol *s,flext_obj *o);
+ //! Unbind object from a symbol
+ static void DoBind(const t_symbol *s,flext_obj *o);
+ //! Get bound object of a symbol
+ static t_class **GetBound(const t_symbol *s) { return (t_class **)s->s_thing; }
+*/
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ /*! \defgroup FLEXT_C_THREAD Flext thread handling
+
+ @{
+ */
+
+ /*! \brief Check if current thread should terminate
+ \todo Check for currently running thread
+ */
+ bool ShouldExit() const { return shouldexit; }
+
+ //! Check if current thread is the realtime system's thread
+ bool IsSystemThread() const { pthread_t cur = pthread_self(); return pthread_equal(cur,thrid) != 0; }
+
+ /*! \brief Yield to other threads
+ \remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
+ */
+ static void ThrYield() { sched_yield(); }
+
+ typedef pthread_t thrid_t;
+
+ /*! \brief Increase/Decrease priority of a thread
+ */
+ static bool ChangePriority(int dp,thrid_t thr = GetThreadId());
+
+ /*! \brief Get priority of a thread
+ */
+ static int GetPriority(thrid_t thr = GetThreadId());
+
+ /*! \brief Set priority of a thread
+ */
+ static bool SetPriority(int p,thrid_t thr = GetThreadId());
+
+ /*! \brief Get current thread id
+ */
+ static thrid_t GetThreadId();
+
+
+#endif // FLEXT_THREADS
+
+//! @}
+
+// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+protected:
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ class thr_params
+ {
+ public:
+ thr_params(flext_base *c,int n = 1);
+ ~thr_params();
+
+ void set_any(const t_symbol *s,int argc,const t_atom *argv);
+ void set_list(int argc,const t_atom *argv);
+
+ flext_base *cl;
+ union _data {
+ bool _bool;
+ float _float;
+ int _int;
+ t_symptr _t_symptr;
+ struct { AtomAnything *args; } _any;
+ struct { AtomList *args; } _list;
+ struct { void *data; } _ext;
+ } *var;
+ };
+
+ class thr_entry
+ {
+ public:
+ thr_entry(pthread_t id = pthread_self()): thrid(id),nxt(NULL) {}
+
+ bool Is(pthread_t id = pthread_self()) const { return pthread_equal(thrid,id) != 0; }
+
+ pthread_t thrid;
+ thr_entry *nxt;
+ };
+
+ static bool StartThread(void *(*)(thr_params *p),thr_params *p,char *methname);
+ bool PushThread();
+ void PopThread();
+#endif
+
+protected:
+
+ flext_base();
+ virtual ~flext_base();
+
+// inlets and outlets
+
+ /*! \brief Set up inlets and outlets
+ \return True on successful creation of all inlets and outlets
+ */
+ virtual bool Init();
+
+ struct xlet {
+ enum type {
+ tp_none = 0,
+ tp_float,tp_int,tp_sym,tp_list,tp_any,
+ tp_LIST,tp_ANY, // use AtomList and AtomAnything
+ tp_sig
+ };
+
+ xlet(type t,const char *desc = NULL);
+ ~xlet();
+
+ char *desc;
+ type tp;
+ xlet *nxt;
+ };
+
+ /*! \addtogroup FLEXT_C_ATTR
+
+ @{
+ */
+
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(attr,a_float,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(attr,a_int,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,t_symbol *&),bool (*set)(flext_base *,t_symbol *&)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
+ void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(attr,a_LIST,(methfun)get,(methfun)set); }
+
+//! @}
+
+ /*! \addtogroup FLEXT_C_INOUT
+
+ @{
+ */
+
+ unsigned long XletCode(xlet::type tp = xlet::tp_none,...); // end list with 0 (= tp_none) !!
+
+ void AddInlets(unsigned long code); // use XletCode to get code value
+ void AddInlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,inlist); }
+ void AddOutlets(unsigned long code); // use XletCode to get code value
+ void AddOutlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,outlist); }
+
+ void DescInlet(int ix,const char *desc) { DescXlet(ix,desc,inlist); }
+ void DescOutlet(int ix,const char *desc) { DescXlet(ix,desc,outlist); }
+
+//! @}
+
+// method handling
+
+ class methitem {
+ public:
+ methitem(int inlet,const t_symbol *t);
+ ~methitem();
+
+ void SetArgs(methfun fun,int argc,metharg *args);
+
+ const t_symbol *tag;
+ int inlet;
+ int argc;
+ metharg *args;
+ methfun fun;
+
+ methitem *nxt;
+ };
+
+// const methitem *FindMethItem(int inlet,const t_symbol *tag,const methitem *st);
+
+ class attritem {
+ public:
+ attritem(const t_symbol *tag,const t_symbol *gtag,metharg tp,methfun gfun,methfun sfun);
+ ~attritem();
+
+ const t_symbol *tag,*gtag;
+ metharg argtp;
+ methfun gfun,sfun;
+
+ attritem *nxt;
+ };
+
+private:
+
+ static void Setup(t_class *c);
+
+ xlet *inlist,*outlist;
+ const t_symbol *curtag;
+ int incnt,outcnt,insigs,outsigs;
+ outlet **outlets,*outattr;
+ bool distmsgs;
+
+ void AddXlet(xlet::type tp,int mult,const char *desc,xlet *&root);
+ void DescXlet(int ix,const char *desc,xlet *&root);
+
+ union t_any {
+ float ft;
+ int it;
+ t_symbol *st;
+ #ifdef PD
+ t_gpointer *pt;
+ #endif
+ void *vt;
+ };
+
+ typedef bool (*methfun_V)(flext_base *c,int argc,t_atom *argv);
+ typedef bool (*methfun_A)(flext_base *c,const t_symbol *s,int argc,t_atom *argv);
+ typedef bool (*methfun_0)(flext_base *c);
+ typedef bool (*methfun_1)(flext_base *c,t_any &);
+ typedef bool (*methfun_2)(flext_base *c,t_any &,t_any &);
+ typedef bool (*methfun_3)(flext_base *c,t_any &,t_any &,t_any &);
+ typedef bool (*methfun_4)(flext_base *c,t_any &,t_any &,t_any &,t_any &);
+ typedef bool (*methfun_5)(flext_base *c,t_any &,t_any &,t_any &,t_any &,t_any &);
+
+ methitem *methhead;
+ void AddMethItem(methitem *m);
+
+ attritem *attrhead;
+ int attrcnt;
+ void AddAttrItem(attritem *m);
+
+ void AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun);
+
+ static int CheckAttrib(int argc,const t_atom *argv);
+ bool InitAttrib(int argc,const t_atom *argv);
+
+ bool ListAttrib();
+ bool GetAttrib(const t_symbol *s,int argc,const t_atom *argv);
+ bool SetAttrib(const t_symbol *s,int argc,const t_atom *argv);
+
+ static bool cb_ListAttrib(flext_base *c) { return c->ListAttrib(); }
+ static bool cb_GetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->GetAttrib(s,argc,argv); }
+ static bool cb_SetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->SetAttrib(s,argc,argv); }
+
+#ifdef FLEXT_THREADS
+ bool shouldexit;
+ int thrcount;
+
+ pthread_t thrid; // the thread that created the object (the system thread)
+ ThrMutex qmutex;
+
+ thr_entry *thrhead,*thrtail;
+ ThrMutex tlmutex;
+#endif
+
+ class qmsg;
+ qmsg *qhead,*qtail;
+ t_qelem *qclk;
+#ifdef MAXMSP
+ t_clock *yclk;
+ static void YTick(flext_base *th);
+#endif
+
+ static void QTick(flext_base *th);
+ void Queue(qmsg *m);
+
+#ifdef PD
+ // proxy object (for additional inlets) stuff
+ struct px_object;
+ friend struct px_object;
+#elif defined(MAXMSP)
+ typedef object px_object;
+ static void cb_px_float(t_class *c,float f);
+ static void cb_px_int(t_class *c,int v);
+ static void cb_px_bang(t_class *c);
+
+ static void cb_px_in1(t_class *c,int v);
+ static void cb_px_in2(t_class *c,int v);
+ static void cb_px_in3(t_class *c,int v);
+ static void cb_px_in4(t_class *c,int v);
+ static void cb_px_in5(t_class *c,int v);
+ static void cb_px_in6(t_class *c,int v);
+ static void cb_px_in7(t_class *c,int v);
+ static void cb_px_in8(t_class *c,int v);
+ static void cb_px_in9(t_class *c,int v);
+#endif
+ static void cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv);
+
+ static void cb_px_ft1(t_class *c,float f);
+ static void cb_px_ft2(t_class *c,float f);
+ static void cb_px_ft3(t_class *c,float f);
+ static void cb_px_ft4(t_class *c,float f);
+ static void cb_px_ft5(t_class *c,float f);
+ static void cb_px_ft6(t_class *c,float f);
+ static void cb_px_ft7(t_class *c,float f);
+ static void cb_px_ft8(t_class *c,float f);
+ static void cb_px_ft9(t_class *c,float f);
+
+ px_object **inlets;
+
+ // callback functions
+
+ static void cb_help(t_class *c);
+
+ static void cb_loadbang(t_class *c);
+#ifdef MAXMSP
+ static void cb_assist(t_class *c,void *b,long msg,long arg,char *s);
+#endif
+};
+
+#endif
diff --git a/externals/grill/flext/source/flcwmax-thr.h b/externals/grill/flext/source/flcwmax-thr.h
new file mode 100755
index 00000000..1a9ecffb
--- /dev/null
+++ b/externals/grill/flext/source/flcwmax-thr.h
@@ -0,0 +1,20 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+// This is the prefix file for CodeWarrior projects - threaded version
+
+#ifndef _FLEXT_CW_MAX_THR_H
+#define _FLEXT_CW_MAX_THR_H
+
+#define FLEXT_THREADS
+
+#include "flcwmax.h"
+
+#endif
diff --git a/externals/grill/flext/source/flcwmax.h b/externals/grill/flext/source/flcwmax.h
new file mode 100644
index 00000000..5ef0b298
--- /dev/null
+++ b/externals/grill/flext/source/flcwmax.h
@@ -0,0 +1,26 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/* This is the prefix file for CodeWarrior projects */
+
+#ifndef _FLEXT_CW_MAX_H
+#define _FLEXT_CW_MAX_H
+
+#include <MacHeaders.h>
+
+#define MAXMSP
+
+#if !defined(__OPTIMIZE__) || __OPTIMIZE__ == 0
+#define _DEBUG
+#endif
+
+/* #define _LOG */
+
+#endif
diff --git a/externals/grill/flext/source/fldefs.h b/externals/grill/flext/source/fldefs.h
new file mode 100644
index 00000000..f92232f9
--- /dev/null
+++ b/externals/grill/flext/source/fldefs.h
@@ -0,0 +1,912 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file fldefs.h
+ \brief This file contains all #defines for actual usage
+
+*/
+
+#ifndef __FLEXT_DEFS_H
+#define __FLEXT_DEFS_H
+
+#ifdef FLEXT_GUI
+#define FLEXT_CAST dynamic_cast
+#else
+#define FLEXT_CAST static_cast
+#endif
+
+/*! \defgroup FLEXT_HEADER Flext class header
+ One (and only one!) of these definitions is compulsory for the class declaration.
+ It has to be placed somewhere in the class definition (not necessarily in a public section).
+
+ @{
+*/
+
+/*! \brief Plain flext class header
+ \param NEW_CLASS name of the current C++ class
+ \param PARENT_CLASS name of the base C++ class (e.g. flext_base or flext_dsp)
+*/
+#define FLEXT_HEADER(NEW_CLASS,PARENT_CLASS) \
+\
+FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS)
+
+/*! \brief Flext class header with setup function
+ \param NEW_CLASS name of the current C++ class
+ \param PARENT_CLASS name of the base C++ class (e.g. flext_base or flext_dsp)
+ \param SETUPFUN setup function, of type "void (*setupfn)(t_class *)"
+
+ The setup function is called after class creation. It corresponds to the
+ original "object_setup" function, apart from the
+ fact that all necessary class initializations have already been taken care by flext.
+ The setup function can e.g. be used for a message to the console upon first creation of an object.
+ The object's t_class* data can be accessed by the static function thisClass()
+*/
+#define FLEXT_HEADER_S(NEW_CLASS, PARENT_CLASS, SETUPFUN)\
+\
+FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS, SETUPFUN)
+
+
+//! @}
+
+
+
+// ====================================================================================
+
+/*! \defgroup FLEXT_NEW Flext class instantiation
+ Makes an actual instance of a class.
+*/
+
+/*! \defgroup FLEXT_NEW_DSP Flext dsp class instantiation
+ Makes an actual instance of a dsp (aka "tilde") class (with signal processing).
+*/
+
+/*! \defgroup FLEXT_LIB Flext library class instantiation
+ Makes an actual instance of a class which is part of an object library (and not stand-alone).
+*/
+
+/*! \defgroup FLEXT_LIB_DSP Flext dsp library class instantiation
+ Makes an actual instance of a dsp (aka "tilde") class with signal processing
+ which is part of an object library (and not stand-alone).
+*/
+
+// NO ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with no arguments
+ \ingroup FLEXT_NEW
+ \param NAME the object's actual name(s) as a string (like "*", "trigger", "noise~", etc.)
+ \param NEW_CLASS the object's C++ class name
+*/
+#define FLEXT_NEW(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,0,0)
+
+/*! Implementation of a flext dsp class with no arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,1,0)
+
+/*! Implementation of a flext class (part of a library) with no arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,0,1)
+
+/*! Implementation of a flext dsp class (part of a library) with no arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP(NAME,NEW_CLASS) \
+\
+REAL_NEW(NAME,NEW_CLASS,1,1)
+
+
+// VARIABLE ARGUMENT LIST
+// ----------------------------------------
+
+/*! Implementation of a flext class with a variable argument list
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS,0,0) \
+
+/*! Implementation of a flext tilde class with a variable argument list
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS,1,0) \
+
+/*! Implementation of a flext class (part of a library) with a variable argument list
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS, 0,1)
+
+/*! Implementation of a flext tilde class (part of a library) with a variable argument list
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_V(NAME,NEW_CLASS) \
+\
+REAL_NEW_V(NAME,NEW_CLASS, 1,1)
+
+
+// OBJECT NAME + VARIABLE ARGUMENT LIST
+// ----------------------------------------
+
+/*! Implementation of a flext class with its name and a variable argument list
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS,0,0) \
+
+/*! Implementation of a flext tilde class with its name and a variable argument list
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS,1,0) \
+
+/*! Implementation of a flext class (part of a library) with its name and a variable argument list
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS, 0,1)
+
+/*! Implementation of a flext tilde class (part of a library) with its name and a variable argument list
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_NV(NAME,NEW_CLASS) \
+\
+REAL_NEW_NV(NAME,NEW_CLASS, 1,1)
+
+
+// ONE ARGUMENT
+// ----------------------------------------
+
+/*! Implementation of a flext class with one argument
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 0, 0,TYPE) \
+
+/*! Implementation of a flext tilde class with one argument
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 1, 0,TYPE) \
+
+/*! Implementation of a flext class (part of a library) with one argument
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 0,1,TYPE)
+
+/*! Implementation of a flext tilde class (part of a library) with one argument
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_1(NAME,NEW_CLASS, TYPE) \
+\
+REAL_NEW_1(NAME,NEW_CLASS, 1,1, TYPE)
+
+
+// TWO ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with 2 arguments
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 0,0, TYPE1, TYPE2) \
+
+/*! Implementation of a flext tilde class with 2 arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 1,0, TYPE1, TYPE2) \
+
+/*! Implementation of a flext class (part of a library) with 2 arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 0,1, TYPE1, TYPE2)
+
+/*! Implementation of a flext tilde class (part of a library) with 2 arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
+\
+REAL_NEW_2(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2)
+
+
+// THREE ARGUMENTS
+// ----------------------------------------
+
+/*! Implementation of a flext class with 3 arguments
+ \ingroup FLEXT_NEW
+*/
+#define FLEXT_NEW_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 0,0, TYPE1, TYPE2, TYPE3) \
+
+/*! Implementation of a flext tilde class with 3 arguments
+ \ingroup FLEXT_NEW_DSP
+*/
+#define FLEXT_NEW_DSP_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 1,0, TYPE1, TYPE2, TYPE3) \
+
+/*! Implementation of a flext class (part of a library) with 3 arguments
+ \ingroup FLEXT_LIB
+*/
+#define FLEXT_LIB_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 0,1,TYPE1, TYPE2, TYPE3)
+
+/*! Implementation of a flext tilde class (part of a library) with 3 arguments
+ \ingroup FLEXT_LIB_DSP
+*/
+#define FLEXT_LIB_DSP_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
+\
+REAL_NEW_3(NAME,NEW_CLASS, 1,1, TYPE1, TYPE2, TYPE3)
+
+
+// deprecated stuff
+
+#define FLEXT_NEW_G FLEXT_NEW_V
+
+#define FLEXT_NEW_TILDE FLEXT_NEW_DSP
+#define FLEXT_NEW_TILDE_G FLEXT_NEW_DSP_V
+#define FLEXT_NEW_TILDE_1 FLEXT_NEW_DSP_1
+#define FLEXT_NEW_TILDE_2 FLEXT_NEW_DSP_2
+#define FLEXT_NEW_TILDE_3 FLEXT_NEW_DSP_3
+
+#define FLEXT_LIB_G FLEXT_LIB_V
+
+#define FLEXT_LIB_TILDE FLEXT_LIB_DSP
+#define FLEXT_LIB_TILDE_G FLEXT_LIB_DSP_V
+#define FLEXT_LIB_TILDE_1 FLEXT_LIB_DSP_1
+#define FLEXT_LIB_TILDE_2 FLEXT_LIB_DSP_2
+#define FLEXT_LIB_TILDE_3 FLEXT_LIB_DSP_3
+
+
+
+
+// ====================================================================================
+
+
+/*! \defgroup FLEXT_CALLBACK Flext callbacks
+
+ @{
+*/
+
+//! Set up a method callback with no arguments
+#define FLEXT_CALLBACK(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(); return true; }
+
+//! Set up a method callback for an anything argument
+#define FLEXT_CALLBACK_A(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,const t_symbol *s,int argc,t_atom *argv) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(s,argc,argv); return true; }
+
+//! Set up a method callback for a variable argument list
+#define FLEXT_CALLBACK_V(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(argc,argv); return true; }
+
+//! Set up a method callback for a data package (void *) argument
+#define FLEXT_CALLBACK_X(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(data); return true; }
+
+//! Set up a method callback for a boolean argument
+#define FLEXT_CALLBACK_B(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1 != 0); return true; }
+
+//! Set up a method callback for 1 argument
+#define FLEXT_CALLBACK_1(M_FUN,TP1) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1); return true; }
+
+//! Set up a method callback for 2 arguments
+#define FLEXT_CALLBACK_2(M_FUN,TP1,TP2) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2); return true; }
+
+//! Set up a method callback for 3 arguments
+#define FLEXT_CALLBACK_3(M_FUN,TP1,TP2,TP3) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3); return true; }
+
+//! Set up a method callback for 4 arguments
+#define FLEXT_CALLBACK_4(M_FUN,TP1,TP2,TP3,TP4) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3,arg4); return true; }
+
+//! Set up a method callback for 5 arguments
+#define FLEXT_CALLBACK_5(M_FUN,TP1,TP2,TP3,TP4,TP5) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4,TP5 &arg5) \
+{ FLEXT_CAST<thisType *>(c)->M_FUN(arg1,arg2,arg3,arg4,arg5); return true; }
+
+
+// Shortcuts
+
+//! Set up a method callback for 1 float argument
+#define FLEXT_CALLBACK_F(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,float)
+
+//! Set up a method callback for 2 float arguments
+#define FLEXT_CALLBACK_FF(M_FUN) \
+\
+FLEXT_CALLBACK_2(M_FUN,float,float)
+
+//! Set up a method callback for 3 float arguments
+#define FLEXT_CALLBACK_FFF(M_FUN) \
+\
+FLEXT_CALLBACK_3(M_FUN,float,float,float)
+
+//! Set up a method callback for 1 integer argument
+#define FLEXT_CALLBACK_I(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,int)
+
+//! Set up a method callback for 2 integer arguments
+#define FLEXT_CALLBACK_II(M_FUN) \
+\
+FLEXT_CALLBACK_2(M_FUN,int,int)
+
+//! Set up a method callback for 3 integer arguments
+#define FLEXT_CALLBACK_III(M_FUN) \
+\
+FLEXT_CALLBACK_3(M_FUN,int,int,int)
+
+//! Set up a method callback for 1 symbol argument
+#define FLEXT_CALLBACK_S(M_FUN) \
+\
+FLEXT_CALLBACK_1(M_FUN,t_symptr)
+
+
+// deprecated
+#define FLEXT_CALLBACK_G FLEXT_CALLBACK_V
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_THREAD Flext threads
+
+ @{
+*/
+
+#ifdef FLEXT_THREADS
+
+//! Set up a threaded method callback with no arguments
+#define FLEXT_THREAD(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c) { \
+ thr_params *p = new thr_params(c); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for an anything argument
+#define FLEXT_THREAD_A(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,const t_symbol *s,int argc,t_atom *argv) { \
+ thr_params *p = new thr_params(c); p->set_any(s,argc,argv); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ AtomAnything *args = p->var[0]._any.args; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(args->Header(),args->Count(),args->Atoms()); \
+ th->PopThread(); \
+ } \
+ delete args; \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for a variable argument list
+#define FLEXT_THREAD_V(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int argc,t_atom *argv) { \
+ thr_params *p = new thr_params(c); p->set_list(argc,argv); \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ AtomList *args = p->var[0]._list.args; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(args->Count(),args->Atoms()); \
+ th->PopThread(); \
+ } \
+ delete args; \
+ return NULL; \
+}
+
+/*! \brief Set up a threaded method callback for an arbitrary data struct
+ \note Data is pure... no destructor is called upon delete
+*/
+#define FLEXT_THREAD_X(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,void *data) { \
+ thr_params *p = new thr_params(c); p->var[0]._ext.data = data; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ void *data = p->var[0]._ext.data; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(data); \
+ th->PopThread(); \
+ } \
+ delete data; \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for a boolean argument
+#define FLEXT_THREAD_B(M_FUN) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,int &arg1) { \
+ thr_params *p = new thr_params(c); p->var[0]._bool = arg1 != 0; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ bool b = p->var[0]._bool; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(b); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 1 argument
+#define FLEXT_THREAD_1(M_FUN,TP1) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1) { \
+ thr_params *p = new thr_params(c,1); \
+ p->var[0]._ ## TP1 = arg1; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 2 arguments
+#define FLEXT_THREAD_2(M_FUN,TP1,TP2) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2) { \
+ thr_params *p = new thr_params(c,2); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP1 v2 = p->var[1]._ ## TP2; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 3 arguments
+#define FLEXT_THREAD_3(M_FUN,TP1,TP2,TP3) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3) { \
+ thr_params *p = new thr_params(c,3); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 4 arguments
+#define FLEXT_THREAD_4(M_FUN,TP1,TP2,TP3,TP4) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4) { \
+ thr_params *p = new thr_params(c,4); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ p->var[3]._ ## TP4 = arg4; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ const TP4 v4 = p->var[3]._ ## TP4; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3,v4); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+//! Set up a threaded method callback for 5 arguments
+#define FLEXT_THREAD_5(M_FUN,TP1,TP2,TP3,TP4,TP5) \
+static bool FLEXT_CALL_PRE(M_FUN)(flext_base *c,TP1 &arg1,TP2 &arg2,TP3 &arg3,TP4 &arg4,TP5 &arg5) { \
+ thr_params *p = new thr_params(c,5); \
+ p->var[0]._ ## TP1 = arg1; \
+ p->var[1]._ ## TP2 = arg2; \
+ p->var[2]._ ## TP3 = arg3; \
+ p->var[3]._ ## TP4 = arg4; \
+ p->var[4]._ ## TP5 = arg5; \
+ return StartThread(FLEXT_THR_PRE(M_FUN),p,#M_FUN); \
+} \
+static void *FLEXT_THR_PRE(M_FUN)(thr_params *p) { \
+ thisType *th = FLEXT_CAST<thisType *>(p->cl); \
+ bool ok = th->PushThread(); \
+ const TP1 v1 = p->var[0]._ ## TP1; \
+ const TP2 v2 = p->var[1]._ ## TP2; \
+ const TP3 v3 = p->var[2]._ ## TP3; \
+ const TP4 v4 = p->var[3]._ ## TP4; \
+ const TP5 v5 = p->var[4]._ ## TP5; \
+ delete p; \
+ if(ok) { \
+ th->M_FUN(v1,v2,v3,v4,v5); \
+ th->PopThread(); \
+ } \
+ return NULL; \
+}
+
+
+//! Shortcuts
+
+//! Set up a threaded method callback for 1 float argument
+#define FLEXT_THREAD_F(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,float)
+
+//! Set up a threaded method callback for 2 float arguments
+#define FLEXT_THREAD_FF(M_FUN) \
+\
+FLEXT_THREAD_2(M_FUN,float,float)
+
+//! Set up a threaded method callback for 3 float arguments
+#define FLEXT_THREAD_FFF(M_FUN) \
+\
+FLEXT_THREAD_3(M_FUN,float,float,float)
+
+//! Set up a threaded method callback for 1 integer argument
+#define FLEXT_THREAD_I(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,int)
+
+//! Set up a threaded method callback for 2 integer arguments
+#define FLEXT_THREAD_II(M_FUN) \
+\
+FLEXT_THREAD_2(M_FUN,int,int)
+
+//! Set up a threaded method callback for 3 integer arguments
+#define FLEXT_THREAD_III(M_FUN) \
+\
+FLEXT_THREAD_3(M_FUN,int,int,int)
+
+//! Set up a threaded method callback for 1 symbol argument
+#define FLEXT_THREAD_S(M_FUN) \
+\
+FLEXT_THREAD_1(M_FUN,t_symptr)
+
+// deprecated
+#define FLEXT_THREAD_G FLEXT_THREAD_V
+
+#endif // FLEXT_THREAD
+
+//! @}
+
+
+
+// ====================================================================================
+
+
+
+/*! \defgroup FLEXT_ADDMETHOD Add flext methods
+ These should be the used in the class' constructor
+
+ @{
+*/
+
+//! Enable list element distribution over inlets (if no better handler found)
+#define FLEXT_ADDDIST() \
+\
+SetDist(true)
+
+//! Add a method handler for bang
+#define FLEXT_ADDBANG(IX,M_FUN) \
+\
+AddMethod(IX,"bang",FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with no arguments
+#define FLEXT_ADDMETHOD(IX,M_FUN) \
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with a (variable argument) list
+#define FLEXT_ADDMETHOD_V(IX,M_FUN) \
+\
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with an anything argument
+#define FLEXT_ADDMETHOD_A(IX,M_FUN) \
+\
+AddMethod(IX,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a a handler for a method with implicit arguments
+#define FLEXT_ADDMETHOD_(IX,M_TAG,M_FUN) \
+\
+AddMethod(IX,M_TAG,FLEXT_CALL_PRE(M_FUN))
+
+//! Add a handler for a method with 1 enum type argument
+#define FLEXT_ADDMETHOD_E(IX,M_TAG,M_FUN) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),a_int,a_null)
+
+//! Add a handler for a method with 1 argument
+#define FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,TP1) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),a_null)
+
+//! Add a handler for a method with 2 arguments
+#define FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,TP1,TP2) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),a_null)
+
+//! Add a handler for a method with 3 arguments
+#define FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,TP1,TP2,TP3) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),a_null)
+
+//! Add a handler for a method with 4 arguments
+#define FLEXT_ADDMETHOD_4(IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),a_null)
+
+//! Add a handler for a method with 5 arguments
+#define FLEXT_ADDMETHOD_5(IX,M_TAG,M_FUN,TP1,TP2,TP3,TP4,TP5) \
+\
+AddMethod(IX,M_TAG,(methfun)(FLEXT_CALL_PRE(M_FUN)),FLEXTARG(TP1),FLEXTARG(TP2),FLEXTARG(TP3),FLEXTARG(TP4),FLEXTARG(TP5),a_null)
+
+
+// Shortcuts
+
+//! Add a handler for a method with a boolean argument
+#define FLEXT_ADDMETHOD_B(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,bool)
+
+//! Add a handler for a method with 1 float argument
+#define FLEXT_ADDMETHOD_F(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,float)
+
+//! Add a handler for a method with 2 float arguments
+#define FLEXT_ADDMETHOD_FF(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,float,float)
+
+//! Add a handler for a method with 3 float arguments
+#define FLEXT_ADDMETHOD_FFF(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,float,float,float)
+
+//! Add a handler for a method with 1 integer argument
+#define FLEXT_ADDMETHOD_I(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_1(IX,M_TAG,M_FUN,int)
+
+//! Add a handler for a method with 2 integer arguments
+#define FLEXT_ADDMETHOD_II(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_2(IX,M_TAG,M_FUN,int,int)
+
+//! Add a handler for a method with 3 integer arguments
+#define FLEXT_ADDMETHOD_III(IX,M_TAG,M_FUN) \
+\
+FLEXT_ADDMETHOD_3(IX,M_TAG,M_FUN,int,int,int)
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_CALLMETHOD Call flext methods manually
+ These can only be used in class member functions!
+
+ @{
+*/
+
+//! Call a (already defined) method with no arguments
+#define FLEXT_CALLMETHOD(M_FUN) \
+\
+FLEXT_CALL_PRE(M_FUN)(this)
+
+//! Call a (already defined) method with variable list arguments
+#define FLEXT_CALLMETHOD_V(M_FUN,ARGC,ARGV) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARGC,ARGV)
+
+//! Call a (already defined) method with anything arguments
+#define FLEXT_CALLMETHOD_A(M_FUN,HDR,ARGC,ARGV) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,HDR,ARGC,ARGV)
+
+//! Call a (already defined) method with a data package (void *)
+#define FLEXT_CALLMETHOD_X(M_FUN,DATA) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,DATA)
+
+//! Call a (already defined) method with 1 enum type argument
+#define FLEXT_CALLMETHOD_E(M_FUN,ARG) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG)
+
+//! Call a (already defined) method with 1 argument
+#define FLEXT_CALLMETHOD_1(M_FUN,ARG) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG)
+
+//! Call a (already defined) method with 2 arguments
+#define FLEXT_CALLMETHOD_2(M_FUN,ARG1,ARG2) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2)
+
+//! Call a (already defined) method with 3 arguments
+#define FLEXT_CALLMETHOD_3(M_FUN,ARG1,ARG2,ARG3) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3)
+
+//! Call a (already defined) method with 4 arguments
+#define FLEXT_CALLMETHOD_4(M_FUN,ARG1,ARG2,ARG3,ARG4) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3,ARG4)
+
+//! Call a (already defined) method with 5 arguments
+#define FLEXT_CALLMETHOD_5(M_FUN,ARG1,ARG2,ARG3,ARG4,ARG5) \
+\
+FLEXT_CALL_PRE(M_FUN)(this,ARG1,ARG2,ARG3,ARG4,ARG5)
+
+//! @}
+
+
+
+/*! \defgroup FLEXT_DEFATTR flext functions for attribute definition
+
+ @{
+*/
+
+#define FLEXT_CALLSET_(FUN,TP) \
+static bool FLEXT_SET_PRE(FUN)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(arg); return true; }
+
+#define FLEXT_CALLGET_(FUN,TP) \
+static bool FLEXT_GET_PRE(FUN)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(arg); return true; }
+
+#define FLEXT_ATTRSET_(VAR,TP) \
+static bool FLEXT_SET_PRE(VAR)(flext_base *c,TP &arg) \
+{ FLEXT_CAST<thisType *>(c)->VAR = arg; return true; }
+
+#define FLEXT_ATTRGET_(VAR,TP) \
+static bool FLEXT_GET_PRE(VAR)(flext_base *c,TP &arg) \
+{ arg = FLEXT_CAST<thisType *>(c)->VAR; return true; }
+
+#define FLEXT_CALLSET_F(SFUN) FLEXT_CALLSET_(SFUN,float)
+#define FLEXT_CALLSET_I(SFUN) FLEXT_CALLSET_(SFUN,int)
+#define FLEXT_CALLSET_S(SFUN) FLEXT_CALLSET_(SFUN,t_symptr)
+
+#define FLEXT_CALLSET_V(FUN) \
+static bool FLEXT_SET_PRE(FUN)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(*arg); return true; }
+
+#define FLEXT_CALLGET_F(GFUN) FLEXT_CALLGET_(GFUN,float)
+#define FLEXT_CALLGET_I(GFUN) FLEXT_CALLGET_(GFUN,int)
+#define FLEXT_CALLGET_S(GFUN) FLEXT_CALLGET_(GFUN,t_symptr)
+
+#define FLEXT_CALLGET_V(FUN) \
+static bool FLEXT_GET_PRE(FUN)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->FUN(*arg); return true; }
+
+#define FLEXT_CALLXFER_F(GFUN,SFUN) FLEXT_CALLGET_F(GFUN) FLEXT_CALLSET_F(SFUN)
+#define FLEXT_CALLXFER_I(GFUN,SFUN) FLEXT_CALLGET_I(GFUN) FLEXT_CALLSET_I(SFUN)
+#define FLEXT_CALLXFER_S(GFUN,SFUN) FLEXT_CALLGET_S(GFUN) FLEXT_CALLSET_S(SFUN)
+#define FLEXT_CALLXFER_V(GFUN,SFUN) FLEXT_CALLGET_V(GFUN) FLEXT_CALLSET_V(SFUN)
+
+#define FLEXT_ATTRSET_F(VAR) FLEXT_ATTRSET_(VAR,float)
+#define FLEXT_ATTRSET_I(VAR) FLEXT_ATTRSET_(VAR,int)
+#define FLEXT_ATTRSET_S(VAR) FLEXT_ATTRSET_(VAR,t_symptr)
+
+#define FLEXT_ATTRSET_V(VAR) \
+static bool FLEXT_SET_PRE(VAR)(flext_base *c,AtomList *&arg) \
+{ FLEXT_CAST<thisType *>(c)->VAR = *arg; return true; }
+
+#define FLEXT_ATTRGET_F(VAR) FLEXT_ATTRGET_(VAR,float)
+#define FLEXT_ATTRGET_I(VAR) FLEXT_ATTRGET_(VAR,int)
+#define FLEXT_ATTRGET_S(VAR) FLEXT_ATTRGET_(VAR,t_symptr)
+
+#define FLEXT_ATTRGET_V(VAR) \
+static bool FLEXT_GET_PRE(VAR)(flext_base *c,AtomList *&arg) \
+{ *arg = FLEXT_CAST<thisType *>(c)->VAR; return true; }
+
+#define FLEXT_ATTRXFER_F(VAR) FLEXT_ATTRGET_F(VAR) FLEXT_ATTRSET_F(VAR)
+#define FLEXT_ATTRXFER_I(VAR) FLEXT_ATTRGET_I(VAR) FLEXT_ATTRSET_I(VAR)
+#define FLEXT_ATTRXFER_S(VAR) FLEXT_ATTRGET_S(VAR) FLEXT_ATTRSET_S(VAR)
+#define FLEXT_ATTRXFER_V(VAR) FLEXT_ATTRGET_V(VAR) FLEXT_ATTRSET_V(VAR)
+
+//! @}
+
+/*! \defgroup FLEXT_ADDATTR flext methods for defining attributes
+ These can only be used in class member functions!
+
+ @{
+*/
+
+#define FLEXT_ADDATTR_GET(NAME,GFUN) AddAttrib(NAME,(FLEXT_GET_PRE(GFUN)),NULL)
+#define FLEXT_ADDATTR_SET(NAME,SFUN) AddAttrib(NAME,NULL,(FLEXT_SET_PRE(SFUN)))
+#define FLEXT_ADDATTRIB(NAME,FUN) AddAttrib(NAME,(FLEXT_GET_PRE(FUN)),(FLEXT_SET_PRE(FUN)))
+
+//! @}
+
+
+
+
+#endif // __FLEXT_DEFS_H
diff --git a/externals/grill/flext/source/fldoxygen.h b/externals/grill/flext/source/fldoxygen.h
new file mode 100644
index 00000000..bae97b44
--- /dev/null
+++ b/externals/grill/flext/source/fldoxygen.h
@@ -0,0 +1,22 @@
+#ifndef __FLEXT_DOXYGEN_H
+#define __FLEXT_DOXYGEN_H
+
+/*! \file fldoxygen.h
+ \brief Doxygen definitions
+ \remark There is no code in here, just documentation stuff.
+*/
+
+/*! \mainpage flext - C++ layer for cross-platform development of PD and Max/MSP objects
+
+ \section intro Introduction
+
+ This is the introduction
+
+ \section install Installation
+
+ \subsection step1 Step 1: Opening the box
+
+ etc...
+*/
+
+#endif
diff --git a/externals/grill/flext/source/fldsp.cpp b/externals/grill/flext/source/fldsp.cpp
new file mode 100644
index 00000000..fc5db717
--- /dev/null
+++ b/externals/grill/flext/source/fldsp.cpp
@@ -0,0 +1,119 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file fldsp.cpp
+ \brief Implementation of the flext dsp base class.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+
+
+
+// === flext_dsp ==============================================
+
+void flext_dsp::Setup(t_class *c)
+{
+#ifdef PD
+// CLASS_MAINSIGNALIN(c,flext_hdr,defsig);
+#elif defined(MAXMSP)
+// dsp_initclass();
+ dsp_initboxclass();
+#endif
+
+ add_dsp(c,cb_dsp);
+#ifndef MAXMSP
+ add_method1(c,cb_enable,"enable",A_FLINT);
+#endif
+}
+
+flext_dsp::flext_dsp():
+#ifndef MAXMSP
+ dspon(true),
+#endif
+ srate(sys_getsr()), // should we set it?
+ blksz(sys_getblksize()),
+#ifdef PD
+ chnsin(sys_get_inchannels()),
+ chnsout(sys_get_outchannels()),
+#else // MAXMSP
+ chnsin(sys_getch()),
+ chnsout(sys_getch()),
+#endif
+ invecs(NULL),outvecs(NULL)
+{}
+
+
+flext_dsp::~flext_dsp()
+{
+ if(invecs) delete[] invecs;
+ if(outvecs) delete[] outvecs;
+}
+
+
+t_int *flext_dsp::dspmeth(t_int *w)
+{
+ flext_dsp *obj = (flext_dsp *)w[1];
+#ifdef MAXMSP
+ if(!obj->thisHdr()->z_disabled)
+#else
+ if(obj->dspon)
+#endif
+ obj->m_signal((int)w[2],obj->invecs,obj->outvecs);
+ return w+3;
+}
+
+void flext_dsp::m_dsp(int /*n*/,t_sample *const * /*insigs*/,t_sample *const * /*outsigs*/) {}
+
+void flext_dsp::m_signal(int n,t_sample *const * /*insigs*/,t_sample *const *outsigs)
+{
+ for(int i = 0; i < CntOutSig(); ++i)
+ memset(outsigs[i],0,n*sizeof(*outsigs[i]));
+}
+
+void flext_dsp::cb_dsp(t_class *c,t_signal **sp)
+{
+ flext_dsp *obj = thisObject(c);
+
+ // store current dsp parameters
+ obj->srate = sp[0]->s_sr;
+ obj->blksz = sp[0]->s_n; // is this guaranteed to be the same as sys_getblksize() ?
+
+#ifdef PD
+ obj->chnsin = sys_get_inchannels();
+ obj->chnsout = sys_get_outchannels();
+#else // MAXMSP
+ obj->chnsin = obj->chnsout = sys_getch();
+#endif
+
+ // store in and out signal vectors
+ int i,in = obj->CntInSig(),out = obj->CntOutSig();
+ if(obj->invecs) delete[] obj->invecs;
+ obj->invecs = new t_sample *[in];
+ for(i = 0; i < in; ++i) obj->invecs[i] = sp[i]->s_vec;
+
+ if(obj->outvecs) delete[] obj->outvecs;
+ obj->outvecs = new t_sample *[out];
+ for(i = 0; i < out; ++i) obj->outvecs[i] = sp[in+i]->s_vec;
+
+ // with the following call derived classes can do their eventual DSP setup
+ obj->m_dsp(sp[0]->s_n,obj->invecs,obj->outvecs);
+
+ // set the DSP function
+ dsp_add((t_dspmethod)dspmeth,2,obj,sp[0]->s_n);
+}
+
+#ifndef MAXMSP
+void flext_dsp::cb_enable(t_class *c,t_flint on) { thisObject(c)->m_enable(on != 0); }
+void flext_dsp::m_enable(bool en) { dspon = en; }
+#endif
+
+
diff --git a/externals/grill/flext/source/fldsp.h b/externals/grill/flext/source/fldsp.h
new file mode 100644
index 00000000..70c88745
--- /dev/null
+++ b/externals/grill/flext/source/fldsp.h
@@ -0,0 +1,140 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file fldsp.h
+ \brief Declares the flext dsp class
+
+*/
+
+#ifndef __FLDSP_H
+#define __FLDSP_H
+
+// include the header file declaring the base classes
+#include "flext.h"
+
+
+// === flext_dsp ==================================================
+
+/*! \brief Flext dsp enabled base object
+*/
+class flext_dsp:
+ public flext_base
+{
+ FLEXT_HEADER_S(flext_dsp,flext_base,Setup)
+
+public:
+
+/*! \defgroup FLEXT_C_DSP Flext basic dsp functionality
+
+ @{
+*/
+
+ //! returns current sample rate
+ float Samplerate() const { return srate; }
+
+ //! returns current block (aka vector) size
+ int Blocksize() const { return blksz; }
+
+ /*! \brief returns number of audio system input channels
+ \bug Doesn't work in Max/MSP - is always 0
+ */
+ int ChannelsIn() const { return chnsin; }
+
+ /*! \brief returns number of audio system output channels
+ \bug Doesn't work in Max/MSP - is always 0
+ */
+ int ChannelsOut() const { return chnsout; }
+
+//! @}
+
+
+// --- inheritable virtual methods --------------------------------
+
+/*! \defgroup FLEXT_C_VIRTUAL_DSP Flext virtual dsp functions
+
+ @{
+*/
+ /*! \brief Called on every dsp init.
+ \note Don't expect any valid data in the signal vectors!
+
+ \param n: frames (aka samples) in one signal vector
+ \param insigs: array of input vectors (get number with function CntInSig())
+ \param outsigs: array of output vectors (get number with function CntOutSig())
+ */
+ virtual void m_dsp(int n,t_sample *const *insigs,t_sample *const *outsigs);
+
+ /*! \brief Called with every signal vector - here you do the dsp calculation
+
+ \param n: frames (aka samples) in one signal vector
+ \param insigs: array of input vectors (get number with function CntInSig())
+ \param outsigs: array of output vectors (get number with function CntOutSig())
+ */
+ virtual void m_signal(int n,t_sample *const *insigs,t_sample *const *outsigs);
+
+#ifndef MAXMSP
+ /*! \brief called with "enable" message: pauses/resumes dsp
+ \note PD only - implicitely defined in MaxMSP
+ */
+ virtual void m_enable(bool on);
+#endif
+
+//! @}
+
+
+/*! \defgroup FLEXT_C_INOUT_DSP Flext dsp in-/outlet functions
+ \note These must be called in the class' constructor
+
+ @{
+*/
+// --- inlet/outlet stuff -----------------------------------------
+
+ /*! \brief Add signal inlet(s)
+ \param m Number of inlets to add
+ */
+ void AddInSignal(int m = 1) { AddInlet(xlet::tp_sig,m); }
+
+ /*! \brief Add signal outlet(s)
+ \param m Number of inlets to add
+ */
+ void AddOutSignal(int m = 1) { AddOutlet(xlet::tp_sig,m); }
+
+//! @}
+
+
+protected:
+
+ flext_dsp();
+ virtual ~flext_dsp();
+
+private:
+
+ // not static, could be different in different patchers..
+ float srate;
+ int blksz;
+ int chnsin,chnsout;
+
+ // setup function
+ static void Setup(t_class *c);
+
+ // callback functions
+
+ static void cb_dsp(t_class *c,t_signal **s);
+#ifndef MAXMSP
+ static void cb_enable(t_class *c,t_flint on);
+ bool dspon;
+#endif
+
+ // dsp stuff
+
+ static t_int *dspmeth(t_int *w);
+ t_sample **invecs,**outvecs;
+};
+
+#endif
diff --git a/externals/grill/flext/source/flext.cpp b/externals/grill/flext/source/flext.cpp
new file mode 100644
index 00000000..5ed852c3
--- /dev/null
+++ b/externals/grill/flext/source/flext.cpp
@@ -0,0 +1,748 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flext.cpp
+ \brief Implementation of the flext base class.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+#include <stdarg.h>
+
+
+// === proxy class for flext_base ============================
+
+#ifdef PD
+
+static t_class *px_class;
+
+struct flext_base::px_object // no virtual table!
+{
+ t_object obj; // MUST reside at memory offset 0
+ flext_base *base;
+ int index;
+
+ void init(flext_base *b,int ix) { base = b; index = ix; }
+ static void px_method(px_object *c,const t_symbol *s,int argc,t_atom *argv);
+};
+
+
+void flext_base::px_object::px_method(px_object *obj,const t_symbol *s,int argc,t_atom *argv)
+{
+ obj->base->m_methodmain(obj->index,s,argc,argv);
+}
+
+void flext_base::cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv)
+{
+ thisObject(c)->m_methodmain(0,s,argc,argv);
+}
+
+#define DEF_IN_FT(IX) \
+void flext_base::cb_px_ft ## IX(t_class *c,float v) { \
+ t_atom atom; SETFLOAT(&atom,v); \
+ thisObject(c)->m_methodmain(IX,&s_float,1,&atom); \
+}
+
+#define ADD_IN_FT(IX) \
+add_method1(c,cb_px_ft ## IX,"ft" #IX,A_FLOAT)
+
+#elif defined(MAXMSP)
+
+void flext_base::cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv)
+{
+ // check if inlet allows anything (or list)
+
+ flext_base *o = thisObject(c);
+ int ci = ((flext_hdr *)o->x_obj)->curinlet;
+
+ o->m_methodmain(ci,s,argc,argv);
+}
+
+void flext_base::cb_px_int(t_class *c,int v)
+{
+ // check if inlet allows int type
+ t_atom atom;
+ SETINT(&atom,v);
+ cb_px_anything(c,sym_int,1,&atom);
+}
+
+void flext_base::cb_px_float(t_class *c,float v)
+{
+ // check if inlet allows float type
+ t_atom atom;
+ SETFLOAT(&atom,v);
+ cb_px_anything(c,sym_float,1,&atom);
+}
+
+void flext_base::cb_px_bang(t_class *c)
+{
+ // check if inlet allows bang
+ cb_px_anything(c,sym_bang,0,NULL);
+}
+
+
+#define DEF_IN_FT(IX) \
+void flext_base::cb_px_in ## IX(t_class *c,int v) { long &ci = ((flext_hdr *)thisObject(c)->x_obj)->curinlet; ci = IX; cb_px_int(c,v); ci = 0; } \
+void flext_base::cb_px_ft ## IX(t_class *c,float v) { long &ci = ((flext_hdr *)thisObject(c)->x_obj)->curinlet; ci = IX; cb_px_float(c,v); ci = 0; }
+
+#define ADD_IN_FT(IX) \
+add_method1(c,cb_px_in ## IX,"in" #IX,A_INT); \
+add_method1(c,cb_px_ft ## IX,"ft" #IX,A_FLOAT)
+
+#endif // MAXMSP
+
+
+DEF_IN_FT(1)
+DEF_IN_FT(2)
+DEF_IN_FT(3)
+DEF_IN_FT(4)
+DEF_IN_FT(5)
+DEF_IN_FT(6)
+DEF_IN_FT(7)
+DEF_IN_FT(8)
+DEF_IN_FT(9)
+
+
+
+// === flext_base ============================================
+
+bool flext_base::compatibility = true;
+
+flext_base::flext_base():
+ inlist(NULL),outlist(NULL),
+ incnt(0),outcnt(0),
+ insigs(0),outsigs(0),
+ curtag(NULL),
+ outlets(NULL),inlets(NULL),outattr(NULL),
+ methhead(NULL),attrhead(NULL),attrcnt(0),
+ distmsgs(false)
+{
+ LOG1("%s - flext logging is on",thisName());
+
+#ifdef FLEXT_THREADS
+ thrid = pthread_self();
+
+ shouldexit = false;
+ thrhead = thrtail = NULL;
+#endif
+ qhead = qtail = NULL;
+ qclk = (t_qelem *)(qelem_new(this,(t_method)QTick));
+#ifdef MAXMSP
+ yclk = (t_clock *)(clock_new(this,(t_method)YTick));
+#endif
+
+ AddMethod(0,"getattributes",(methfun)cb_ListAttrib);
+}
+
+flext_base::~flext_base()
+{
+#ifdef FLEXT_THREADS
+ // wait for thread termination
+ shouldexit = true;
+ for(int wi = 0; thrhead && wi < 100; ++wi) Sleep(0.01f);
+
+#ifdef PD
+ qmutex.Lock(); // Lock message queue
+ tlmutex.Lock();
+ // timeout -> hard termination
+ while(thrhead) {
+ thr_entry *t = thrhead;
+ if(pthread_cancel(t->thrid)) post("%s - Thread could not be terminated!",thisName());
+ thrhead = t->nxt;
+ t->nxt = NULL; delete t;
+ }
+ tlmutex.Unlock();
+ qmutex.Unlock();
+#else
+#pragma message ("No tread cancelling")
+#endif
+
+#endif
+
+ // send remaining pending messages
+ while(qhead) QTick(this);
+ qelem_free((t_qelem *)qclk);
+#ifdef MAXMSP
+ clock_free((object *)yclk);
+#endif
+
+ if(inlist) delete inlist;
+ if(outlist) delete outlist;
+ if(outlets) delete[] outlets;
+
+ if(inlets) {
+ for(int ix = 0; ix < incnt; ++ix)
+ if(inlets[ix]) {
+#ifdef PD
+ pd_free(&inlets[ix]->obj.ob_pd);
+#elif defined(MAXMSP)
+ freeobject((object *)inlets[ix]);
+#endif
+ }
+ delete[] inlets;
+ }
+
+#ifdef MAXMSP
+// if(insigs) dsp_free(thisHdr());
+ if(insigs) dsp_freebox(thisHdr());
+#endif
+
+ if(methhead) delete methhead;
+ if(attrhead) delete attrhead;
+}
+
+
+bool flext_base::Init()
+{
+// if(!flext_obj::Init()) return false;
+
+ bool ok = true;
+
+ incnt = insigs = 0;
+
+ if(inlets) {
+ for(int ix = 0; ix < incnt; ++ix)
+ if(inlets[ix]) {
+#ifdef PD
+ pd_free(&inlets[ix]->obj.ob_pd);
+#elif defined(MAXMSP)
+ freeobject(inlets[ix]);
+#endif
+ }
+ delete[] inlets;
+ inlets = NULL;
+ }
+
+ if(inlist) {
+ xlet *xi;
+ incnt = 0;
+ for(xi = inlist; xi; xi = xi->nxt) ++incnt;
+ xlet::type *list = new xlet::type[incnt];
+ int i;
+ for(xi = inlist,i = 0; xi; xi = xi->nxt,++i) list[i] = xi->tp;
+ delete inlist; inlist = NULL;
+
+ inlets = new px_object *[incnt];
+ for(i = 0; i < incnt; ++i) inlets[i] = NULL;
+
+ // type info is now in list array
+#ifdef PD
+ {
+ int cnt = 0;
+
+ if(incnt >= 1) {
+ switch(list[0]) {
+ case xlet::tp_sig:
+ CLASS_MAINSIGNALIN(thisClass(),flext_hdr,defsig);
+ ++insigs;
+ break;
+ default:
+ // leftmost inlet is already there...
+ break;
+ }
+ ++cnt;
+ }
+
+ for(int ix = 1; ix < incnt; ++ix,++cnt) {
+ switch(list[ix]) {
+ case xlet::tp_float:
+ case xlet::tp_int: {
+ char sym[] = "ft??";
+ if(ix >= 10) {
+ if(compatibility) {
+ // Max allows max. 9 inlets
+ post("%s: Only 9 float/int inlets allowed in compatibility mode",thisName());
+ ok = false;
+ }
+ else {
+ if(ix > 99)
+ post("%s: Inlet index > 99 not allowed for float/int inlets",thisName());
+ sym[2] = '0'+ix/10,sym[3] = '0'+ix%10;
+ }
+ }
+ else
+ sym[2] = '0'+ix,sym[3] = 0;
+ if(ok) inlet_new(&x_obj->obj, &x_obj->obj.ob_pd, &s_float, gensym(sym));
+ break;
+ }
+ case xlet::tp_sym:
+ (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, &s_symbol, &s_symbol);
+ break;
+ case xlet::tp_list:
+ (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, &s_list, &s_list);
+ break;
+ case xlet::tp_any:
+ (inlets[ix] = (px_object *)pd_new(px_class))->init(this,ix); // proxy for 2nd inlet messages
+ inlet_new(&x_obj->obj,&inlets[ix]->obj.ob_pd, 0, 0);
+ break;
+ case xlet::tp_sig:
+ if(compatibility && list[ix-1] != xlet::tp_sig) {
+ post("%s: All signal inlets must be left-aligned in compatibility mode",thisName());
+ ok = false;
+ }
+ else {
+ // pd doesn't seem to be able to handle signals and messages into the same inlet...
+
+ inlet_new(&x_obj->obj, &x_obj->obj.ob_pd, &s_signal, &s_signal);
+ ++insigs;
+ }
+ break;
+ default:
+ error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)list[ix]);
+ ok = false;
+ }
+ }
+
+ incnt = cnt;
+ }
+#elif defined(MAXMSP)
+ {
+ int ix,cnt;
+ // count leftmost signal inlets
+ while(insigs < incnt && list[insigs] == xlet::tp_sig) ++insigs;
+
+ for(cnt = 0,ix = incnt-1; ix >= insigs; --ix,++cnt) {
+ if(ix == 0) {
+ if(list[ix] != xlet::tp_any) {
+ error("%s: Leftmost inlet must be of type signal or default",thisName());
+ ok = false;
+ }
+ }
+ else {
+ switch(list[ix]) {
+ case xlet::tp_sig:
+ error("%s: All signal inlets must be at the left side",thisName());
+ ok = false;
+ break;
+ case xlet::tp_float:
+ if(ix >= 10) {
+ post("%s: Only 9 float inlets possible",thisName());
+ ok = false;
+ }
+ else
+ floatin(x_obj,ix);
+ break;
+ case xlet::tp_int:
+ if(ix >= 10) {
+ post("%s: Only 9 int inlets possible",thisName());
+ ok = false;
+ }
+ else
+ intin(x_obj,ix);
+ break;
+ case xlet::tp_any: // non-leftmost
+ case xlet::tp_sym:
+ case xlet::tp_list:
+ inlets[ix] = (px_object *)proxy_new(x_obj,ix,&((flext_hdr *)x_obj)->curinlet);
+ break;
+ default:
+ error("%s: Wrong type for inlet #%i: %i",thisName(),ix,(int)list[ix]);
+ ok = false;
+ }
+ }
+ }
+
+ incnt = cnt;
+
+ if(insigs)
+// dsp_setup(thisHdr(),insigs); // signal inlets
+ dsp_setupbox(thisHdr(),insigs); // signal inlets
+ }
+#endif
+
+ delete[] list;
+ }
+
+ if(outlets) { delete[] outlets; outlets = NULL; }
+ outcnt = outsigs = 0;
+
+ if(outlist) {
+ xlet *xi;
+
+ // count outlets
+ outcnt = 0;
+ for(xi = outlist; xi; xi = xi->nxt) ++outcnt;
+
+ xlet::type *list = new xlet::type[outcnt];
+ int i;
+ for(xi = outlist,i = 0; xi; xi = xi->nxt,++i) list[i] = xi->tp;
+ delete outlist; outlist = NULL;
+
+ outlets = new outlet *[outcnt];
+
+ // type info is now in list array
+#ifdef PD
+ for(int ix = 0; ix < outcnt; ++ix)
+#elif defined(MAXMSP)
+ for(int ix = outcnt-1; ix >= 0; --ix)
+#endif
+ {
+ switch(list[ix]) {
+ case xlet::tp_float:
+ outlets[ix] = (outlet *)newout_float(&x_obj->obj);
+ break;
+ case xlet::tp_int:
+ outlets[ix] = (outlet *)newout_flint(&x_obj->obj);
+ break;
+ case xlet::tp_sig:
+ outlets[ix] = (outlet *)newout_signal(&x_obj->obj);
+ ++outsigs;
+ break;
+ case xlet::tp_sym:
+ outlets[ix] = (outlet *)newout_symbol(&x_obj->obj);
+ break;
+ case xlet::tp_list:
+ outlets[ix] = (outlet *)newout_list(&x_obj->obj);
+ break;
+ case xlet::tp_any:
+ outlets[ix] = (outlet *)newout_anything(&x_obj->obj);
+ break;
+#ifdef _DEBUG
+ default:
+ ERRINTERNAL();
+ ok = false;
+#endif
+ }
+ }
+
+ delete[] list;
+ }
+
+ if(procattr)
+ // attribute dump outlet is the last one
+ outattr = (outlet *)newout_anything(&x_obj->obj);
+
+ return ok;
+}
+
+void flext_base::Setup(t_class *c)
+{
+ add_method(c,cb_help,"help");
+ add_loadbang(c,cb_loadbang);
+#ifdef MAXMSP
+ add_assist(c,cb_assist);
+#endif
+
+ // proxy for extra inlets
+#ifdef PD
+ add_anything(c,cb_px_anything); // for leftmost inlet
+ px_class = class_new(gensym("flext_base proxy"),NULL,NULL,sizeof(px_object),CLASS_PD|CLASS_NOINLET, A_NULL);
+ add_anything(px_class,px_object::px_method); // for other inlets
+#elif defined(MAXMSP)
+ add_bang(c,cb_px_bang);
+ add_method1(c,cb_px_int,"int",A_INT);
+ add_method1(c,cb_px_float,"float",A_FLOAT);
+ add_methodG(c,cb_px_anything,"list");
+ add_anything(c,cb_px_anything);
+#endif
+
+ // setup non-leftmost ints and floats
+ ADD_IN_FT(1);
+ ADD_IN_FT(2);
+ ADD_IN_FT(3);
+ ADD_IN_FT(4);
+ ADD_IN_FT(5);
+ ADD_IN_FT(6);
+ ADD_IN_FT(7);
+ ADD_IN_FT(8);
+ ADD_IN_FT(9);
+}
+
+void flext_base::cb_help(t_class *c) { thisObject(c)->m_help(); }
+
+void flext_base::cb_loadbang(t_class *c) { thisObject(c)->m_loadbang(); }
+#ifdef MAXMSP
+void flext_base::cb_assist(t_class *c,void * /*b*/,long msg,long arg,char *s) { thisObject(c)->m_assist(msg,arg,s); }
+#endif
+
+void flext_base::m_help()
+{
+ // This should better be overloaded
+ post("%s (using flext " FLEXT_VERSTR ") - compiled on %s %s",thisName(),__DATE__,__TIME__);
+}
+
+
+bool flext_base::m_methodmain(int inlet,const t_symbol *s,int argc,t_atom *argv)
+{
+ static bool trap = false;
+ bool ret = false;
+
+ curtag = s;
+
+ LOG3("methodmain inlet:%i args:%i symbol:%s",inlet,argc,s?s->s_name:"");
+
+ for(const methitem *m = methhead; m && !ret; m = m->nxt) {
+ if(m->tag == s && (inlet == m->inlet || m->inlet < 0 )) {
+ // tag fits
+ LOG4("found method tag %s: inlet=%i, symbol=%s, argc=%i",m->tag->s_name,inlet,s->s_name,argc);
+
+ if(m->argc == 1 && m->args[0] == a_list) {
+ ret = ((methfun_V)m->fun)(this,argc,argv);
+ }
+ else if(m->argc == 1 && m->args[0] == a_any) {
+ ret = ((methfun_A)m->fun)(this,s,argc,argv);
+ }
+ else if(argc == m->argc) {
+ int ix;
+ t_any aargs[FLEXT_MAXMETHARGS];
+ bool ok = true;
+ for(ix = 0; ix < argc && ok; ++ix) {
+ switch(m->args[ix]) {
+ case a_float: {
+ if(IsFloat(argv[ix])) aargs[ix].ft = GetFloat(argv[ix]);
+ else if(IsInt(argv[ix])) aargs[ix].ft = (float)GetInt(argv[ix]);
+ else ok = false;
+
+ if(ok) LOG2("int arg %i = %f",ix,aargs[ix].ft);
+ break;
+ }
+ case a_int: {
+ if(IsFloat(argv[ix])) aargs[ix].it = (int)GetFloat(argv[ix]);
+ else if(IsInt(argv[ix])) aargs[ix].it = GetInt(argv[ix]);
+ else ok = false;
+
+ if(ok) LOG2("float arg %i = %i",ix,aargs[ix].it);
+ break;
+ }
+ case a_symbol: {
+ if(IsSymbol(argv[ix])) aargs[ix].st = GetSymbol(argv[ix]);
+ else ok = false;
+
+ if(ok) LOG2("symbol arg %i = %s",ix,GetString(aargs[ix].st));
+ break;
+ }
+#ifdef PD
+ case a_pointer: {
+ if(IsPointer(argv[ix])) aargs[ix].pt = GetPointer(argv[ix]);
+ else ok = false;
+ break;
+ }
+#endif
+ default:
+ error("Argument type illegal");
+ ok = false;
+ }
+ }
+
+ if(ok && ix == argc) {
+ switch(argc) {
+ case 0: ret = ((methfun_0)m->fun)(this); break;
+ case 1: ret = ((methfun_1)m->fun)(this,aargs[0]); break;
+ case 2: ret = ((methfun_2)m->fun)(this,aargs[0],aargs[1]); break;
+ case 3: ret = ((methfun_3)m->fun)(this,aargs[0],aargs[1],aargs[2]); break;
+ case 4: ret = ((methfun_4)m->fun)(this,aargs[0],aargs[1],aargs[2],aargs[3]); break;
+ case 5: ret = ((methfun_5)m->fun)(this,aargs[0],aargs[1],aargs[2],aargs[3],aargs[4]); break;
+ }
+ }
+ }
+ }
+ else if(m->tag == sym_symbol && !argc && (inlet == m->inlet || m->inlet < 0 )) {
+ // symbol
+ LOG3("found symbol method for %s: inlet=%i, symbol=%s",m->tag->s_name,inlet,s->s_name);
+
+ t_any sym; sym.st = const_cast<t_symbol *>(s);
+ ret = ((methfun_1)m->fun)(this,sym);
+ }
+ else if(m->tag == sym_anything && (inlet == m->inlet || m->inlet < 0) && m->argc == 1 && m->args[0] == a_any) {
+ // any
+ LOG4("found any method for %s: inlet=%i, symbol=%s, argc=%i",m->tag->s_name,inlet,s->s_name,argc);
+
+ ret = ((methfun_A)m->fun)(this,s,argc,argv);
+ }
+ }
+
+#ifdef MAXMSP
+ // If float message is not explicitly handled: try int handler instead
+ if(!ret && argc == 1 && s == sym_float && !trap) {
+ t_atom fl;
+ SetInt(fl,GetAInt(argv[0]));
+ trap = true;
+ ret = m_methodmain(inlet,sym_int,1,&fl);
+ trap = false;
+ }
+
+ // If int message is not explicitly handled: try float handler instead
+ if(!ret && argc == 1 && s == sym_int && !trap) {
+ t_atom fl;
+ SetFloat(fl,GetAFloat(argv[0]));
+ trap = true;
+ ret = m_methodmain(inlet,sym_float,1,&fl);
+ trap = false;
+ }
+#endif
+
+ // If float or int message is not explicitly handled: try list handler instead
+ if(!ret && !trap && argc == 1 && (s == sym_float
+#ifdef MAXMSP
+ || s == sym_int
+#endif
+ )) {
+ t_atom list;
+ if(s == sym_float)
+ SetFloat(list,GetFloat(argv[0]));
+#ifdef MAXMSP
+ else if(s == sym_int)
+ SetInt(list,GetInt(argv[0]));
+#endif
+
+ trap = true;
+ ret = m_methodmain(inlet,sym_list,1,&list);
+ trap = false;
+ }
+
+ // If symbol message (pure anything without args) is not explicitly handled: try list handler instead
+ if(!ret && !trap && argc == 0) {
+ t_atom list;
+ SetSymbol(list,s);
+ trap = true;
+ ret = m_methodmain(inlet,sym_list,1,&list);
+ trap = false;
+ }
+
+ // if distmsgs is switched on then distribute list elements over inlets (Max/MSP behavior)
+ if(!ret && distmsgs && !trap && inlet == 0 && s == sym_list && insigs <= 1) {
+ int i = incnt;
+ if(i > argc) i = argc;
+ for(--i; i >= 0; --i) { // right to left distribution
+ const t_symbol *sym = NULL;
+ if(IsFloat(argv[i])) sym = sym_float;
+ else if(IsInt(argv[i])) sym = sym_int;
+ else if(IsSymbol(argv[i])) sym = sym_symbol;
+#ifdef PD
+ else if(IsPointer(argv[i])) sym = sym_pointer; // can pointer atoms occur here?
+#endif
+ if(sym) {
+ trap = true;
+ m_methodmain(i,sym,1,argv+i);
+ trap = false;
+ }
+ }
+
+ ret = true;
+ }
+
+ if(!ret && !trap) ret = m_method_(inlet,s,argc,argv);
+
+ curtag = NULL;
+
+ return ret; // true if appropriate handler was found and called
+}
+
+bool flext_base::m_method_(int inlet,const t_symbol *s,int argc,t_atom *argv)
+{
+//#ifdef _DEBUG
+ post("%s: message unhandled - inlet:%i args:%i symbol:%s",thisName(),inlet,argc,s?s->s_name:"");
+//#endif
+ return false;
+}
+
+
+flext_base::methitem::methitem(int in,const t_symbol *t):
+ inlet(in),tag(t),
+ fun(NULL),
+ argc(0),args(NULL),
+ nxt(NULL)
+{}
+
+flext_base::methitem::~methitem()
+{
+ if(nxt) delete nxt;
+ if(args) delete[] args;
+}
+
+void flext_base::methitem::SetArgs(methfun _fun,int _argc,metharg *_args)
+{
+ fun = _fun;
+ if(args) delete[] args;
+ argc = _argc,args = _args;
+}
+
+
+
+void flext_base::AddMethItem(methitem *m)
+{
+ if(methhead) {
+ methitem *mi;
+ for(mi = methhead; mi->nxt; mi = mi->nxt) {}
+ mi->nxt = m;
+ }
+ else
+ methhead = m;
+}
+/*
+const flext_base::methitem *flext_base::FindMethItem(int inlet,const t_symbol *tag,const methitem *st)
+{
+ const methitem *mi = st?st:mlst;
+ if(inlet < 0) {
+ for(; mi; mi = mi->nxt)
+ if(mi->tag == tag) break;
+ }
+ else {
+ for(; mi; mi = mi->nxt)
+ if(mi->inlet == inlet && mi->tag == tag) break;
+ }
+ return mi;
+}
+*/
+
+void flext_base::AddMethodDef(int inlet,const char *tag)
+{
+ AddMethItem(new methitem(inlet,tag?MakeSymbol(tag):NULL));
+}
+
+void flext_base::AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...)
+{
+ methitem *mi = new methitem(inlet,MakeSymbol(tag));
+
+ va_list marker;
+
+ // at first just count the arg type list (in argc)
+ int argc = 0;
+ va_start(marker,tp);
+ metharg *args = NULL,arg = tp;
+ for(; arg != a_null; ++argc) arg = (metharg)va_arg(marker,int); //metharg);
+ va_end(marker);
+
+ if(argc > 0) {
+ if(argc > FLEXT_MAXMETHARGS) {
+ error("%s - method %s: only %i arguments are type-checkable: use variable argument list for more",thisName(),tag?tag:"?",FLEXT_MAXMETHARGS);
+ argc = FLEXT_MAXMETHARGS;
+ }
+
+ args = new metharg[argc];
+
+ va_start(marker,tp);
+ metharg a = tp;
+ for(int ix = 0; ix < argc; ++ix) {
+#ifdef _DEBUG
+ if(a == a_list && ix > 0) {
+ ERRINTERNAL();
+ }
+#endif
+#ifdef PD
+ if(a == a_pointer && flext_base::compatibility) {
+ post("Pointer arguments are not allowed in compatibility mode");
+ }
+#endif
+ args[ix] = a;
+ a = (metharg)va_arg(marker,int); //metharg);
+ }
+ va_end(marker);
+ }
+
+ mi->SetArgs(fun,argc,args);
+
+ AddMethItem(mi);
+}
+
+
diff --git a/externals/grill/flext/source/flext.h b/externals/grill/flext/source/flext.h
new file mode 100644
index 00000000..fd99f253
--- /dev/null
+++ b/externals/grill/flext/source/flext.h
@@ -0,0 +1,45 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flext.h
+ \brief This is the main flext include file.
+
+ The basic definitions are set here and the necessary header files are included
+*/
+
+#ifndef __FLEXT_H
+#define __FLEXT_H
+
+
+/*! \defgroup FLEXT_GLOBAL Flext global definitions
+ @{
+*/
+
+//! \brief flext version number
+#define FLEXT_VERSION 400
+
+//! \brief flext version string
+#define FLEXT_VERSTR "0.4.0pre"
+
+//! @}
+
+
+// include all the flext interface definitions
+#include "fldefs.h"
+
+// include the basic flext object classes
+#include "flclass.h"
+
+// include the flext dsp class
+#include "fldsp.h"
+
+#endif // FLEXT_H
+
+
diff --git a/externals/grill/flext/source/flinternal.h b/externals/grill/flext/source/flinternal.h
new file mode 100644
index 00000000..20989b1b
--- /dev/null
+++ b/externals/grill/flext/source/flinternal.h
@@ -0,0 +1,111 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flinternal.h
+ \brief Definitions for internal flext usage
+ \internal
+
+ Here, a few shortcuts for common MaxMSP or PD library calls and type definitions
+ are declared
+*/
+
+#ifndef __FLEXT_INTERNALS_H
+#define __FLEXT_INTERNALS_H
+
+#include "flstdc.h"
+
+
+#ifdef PD
+
+#define object_new(clss) pd_new(clss)
+#define object_free(obj) pd_free(&(obj).ob_pd)
+
+
+
+#define add_dsp(clss,meth) class_addmethod(clss, (t_method)meth,gensym("dsp"),A_NULL)
+#define add_bang(clss,meth) class_addbang(clss, (t_method)meth)
+#define add_float(clss,meth) class_addfloat(clss, (t_method)meth)
+#define add_floatn(clss,meth,n) class_addmethod(clss, (t_method)meth,gensym("ft" #n),A_FLOAT,A_NULL)
+#define add_flint(clss,meth) class_addfloat(clss, (t_method)meth)
+#define add_flintn(clss,meth,n) class_addmethod(clss, (t_method)meth,gensym("ft" #n),A_FLOAT,A_NULL)
+#define add_method(clss,meth,text) class_addmethod(clss, (t_method)meth, gensym(text), A_NULL)
+#define add_methodG(clss,meth,text) class_addmethod(clss, (t_method)meth, gensym(text), A_GIMME,A_NULL)
+#define add_method1(clss,meth,text,a1) class_addmethod(clss, (t_method)meth, gensym(text), a1,A_NULL)
+#define add_method2(clss,meth,text,a1,a2) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,A_NULL)
+#define add_method3(clss,meth,text,a1,a2,a3) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,A_NULL)
+#define add_method4(clss,meth,text,a1,a2,a3,a4) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,a4,A_NULL)
+#define add_method5(clss,meth,text,a1,a2,a3,a5) class_addmethod(clss, (t_method)meth, gensym(text), a1,a2,a3,a4,a5,A_NULL)
+#define add_loadbang(clss,meth) class_addmethod(clss,(t_method)meth, gensym("loadbang"), A_CANT, A_NULL)
+#define add_anything(clss,meth) class_addanything(clss,meth)
+
+
+#define newout_signal(clss) outlet_new(clss,&s_signal)
+#define newout_float(clss) outlet_new(clss,&s_float)
+#define newout_flint(clss) outlet_new(clss,&s_float)
+#define newout_list(clss) outlet_new(clss,&s_list)
+#define newout_symbol(clss) outlet_new(clss,&s_symbol)
+#define newout_anything(clss) outlet_new(clss,&s_anything)
+
+#define outlet_flint(o,v) outlet_float(o,(float)(v))
+
+typedef t_perfroutine t_dspmethod;
+
+#define qelem_new clock_new
+#define qelem_free clock_free
+#define qelem_set clock_set
+#define qelem_unset clock_unset
+
+#elif defined(MAXMSP)
+
+/*
+typedef void _inlet;
+typedef _inlet t_inlet;
+*/
+
+typedef void t_outlet;
+//typedef _outlet t_outlet;
+
+#define object_new(clss) pd_new(clss)
+#define object_free(obj) freeobject((object *)obj)
+
+#define add_dsp(clss,meth) addmess((method)meth,"dsp",A_CANT,A_NOTHING)
+#define add_bang(clss,meth) addbang((method)meth)
+#define add_float(clss,meth) addfloat((method)meth)
+#define add_floatn(clss,meth,n) addftx((method)meth,n)
+#define add_flint(clss,meth) addint((method)meth)
+#define add_flintn(clss,meth,n) addinx((method)meth,n)
+#define add_method(clss,meth,text) addmess((method)meth, text, A_NOTHING)
+#define add_methodG(clss,meth,text) addmess((method)meth, text, A_GIMME,A_NOTHING)
+#define add_method1(clss,meth,text,a1) addmess((method)meth, text, a1,A_NOTHING)
+#define add_method2(clss,meth,text,a1,a2) addmess((method)meth, text, a1,a2,A_NOTHING)
+#define add_method3(clss,meth,text,a1,a2,a3) addmess((method)meth, text, a1,a2,a3,A_NOTHING)
+#define add_method4(clss,meth,text,a1,a2,a3,a4) addmess((method)meth, text, a1,a2,a3,a4,A_NOTHING)
+#define add_method5(clss,meth,text,a1,a2,a3,a5) addmess((method)meth, text, a1,a2,a3,a4,a5,A_NOTHING)
+#define add_anything(clss,meth) addmess((method)meth, "anything", A_GIMME,A_NOTHING)
+
+#define add_assist(clss,meth) addmess((method)meth, "assist", A_CANT, A_NULL)
+#define add_loadbang(clss,meth) addmess((method)meth, "loadbang", A_CANT, A_NULL)
+
+#define newout_signal(clss) outlet_new(clss,"signal")
+#define newout_float(clss) outlet_new(clss,"float")
+#define newout_flint(clss) outlet_new(clss,"int")
+#define newout_list(clss) outlet_new(clss,"list")
+#define newout_symbol(clss) outlet_new(clss,"symbol")
+#define newout_anything(clss) outlet_new(clss,"anything")
+
+#define outlet_flint(o,v) outlet_int(o,(int)(v))
+#define outlet_symbol(o,s) outlet_anything(o,s,0,NULL)
+
+typedef t_perfroutine t_dspmethod;
+
+#endif
+
+
+#endif
diff --git a/externals/grill/flext/source/fllib.cpp b/externals/grill/flext/source/fllib.cpp
new file mode 100755
index 00000000..eee94ce5
--- /dev/null
+++ b/externals/grill/flext/source/fllib.cpp
@@ -0,0 +1,386 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+// Code for handling of object creation functions
+
+#include "flext.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+
+#define ALIASDEL ','
+
+#define ALIASSLASHES ":/\\"
+#ifdef MAXMSP
+ #define ALIASSLASH ':'
+#elif defined(NT)
+ #define ALIASSLASH '/'
+#else
+ #define ALIASSLASH '/'
+#endif
+
+//! Extract space-delimited words from a string
+static const char *extract(const char *name,int ix = 0)
+{
+ static char tmp[1024];
+ const char *n = name;
+
+ const char *del = strchr(name,ALIASDEL);
+
+ if(del) {
+ if(ix < 0) {
+ char *t = tmp;
+ while(n < del && (isspace(*n) || strchr(ALIASSLASHES,*n))) ++n;
+ while(n < del && !isspace(*n)) {
+ char c = *(n++);
+ *(t++) = strchr(ALIASSLASHES,c)?ALIASSLASH:c;
+ }
+ while(*t == ALIASSLASH && t > tmp) --t;
+ *t = 0;
+
+ return tmp;
+ }
+
+ n = del+1;
+ }
+
+ while(*n && isspace(*n)) ++n;
+
+ for(int i = 0; n && *n; ++i) {
+ if(i == ix) {
+ char *t = tmp;
+
+ for(; *n && !isspace(*n); ++t,++n) *t = *n;
+ *t = 0;
+ return *tmp?tmp:NULL;
+ }
+ else {
+ while(*n && !isspace(*n)) ++n;
+ while(*n && isspace(*n)) ++n;
+ }
+ }
+
+ return NULL;
+}
+
+
+//! Check if object's name ends with a tilde
+static bool chktilde(const char *objname)
+{
+// int stplen = strlen(setupfun);
+ bool tilde = true; //!strncmp(setupfun,"_tilde",6);
+
+ if((objname[strlen(objname)-1] == '~'?1:0)^(tilde?1:0)) {
+ if(tilde)
+ error("flext: %s (no trailing ~) is defined as a tilde object",objname);
+ else
+ error("flext::check_tilde: %s is no tilde object",objname);
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+// this class stands for one registered object
+// it holds the class, type flags, constructor and destructor of the object and the creation arg types
+// it will never be destroyed
+class libobject {
+public:
+ libobject(t_class *&cl,flext_obj *(*newf)(int,t_atom *),void (*freef)(flext_hdr *));
+
+ flext_obj *(*newfun)(int,t_atom *);
+ void (*freefun)(flext_hdr *c);
+
+ t_class *const &clss;
+ bool lib,dsp,attr;
+ int argc;
+ int *argv;
+};
+
+libobject::libobject(t_class *&cl,flext_obj *(*newf)(int,t_atom *),void (*freef)(flext_hdr *)):
+ clss(cl),newfun(newf),freefun(freef),argc(0),argv(NULL)
+{}
+
+// this class stands for one registered object name
+// it holds a pointer to the respective object
+// it will never be destroyed
+class libname {
+public:
+ libname(const t_symbol *n,libobject *o): name(n),obj(o),nxt(NULL) {}
+
+ const t_symbol *name;
+ libobject *obj;
+
+ static void add(libname *n);
+ static libname *find(const t_symbol *s);
+
+protected:
+ libname *nxt;
+ void addrec(libname *n);
+ static libname *root;
+};
+
+void libname::addrec(libname *n) { if(nxt) nxt->addrec(n); else nxt = n; }
+
+libname *libname::root = NULL;
+
+void libname::add(libname *l) {
+ if(root) root->addrec(l);
+ else root = l;
+}
+
+libname *libname::find(const t_symbol *s) {
+ libname *l;
+ for(l = root; l; l = l->nxt)
+ if(s == l->name) break;
+ return l;
+}
+
+// for MAXMSP, the library is represented by a special object (class) registered at startup
+// all objects in the library are clones of that library object - they share the same class
+#ifdef MAXMSP
+static t_class *lib_class = NULL;
+static const t_symbol *lib_name = NULL;
+#endif
+
+void flext_obj::lib_init(const char *name,void setupfun(),bool attr)
+{
+#ifdef MAXMSP
+ lib_name = MakeSymbol(name);
+ ::setup(
+ (t_messlist **)&lib_class,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),NULL,A_GIMME,A_NULL);
+#endif
+ process_attributes = attr;
+ setupfun();
+}
+
+void flext_obj::obj_add(bool lib,bool dsp,bool attr,const char *idname,const char *names,void setupfun(t_class *),flext_obj *(*newfun)(int,t_atom *),void (*freefun)(flext_hdr *),int argtp1,...)
+{
+ // get first possible object name
+ const t_symbol *nsym = MakeSymbol(extract(names));
+
+#ifdef _DEBUG
+ if(dsp) chktilde(GetString(nsym));
+#endif
+
+ if(!lib) process_attributes = attr;
+
+ // set dynamic class pointer
+ t_class **cl =
+#ifdef MAXMSP
+ lib?&lib_class:
+#endif
+ new t_class *;
+
+ // register object class
+#ifdef PD
+ *cl = ::class_new(
+ (t_symbol *)nsym,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),0,A_GIMME,A_NULL);
+#elif defined(MAXMSP)
+ if(!lib) {
+ ::setup(
+ (t_messlist **)cl,
+ (t_newmethod)obj_new,(t_method)obj_free,
+ sizeof(flext_hdr),NULL,A_GIMME,A_NULL);
+ }
+#endif
+
+ // make new dynamic object
+ libobject *lo = new libobject(*cl,newfun,freefun);
+ lo->lib = lib;
+ lo->dsp = dsp;
+ lo->attr = process_attributes;
+
+ // parse the argument type list and store it with the object
+ if(argtp1 == A_GIMME)
+ lo->argc = -1;
+ else {
+ int argtp,i;
+ va_list marker;
+
+ // parse a first time and count only
+ va_start(marker,argtp1);
+ for(argtp = argtp1; argtp != A_NULL; ++lo->argc) argtp = (int)va_arg(marker,int);
+ va_end(marker);
+
+ lo->argv = new int[lo->argc];
+
+ // now parse and store
+ va_start(marker,argtp1);
+ for(argtp = argtp1,i = 0; i < lo->argc; ++i) {
+ lo->argv[i] = argtp;
+ argtp = (int)va_arg(marker,int);
+ }
+ va_end(marker);
+ }
+
+ // make help reference
+ flext_obj::DefineHelp(lo->clss,idname,extract(names,-1),dsp);
+
+ for(int ix = 0; ; ++ix) {
+ // in this loop register all the possible aliases of the object
+
+ const char *c = ix?extract(names,ix):GetString(nsym);
+ if(!c || !*c) break;
+
+ // add to name list
+ libname *l = new libname(MakeSymbol(c),lo);
+ libname::add(l);
+
+#ifdef PD
+ if(ix > 0)
+ // in PD the first name is already registered with class creation
+ ::class_addcreator((t_newmethod)obj_new,(t_symbol *)l->name,A_GIMME,A_NULL);
+#elif defined(MAXMSP)
+ if(ix > 0 || lib)
+ // in MaxMSP the first alias gets its name from the name of the object file,
+ // unless it is a library (then the name can be different)
+ ::alias(const_cast<char *>(c));
+#endif
+ }
+
+ // call class setup function
+ setupfun(lo->clss);
+}
+
+
+typedef flext_obj *(*libfun)(int,t_atom *);
+
+flext_hdr *flext_obj::obj_new(const t_symbol *s,int _argc_,t_atom *argv)
+{
+ flext_hdr *obj = NULL;
+ libname *l = libname::find(s);
+ if(l) {
+ bool ok = true;
+ t_atom args[FLEXT_MAXNEWARGS];
+ libobject *lo = l->obj;
+
+ int argc = _argc_;
+ if(lo->attr) {
+ argc = flext_base::CheckAttrib(argc,argv);
+ }
+
+ if(lo->argc >= 0) {
+#ifdef _DEBUG
+ if(lo->argc > FLEXT_MAXNEWARGS) { ERRINTERNAL(); ok = false; }
+#endif
+
+ if(argc == lo->argc) {
+ for(int i = 0; /*ok &&*/ i < lo->argc; ++i) {
+ switch(lo->argv[i]) {
+#ifdef MAXMSP
+ case A_INT:
+ if(flext::IsInt(argv[i])) args[i] = argv[i];
+ else if(flext::IsFloat(argv[i])) flext::SetInt(args[i],(int)flext::GetFloat(argv[i]));
+ else ok = false;
+ break;
+#endif
+ case A_FLOAT:
+ if(flext::IsInt(argv[i])) flext::SetFloat(args[i],(float)flext::GetInt(argv[i]));
+ else if(flext::IsFloat(argv[i])) args[i] = argv[i];
+ else ok = false;
+ break;
+ case A_SYMBOL:
+ if(flext::IsSymbol(argv[i])) args[i] = argv[i];
+ else ok = false;
+ break;
+ }
+ }
+
+ if(!ok)
+ post("%s: Creation arguments do not match",s->s_name);
+ }
+ else {
+ error("%s: %s creation arguments",s->s_name,argc < lo->argc?"Not enough":"Too many");
+ ok = false;
+ }
+ }
+
+ if(ok) {
+#ifdef PD
+ obj = (flext_hdr *)::pd_new(lo->clss);
+#elif defined(MAXMSP)
+ obj = (flext_hdr *)::newobject(lo->clss);
+#endif
+ flext_obj::m_holder = obj;
+ flext_obj::m_holdname = l->name;
+ flext_obj::m_holdattr = lo->attr;
+
+ // get actual flext object (newfun calls "new flext_obj()")
+ if(lo->argc >= 0)
+ // for interpreted arguments
+ obj->data = lo->newfun(lo->argc,args);
+ else
+ obj->data = lo->newfun(argc,argv);
+
+ flext_obj::m_holder = NULL;
+ flext_obj::m_holdname = NULL;
+ flext_obj::m_holdattr = false;
+
+ bool ok = obj->data ||
+ // check constructor exit flag
+ obj->data->InitOk();
+
+ if(ok && lo->attr && argc < _argc_)
+ // set cmdline attributes (this is a flext_base function!)
+ ok = ((flext_base *)obj->data)->InitAttrib(_argc_-argc,argv+argc);
+
+ if(ok) // call virtual init function
+ ok = obj->data->Init();
+
+ if(!ok) {
+ // there was some init error, free object
+ lo->freefun(obj);
+ obj = NULL;
+ }
+ }
+ }
+#ifdef _DEBUG
+ else
+#ifdef MAXMSP
+ // in MaxMSP an object with the name of the library exists, even if not explicitely declared!
+ if(s != lib_name)
+#endif
+ error("Class %s not found in library!",s->s_name);
+#endif
+
+ return obj;
+}
+
+void flext_obj::obj_free(flext_hdr *hdr)
+{
+ const t_symbol *name = hdr->data->thisNameSym();
+ libname *l = libname::find(name);
+
+ if(l) {
+ // call virtual exit function
+ hdr->data->Exit();
+
+ // now call object destructor and deallocate
+ l->obj->freefun(hdr);
+ }
+#ifdef _DEBUG
+ else
+#ifdef MAXMSP
+ // in MaxMSP an object with the name of the library exists, even if not explicitely declared!
+ if(name != lib_name)
+#endif
+ error("Class %s not found in library!",name);
+#endif
+}
+
+
diff --git a/externals/grill/flext/source/flmspbuffer.h b/externals/grill/flext/source/flmspbuffer.h
new file mode 100755
index 00000000..4a8ffe69
--- /dev/null
+++ b/externals/grill/flext/source/flmspbuffer.h
@@ -0,0 +1,83 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flmspbuffer.h
+ \brief Definition of the Max/MSP buffer structure
+ \internal
+
+ This file comes from David Zicarellis inofficial package index.sit
+ The latter is not easily found so i included the original file buffer.h with flext
+*/
+
+#if defined(MAXMSP) && !defined(__FLEXT_MSPBUFFER_H)
+#define __FLEXT_MSPBUFFER_H
+
+enum {
+ MAXCHAN = 4
+};
+
+enum {
+ bi_basefreq = 0,
+ bi_detune,
+ bi_lowfreq,
+ bi_hifreq,
+ bi_lowvel,
+ bi_hivel,
+ bi_gain,
+ bi_numparams
+};
+
+typedef struct _buffer
+{
+ t_object b_obj; // doesn't have any signals so it doesn't need to be pxobject
+ long b_valid; // flag is off during read replacement or editing operation
+ float *b_samples; // stored with interleaved channels if multi-channel
+ long b_frames; // number of sample frames (each one is sizeof(float) * b_nchans bytes)
+ long b_nchans; // number of channels
+ long b_size; // size of buffer in floats
+ float b_sr; // sampling rate of the buffer
+ float b_1oversr; // 1 / sr
+ float b_msr; // sr * .001
+ // Mac-specific stuff
+ float *b_memory; // pointer to where memory starts (initial padding for interp)
+ t_symbol *b_name;
+ short b_vol;
+ short b_space;
+ // looping info (from AIFF file)
+ long b_susloopstart; // in samples
+ long b_susloopend; // in samples
+ long b_relloopstart; // in samples
+ long b_relloopend; // in samples
+ // instrument info (from AIFF file)
+ short b_inst[bi_numparams];
+ // window stuff
+ void *b_wind;
+ double b_pixperfr;
+ double b_frperpix;
+ long b_imagesize;
+ Point b_scroll;
+ long b_scrollscale;
+ long b_selbegin[MAXCHAN];
+ long b_selend[MAXCHAN];
+ long b_zoom;
+ long b_zim[11];
+ void *b_mouseout;
+ long b_format; // 'AIFF' or 'Sd2f'
+ t_symbol *b_filename; // last file read (not written) for readagain message
+ long b_oldnchans; // used for resizing window in case of # of channels change
+ void *b_doneout;
+ long b_outputbytes; // number of bytes used for output sample (1-4)
+ long b_modtime; // last modified time ("dirty" method)
+} t_buffer;
+
+#define BUFWIND(x) ((t_wind *)(x->b_wind))
+
+
+#endif
diff --git a/externals/grill/flext/source/flout.cpp b/externals/grill/flext/source/flout.cpp
new file mode 100644
index 00000000..3b7c6bd9
--- /dev/null
+++ b/externals/grill/flext/source/flout.cpp
@@ -0,0 +1,201 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flout.cpp
+ \brief Implementation of the flext outlet functionality.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+
+
+#ifdef MAXMSP
+#define CRITON() short state = lockout_set(1)
+#define CRITOFF() lockout_set(state)
+#else
+#define CRITON()
+#define CRITOFF()
+#endif
+
+#ifndef FLEXT_THREADS
+void flext_base::ToOutBang(outlet *o) { CRITON(); outlet_bang((t_outlet *)o); CRITOFF(); }
+void flext_base::ToOutFloat(outlet *o,float f) { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); }
+void flext_base::ToOutInt(outlet *o,int f) { CRITON(); outlet_flint((t_outlet *)o,f); CRITOFF(); }
+void flext_base::ToOutSymbol(outlet *o,const t_symbol *s) { CRITON(); outlet_symbol((t_outlet *)o,const_cast<t_symbol *>(s)); CRITOFF(); }
+void flext_base::ToOutList(outlet *o,int argc,const t_atom *argv) { CRITON(); outlet_list((t_outlet *)o,gensym("list"),argc,(t_atom *)argv); CRITOFF(); }
+void flext_base::ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { CRITON(); outlet_anything((t_outlet *)o,const_cast<t_symbol *>(s),argc,(t_atom *)argv); CRITOFF(); }
+#else
+void flext_base::ToOutBang(outlet *o) { if(IsSystemThread()) { CRITON(); outlet_bang((t_outlet *)o); CRITOFF(); } else ToQueueBang(o); }
+void flext_base::ToOutFloat(outlet *o,float f) { if(IsSystemThread()) { CRITON(); outlet_float((t_outlet *)o,f); CRITOFF(); } else ToQueueFloat(o,f); }
+void flext_base::ToOutInt(outlet *o,int f) { if(IsSystemThread()) { CRITON(); outlet_flint((t_outlet *)o,f); CRITOFF(); } else ToQueueInt(o,f); }
+void flext_base::ToOutSymbol(outlet *o,const t_symbol *s) { if(IsSystemThread()) { CRITON(); outlet_symbol((t_outlet *)o,const_cast<t_symbol *>(s)); CRITOFF(); } else ToQueueSymbol(o,s); }
+void flext_base::ToOutList(outlet *o,int argc,const t_atom *argv) { if(IsSystemThread()) { CRITON(); outlet_list((t_outlet *)o,gensym("list"),argc,(t_atom *)argv); CRITOFF(); } else ToQueueList(o,argc,(t_atom *)argv); }
+void flext_base::ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { if(IsSystemThread()) { CRITON(); outlet_anything((t_outlet *)o,const_cast<t_symbol *>(s),argc,(t_atom *)argv); CRITOFF(); } else ToQueueAnything(o,s,argc,(t_atom *)argv); }
+#endif
+
+
+class flext_base::qmsg
+{
+public:
+ qmsg(): nxt(NULL),tp(tp_none) {}
+ ~qmsg();
+
+ qmsg *nxt;
+
+ void Clear();
+
+ void SetBang(outlet *o) { Clear(); out = o; tp = tp_bang; }
+ void SetFloat(outlet *o,float f) { Clear(); out = o; tp = tp_float; _float = f; }
+ void SetInt(outlet *o,int i) { Clear(); out = o; tp = tp_int; _int = i; }
+ void SetSymbol(outlet *o,const t_symbol *s) { Clear(); out = o; tp = tp_sym; _sym = s; }
+ void SetList(outlet *o,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_list; _list.argc = argc,_list.argv = CopyList(argc,argv); }
+ void SetAny(outlet *o,const t_symbol *s,int argc,const t_atom *argv) { Clear(); out = o; tp = tp_any; _any.s = s,_any.argc = argc,_any.argv = CopyList(argc,argv); }
+
+ outlet *out;
+ enum { tp_none,tp_bang,tp_float,tp_int,tp_sym,tp_list,tp_any } tp;
+ union {
+ float _float;
+ int _int;
+ const t_symbol *_sym;
+ struct { int argc; t_atom *argv; } _list;
+ struct { const t_symbol *s; int argc; t_atom *argv; } _any;
+ };
+
+// void Add(qmsg *o);
+};
+
+flext_base::qmsg::~qmsg()
+{
+ Clear();
+ if(nxt) delete nxt;
+}
+
+void flext_base::qmsg::Clear()
+{
+ if(tp == tp_list) { if(_list.argv) delete[] _list.argv; }
+ else if(tp == tp_any) { if(_any.argv) delete[] _any.argv; }
+ tp = tp_none;
+}
+
+/*
+void flext_base::qmsg::Add(qmsg *o)
+{
+ if(nxt) nxt->Add(o);
+ else nxt = o;
+}
+*/
+
+void flext_base::QTick(flext_base *th)
+{
+#ifdef DEBUG
+ if(!th->IsSystemThread()) {
+ error("flext - Queue tick called by wrong thread!");
+ return;
+ }
+#endif
+
+#ifdef FLEXT_THREADS
+ th->qmutex.Lock();
+#endif
+ while(th->qhead) {
+ qmsg *m = th->qhead;
+
+#ifdef MAXMSP
+ short state = lockout_set(1);
+#endif
+
+ switch(m->tp) {
+ case qmsg::tp_bang: th->ToOutBang(m->out); break;
+ case qmsg::tp_float: th->ToOutFloat(m->out,m->_float); break;
+ case qmsg::tp_int: th->ToOutInt(m->out,m->_int); break;
+ case qmsg::tp_sym: th->ToOutSymbol(m->out,m->_sym); break;
+ case qmsg::tp_list: th->ToOutList(m->out,m->_list.argc,m->_list.argv); break;
+ case qmsg::tp_any: th->ToOutAnything(m->out,m->_any.s,m->_any.argc,m->_any.argv); break;
+#ifdef DEBUG
+ default: ERRINTERNAL();
+#endif
+ }
+
+#ifdef MAXMSP
+ lockout_set(state);
+#endif
+
+ th->qhead = m->nxt;
+ if(!th->qhead) th->qtail = NULL;
+ m->nxt = NULL;
+ delete m;
+ }
+#ifdef FLEXT_THREADS
+ th->qmutex.Unlock();
+#endif
+}
+
+void flext_base::Queue(qmsg *m)
+{
+#ifdef FLEXT_THREADS
+ qmutex.Lock();
+#endif
+ if(qtail) qtail->nxt = m;
+ else qhead = m;
+ qtail = m;
+#ifdef FLEXT_THREADS
+ qmutex.Unlock();
+#endif
+#ifdef PD
+ clock_delay(qclk,0);
+#elif defined(MAXMSP)
+ clock_delay(yclk,0);
+#else
+ #error "To implement!"
+#endif
+}
+
+void flext_base::ToQueueBang(outlet *o)
+{
+ qmsg *m = new qmsg();
+ m->SetBang(o);
+ Queue(m);
+}
+
+void flext_base::ToQueueFloat(outlet *o,float f)
+{
+ qmsg *m = new qmsg;
+ m->SetFloat(o,f);
+ Queue(m);
+}
+
+void flext_base::ToQueueInt(outlet *o,int f)
+{
+ qmsg *m = new qmsg;
+ m->SetInt(o,f);
+ Queue(m);
+}
+
+void flext_base::ToQueueSymbol(outlet *o,const t_symbol *s)
+{
+ qmsg *m = new qmsg;
+ m->SetSymbol(o,s);
+ Queue(m);
+}
+
+void flext_base::ToQueueList(outlet *o,int argc,const t_atom *argv)
+{
+ qmsg *m = new qmsg;
+ m->SetList(o,argc,argv);
+ Queue(m);
+}
+
+void flext_base::ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv)
+{
+ qmsg *m = new qmsg;
+ m->SetAny(o,s,argc,argv);
+ Queue(m);
+}
+
diff --git a/externals/grill/flext/source/flsndobj.cpp b/externals/grill/flext/source/flsndobj.cpp
new file mode 100644
index 00000000..1965b86b
--- /dev/null
+++ b/externals/grill/flext/source/flsndobj.cpp
@@ -0,0 +1,107 @@
+#include "flsndobj.h"
+
+//namespace flext {
+
+flext_sndobj::flext_sndobj():
+ inobjs(0),outobjs(0),
+ inobj(NULL),tmpobj(NULL),outobj(NULL),
+ smprt(0),blsz(0)
+{}
+
+flext_sndobj::~flext_sndobj()
+{
+ ClearObjs();
+}
+
+void flext_sndobj::ClearObjs()
+{
+ FreeObjs();
+
+ if(inobj) {
+ for(int i = 0; i < inobjs; ++i) { delete inobj[i]; delete tmpobj[i]; }
+ delete[] inobj; inobj = NULL;
+ delete[] tmpobj; tmpobj = NULL;
+ inobjs = 0;
+ }
+ if(outobj) {
+ for(int i = 0; i < outobjs; ++i) delete outobj[i];
+ delete[] outobj; outobj = NULL; outobjs = 0;
+ }
+}
+
+void flext_sndobj::m_dsp(int n,t_sample *const *in,t_sample *const *out)
+{
+ // called on every rebuild of the dsp chain
+
+ int i;
+ if(Blocksize() != blsz || Samplerate() != smprt) {
+ // block size or sample rate has changed... rebuild all objects
+
+ ClearObjs();
+
+ blsz = Blocksize();
+ smprt = Samplerate();
+
+ // set up sndobjs for inlets and outlets
+ inobj = new Inlet *[inobjs = CntInSig()];
+ tmpobj = new SndObj *[inobjs];
+ for(i = 0; i < inobjs; ++i) {
+ inobj[i] = new Inlet(in[i],blsz,smprt);
+ tmpobj[i] = new SndObj(NULL,blsz,smprt);
+ }
+ outobj = new Outlet *[outobjs = CntInSig()];
+ for(i = 0; i < outobjs; ++i) outobj[i] = new Outlet(out[i],blsz,smprt);
+
+ NewObjs();
+ }
+ else {
+ // assign changed input/output vectors
+
+ for(i = 0; i < inobjs; ++i) inobj[i]->SetBuf(in[i]);
+ for(i = 0; i < outobjs; ++i) outobj[i]->SetBuf(out[i]);
+ }
+}
+
+void flext_sndobj::m_signal(int n,t_sample *const *in,t_sample *const *out)
+{
+ for(int i = 0; i < inobjs; ++i) *tmpobj[i] << *inobj[i];
+ ProcessObjs();
+}
+
+
+flext_sndobj::Inlet::Inlet(const t_sample *b,int vecsz,float sr):
+ SndIO(1,sizeof(t_sample)*8,NULL,vecsz,sr),buf(b)
+{}
+
+short flext_sndobj::Inlet::Read()
+{
+ if(!m_error) {
+ for(m_vecpos = 0; m_vecpos < m_samples; m_vecpos++)
+ m_output[m_vecpos] = buf[m_vecpos];
+ return 1;
+ }
+ else return 0;
+}
+
+short flext_sndobj::Inlet::Write() { return 0; }
+
+
+flext_sndobj::Outlet::Outlet(t_sample *b,int vecsz,float sr):
+ SndIO(1,sizeof(t_sample)*8,NULL,vecsz,sr),buf(b)
+{}
+
+short flext_sndobj::Outlet::Read() { return 0; }
+
+short flext_sndobj::Outlet::Write()
+{
+ if(!m_error) {
+ if(m_IOobjs[0])
+ for(m_vecpos = 0; m_vecpos < m_samples; m_vecpos++)
+ buf[m_vecpos] = m_IOobjs[0]->Output(m_vecpos);
+ return 1;
+ }
+ else return 0;
+}
+
+//} // namespace flext
+
diff --git a/externals/grill/flext/source/flsndobj.h b/externals/grill/flext/source/flsndobj.h
new file mode 100644
index 00000000..f68054ed
--- /dev/null
+++ b/externals/grill/flext/source/flsndobj.h
@@ -0,0 +1,83 @@
+/*
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#ifndef FLEXT_SNDOBJ
+#define FLEXT_SNDOBJ
+
+#include "flext.h"
+#include <SndObj/AudioDefs.h>
+
+//namespace flext {
+
+class flext_sndobj:
+ public flext_dsp
+{
+ FLEXT_HEADER(flext_sndobj,flext_dsp)
+
+public:
+ flext_sndobj();
+ virtual ~flext_sndobj();
+
+ // these have to be overridden in child classes
+ virtual void NewObjs() {}
+ virtual void FreeObjs() {}
+ virtual void ProcessObjs() {}
+
+ // inputs and outputs
+ SndObj &InObj(int i) { return *tmpobj[i]; }
+ SndIO &OutObj(int i) { return *outobj[i]; }
+
+protected:
+ virtual void m_dsp(int n,t_sample *const *in,t_sample *const *out);
+ virtual void m_signal(int n,t_sample *const *in,t_sample *const *out);
+
+private:
+ //! SndObj for reading from inlet buffer
+ class Inlet:
+ public SndIO
+ {
+ public:
+ Inlet(const t_sample *b,int vecsz,float sr);
+ virtual short Read();
+ virtual short Write();
+
+ void SetBuf(const t_sample *b) { buf = b; }
+
+ private:
+ const t_sample *buf;
+ };
+
+ //! SndObj for writing to outlet buffer
+ class Outlet:
+ public SndIO
+ {
+ public:
+ Outlet(t_sample *b,int vecsz,float sr);
+ virtual short Read();
+ virtual short Write();
+
+ void SetBuf(t_sample *b) { buf = b; }
+
+ private:
+ t_sample *buf;
+ };
+
+ void ClearObjs();
+
+ int inobjs,outobjs;
+ SndObj **tmpobj;
+ Inlet **inobj;
+ Outlet **outobj;
+
+ float smprt;
+ int blsz;
+};
+
+//} // namespace flext
+
+#endif
diff --git a/externals/grill/flext/source/flstdc.h b/externals/grill/flext/source/flstdc.h
new file mode 100644
index 00000000..73ce613c
--- /dev/null
+++ b/externals/grill/flext/source/flstdc.h
@@ -0,0 +1,163 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flstdc.h
+ \brief Definitions to unite MaxMSP and PD notions
+
+ This file contains a few definitions to unite a few of the notions that
+ once drifted apart in Max and PD. It is not elegant but helps.
+*/
+
+#ifndef __FLEXT_STDC_H
+#define __FLEXT_STDC_H
+
+// Be sure that one target is defined
+#if !defined(PD) && !defined(MAXMSP)
+#error Either PD or MAXMSP must be defined
+#endif
+
+// Do some compiler checking
+#if defined(__MRC__) && __MRC__ < 0x500
+#error Apple MPW MrCpp v.5.0.0 or better compiler required
+#endif
+
+
+// PD stuff
+
+#ifdef PD
+
+/* PD definitions start here */
+
+#ifdef _MSC_VER
+#pragma warning (push)
+#pragma warning (disable:4091)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Include the relevant PD header files
+#ifdef _DEBUG
+#include <m_imp.h> // for easier debugging
+#else
+#include <m_pd.h>
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef _MSC_VER
+#pragma warning (pop)
+#endif
+
+typedef t_object t_sigobj;
+typedef t_gpointer *t_ptrtype;
+
+typedef t_float t_flint;
+typedef t_symbol *t_symptr;
+typedef t_symbol *t_symtype;
+typedef t_class **t_thing;
+
+typedef t_clock t_qelem;
+
+#define A_NOTHING A_NULL
+#define A_FLINT A_FLOAT
+#define A_DEFFLINT A_DEFFLOAT
+
+// MAX stuff
+#elif defined(MAXMSP)
+
+/* MaxMSP definitions start here */
+
+// Include the relevant MaxMSP header files
+extern "C"
+{
+#include "ext.h"
+//#include "ext_strings.h" // clashes with MPW
+#include "ext_user.h"
+#include "z_dsp.h"
+//#include "z_atom.h"
+}
+
+typedef t_pxbox t_sigobj; // that's the all-in-one object type of MaxMSP (not very memory-efficent, i guess)
+typedef t_patcher t_canvas;
+
+typedef t_int t_flint;
+typedef t_symbol *t_symptr;
+typedef t_symbol *t_symtype;
+typedef t_object *t_thing;
+
+typedef qelem t_qelem;
+
+typedef method t_method;
+typedef method t_newmethod;
+typedef int t_atomtype;
+
+typedef struct clock t_clock;
+typedef void t_binbuf;
+
+#undef clock_free
+#define clock_free(tick) freeobject((object *)tick)
+
+#define A_NULL A_NOTHING
+#define A_FLINT A_INT
+#define A_DEFFLINT A_DEFLONG
+
+#endif
+
+
+#ifdef _LOG
+
+/* If _LOG is defined implement logging */
+#define LOG(s) post(s)
+#define LOG1(s,v1) post(s,v1)
+#define LOG2(s,v1,v2) post(s,v1,v2)
+#define LOG3(s,v1,v2,v3) post(s,v1,v2,v3)
+#define LOG4(s,v1,v2,v3,v4) post(s,v1,v2,v3,v4)
+#define LOG5(s,v1,v2,v3,v4,v5) post(s,v1,v2,v3,v4,v5)
+
+
+#else
+
+/* If _LOG is not defined avoid logging */
+#define LOG(s) ((void)0)
+#define LOG1(s,v1) ((void)0)
+#define LOG2(s,v1,v2) ((void)0)
+#define LOG3(s,v1,v2,v3) ((void)0)
+#define LOG4(s,v1,v2,v3,v4) ((void)0)
+#define LOG5(s,v1,v2,v3,v4,v5) ((void)0)
+
+#endif
+
+#ifdef _DEBUG
+#define ASSERT(b) ((void)(!(b)?(error("Assertion failed: " #b " - in " __FILE__ " line %i",(int)__LINE__),0):0))
+#else
+#define ASSERT(b) ((void)0)
+#endif
+
+#define ERRINTERNAL() error("flext: Internal error in file " __FILE__ ", line %i - please report",(int)__LINE__)
+
+
+/* Set the right calling convention (and exporting) for the OS */
+
+#if defined(NT)
+#define FLEXT_EXT __declspec(dllexport)
+#else // other OS's
+#define FLEXT_EXT
+#endif
+
+#endif
+
+
+
+
+
diff --git a/externals/grill/flext/source/flsupport.cpp b/externals/grill/flext/source/flsupport.cpp
new file mode 100644
index 00000000..854fe871
--- /dev/null
+++ b/externals/grill/flext/source/flsupport.cpp
@@ -0,0 +1,58 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flsupport.cpp
+ \brief flext support functions and classes.
+*/
+
+#include "flsupport.h"
+
+const t_symbol *flext::sym_float = NULL;
+const t_symbol *flext::sym_symbol = NULL;
+const t_symbol *flext::sym_bang = NULL;
+const t_symbol *flext::sym_list = NULL;
+const t_symbol *flext::sym_anything = NULL;
+const t_symbol *flext::sym_pointer = NULL;
+const t_symbol *flext::sym_int = NULL;
+
+#ifdef PD
+const t_symbol *flext::sym_signal = NULL;
+#endif
+
+void flext::Setup()
+{
+#ifdef PD
+ sym_anything = &s_anything;
+ sym_pointer = &s_pointer;
+ sym_float = &s_float;
+ sym_symbol = &s_symbol;
+ sym_bang = &s_bang;
+ sym_list = &s_list;
+ sym_signal = &s_signal;
+#elif defined(MAXMSP)
+ sym_int = gensym("int");
+ sym_float = gensym("float");
+ sym_symbol = gensym("symbol");
+ sym_bang = gensym("bang");
+ sym_list = gensym("list");
+ sym_anything = gensym("anything");
+#endif
+}
+
+void flext::GetAString(const t_atom &a,char *buf,int szbuf)
+{
+#ifdef PD
+ atom_string(const_cast<t_atom *>(&a),buf,szbuf);
+#else
+ if(IsSymbol(a)) sprintf(buf,GetString(a));
+ else if(IsFloat(a)) sprintf(buf,"%f",GetFloat(a));
+ else if(IsInt(a)) sprintf(buf,"%i",GetInt(a));
+#endif
+}
diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h
new file mode 100644
index 00000000..148790ae
--- /dev/null
+++ b/externals/grill/flext/source/flsupport.h
@@ -0,0 +1,438 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flsupport.h
+ \brief flext support functions and classes
+*/
+
+#ifndef __FLSUPPORT_H
+#define __FLSUPPORT_H
+
+#include "flstdc.h"
+
+#ifdef FLEXT_THREADS
+#include <pthread.h>
+#endif
+
+class FLEXT_EXT flext {
+public:
+// --- buffer/array stuff -----------------------------------------
+
+ /*! \defgroup FLEXT_N_BUFFER Flext buffer handling
+
+ @{
+ */
+
+ //! Class for platform independent buffer handling
+ class buffer
+ {
+ public:
+ /*! \brief Construct buffer.
+ \param delayed = true: only sets name, needs another Set(NULL) to really initialize the buffer
+ \remark As externals can be created prior to the buffer objects they are pointing to, initialization should be done at loadbang!
+ */
+ buffer(const t_symbol *s = NULL,bool delayed = false);
+
+ //! Destroy buffer
+ ~buffer();
+
+ /*! \brief Check if the data is valid
+ */
+ bool Ok() const { return sym != NULL && data != NULL; }
+
+ /*! \brief Check and update if the buffer has been changed (e.g. resized)
+ */
+ bool Update();
+
+ /*! \brief Set to specified buffer.
+ \param nameonly: if true sets name only, but doesn't look at buffer actually
+ */
+ int Set(const t_symbol *s = NULL,bool nameonly = false);
+
+ /*! \brief Declare buffer content as dirty.
+ \param refr: if true forces immediate graphics refresh
+ */
+ void Dirty(bool refr = false);
+
+ //! Get symbol of buffer
+ t_symbol *Symbol() const { return const_cast<t_symbol *>(sym); }
+
+ //! Get literal name of buffer
+ const char *Name() const { return sym?sym->s_name:""; }
+
+ /*! \brief Get pointer to buffer, channel and frame count.
+ \remark Channels are interleaved
+ */
+ t_sample *Data() { return data; }
+
+ //! Get channel count
+ int Channels() const { return chns; }
+ //! Get frame count
+ int Frames() const { return frames; }
+ //! Set frame count
+ void Frames(int fr,bool keep = false);
+
+ //! Graphic auto refresh interval
+ void SetRefrIntv(float intv);
+
+ protected:
+ const t_symbol *sym;
+ t_sample *data;
+ int chns,frames;
+#ifdef PD
+ t_garray *arr;
+ float interval;
+ bool isdirty,ticking;
+ t_clock *tick;
+
+ private:
+ static void cb_tick(buffer *b);
+#endif
+ };
+
+//! @}
+
+// --- various symbols --------------------------------------------
+
+ /*! \defgroup FLEXT_N_SYMBOL Flext atom/symbol handling
+
+ @{
+ */
+
+ //! Symbol constant for "float"
+ static const t_symbol *sym_float;
+ //! Symbol constant for "symbol"
+ static const t_symbol *sym_symbol;
+ //! Symbol constant for "bang"
+ static const t_symbol *sym_bang;
+ //! Symbol constant for "list"
+ static const t_symbol *sym_list;
+ //! Symbol constant for "anything"
+ static const t_symbol *sym_anything;
+
+ /*! \brief Symbol constant for "int"
+ \note Only the Max/MSP system has this defined as an internal type
+ */
+ static const t_symbol *sym_int;
+
+ /*! Symbol constant for "pointer"
+ \note Only PD has this defined as an internal type
+ */
+ static const t_symbol *sym_pointer;
+
+#ifdef PD
+
+ /*! \brief Symbol constant for "signal"
+ \note PD only
+ */
+ static const t_symbol *sym_signal;
+#endif
+
+ //! Make a symbol from a string
+ static const t_symbol *MakeSymbol(const char *s) { return gensym(const_cast<char *>(s)); }
+
+ //! Get symbol string
+ static const char *GetString(const t_symbol *s) { return s->s_name; }
+ //! Check for symbol and get string
+ static const char *GetAString(const t_symbol *s) { return s?s->s_name:""; }
+
+//! @}
+
+// --- utilities --------------------------------------------------
+
+ /*! \defgroup FLEXT_C_UTIL Flext utility functions
+
+ @{
+ */
+
+ //! Copy an atom
+ static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
+
+ //! Copy a list of atoms
+ static t_atom *CopyList(int argc,const t_atom *argv);
+ //! Copy a memory region
+ static void CopyMem(void *dst,const void *src,int bytes);
+ //! Sleep for an amount of time
+ static void Sleep(float s);
+
+//! @}
+
+// --- atom stuff ----------------------------------------
+
+ //! Set atom from another atom
+ static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
+
+ //! Check whether the atom is nothing
+ static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
+ //! Set the atom to represent nothing
+ static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
+
+ //! Check whether the atom is a float
+ static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
+ //! Check whether the atom can be represented as a float
+ static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+ //! Access the float value (without type check)
+ static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
+ //! Set the atom to represent a float
+ static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
+
+ //! Check whether the atom is a symbol
+ static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
+ //! Access the symbol value (without type check)
+ static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_symbol; }
+ //! Check for a symbol and get its value
+ static t_symbol *GetASymbol(const t_atom &a) { return IsSymbol(a)?GetSymbol(a):NULL; } // NULL or empty symbol?
+ //! Set the atom to represent a symbol
+ static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast<t_symbol *>(s); }
+
+ //! Check whether the atom is a string
+ static bool IsString(const t_atom &a) { return IsSymbol(a); }
+ //! Access the string value (without type check)
+ static const char *GetString(const t_atom &a) { t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
+ //! Check for a string and get its value
+ static void GetAString(const t_atom &a,char *buf,int szbuf);
+ //! Set the atom to represent a string
+ static void SetString(t_atom &a,const char *c) { SetSymbol(a,gensym(const_cast<char *>(c))); }
+
+ //! Check whether the atom can be represented as an integer
+ static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
+
+ //! Check whether the atom can be represented as a boolean
+ static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
+ //! Check for an boolean and get its value
+ static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
+
+#ifdef PD
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):0; }
+
+ //! Check whether the atom is an integer
+ static bool IsInt(const t_atom &) { return false; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a) { return (int)GetAFloat(a); }
+ //! Set the atom to represent a integer (depending on the system)
+ static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
+
+ //! Check whether the atom is a pointer
+ static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
+ //! Access the pointer value (without type check)
+ static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
+ //! Check for a pointer and get its value
+ static t_gpointer *GetAPointer(const t_atom &a) { return IsPointer(a)?GetPointer(a):NULL; }
+ //! Set the atom to represent a pointer
+ static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = p; }
+
+#elif defined(MAXMSP)
+ //! Check for a float and get its value
+ static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):0); }
+
+ //! Check whether the atom is an int
+ static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
+ //! Access the integer value (without type check)
+ static int GetInt(const t_atom &a) { return a.a_w.w_long; }
+ //! Check for an integer and get its value
+ static int GetAInt(const t_atom &a) { return IsInt(a)?GetInt(a):(IsFloat(a)?GetFloat(a):0); }
+ //! Set the atom to represent an integer
+ static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
+
+ //! Check whether the atom is a pointer
+ static bool IsPointer(const t_atom &) { return false; }
+ //! Access the pointer value (without type check)
+ static void *GetPointer(const t_atom &) { return NULL; }
+ //! Check for a pointer and get its value
+ static void *GetAPointer(const t_atom &) { return NULL; }
+// void SetPointer(t_atom &,void *) {}
+#endif
+
+// --- atom list stuff -------------------------------------------
+
+ /*! \defgroup FLEXT_N_ATOM Flext atom/list handling
+
+ @{
+ */
+
+ //! Class representing a list of atoms
+ class AtomList
+ {
+ public:
+ //! Construct list
+ AtomList(int argc = 0,const t_atom *argv = NULL);
+ //! Construct list
+ AtomList(const AtomList &a);
+ //! Destroy list
+ ~AtomList();
+
+ //! Clear list
+ AtomList &Clear() { return operator()(); }
+
+ //! Set list
+ AtomList &operator()(int argc = 0,const t_atom *argv = NULL);
+ //! Set list by another AtomList
+ AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
+
+ //! Get number of atoms in the list
+ int Count() const { return cnt; }
+ //! Get a reference to an indexed atom
+ t_atom &operator [](int ix) { return lst[ix]; }
+ //! Get a reference to an indexed atom
+ const t_atom &operator [](int ix) const { return lst[ix]; }
+
+ //! Get a pointer to the list of atoms
+ t_atom *Atoms() { return lst; }
+ //! Get a pointer to the list of atoms
+ const t_atom *Atoms() const { return lst; }
+
+ //! Append an atom to the list
+ AtomList &Append(const t_atom &a);
+ //! Append an atom list to the list
+ AtomList &Append(int argc,const t_atom *argv);
+ //! Append an atom list to the list
+ AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
+ //! Prepend an atom to the list
+ AtomList &Prepend(const t_atom &a);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(int argc,const t_atom *argv);
+ //! Prepend an atom list to the list
+ AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
+
+ //! Get a part of the list
+ AtomList GetPart(int offs,int len) const;
+ //! Set to a part of the list
+ AtomList &Part(int offs,int len) { return (*this = GetPart(offs,len)); }
+
+ protected:
+ int cnt;
+ t_atom *lst;
+ };
+
+
+ //! Class representing an "anything"
+ class AtomAnything:
+ public AtomList
+ {
+ public:
+ //! Construct anything
+ AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(h) {}
+ //! Construct anything
+ AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(MakeSymbol(h)) {}
+ //! Construct anything
+ AtomAnything(const AtomAnything &a): AtomList(a),hdr(a.hdr) {}
+
+ //! Clear anything
+ AtomAnything &Clear() { return operator()(); }
+
+ //! Get header symbol of anything
+ const t_symbol *Header() const { return hdr; }
+
+ //! Set anything
+ AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
+ {
+ hdr = h; AtomList::operator()(argc,argv);
+ return *this;
+ }
+
+ //! Set list by another AtomAnything
+ AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
+
+ protected:
+ const t_symbol *hdr;
+ };
+
+//! @}
+
+// --- clock stuff ------------------------------------------------
+
+
+ /*! \defgroup FLEXT_N_CLOCK Flext clock functions
+
+ At the moment there are none
+
+ @{
+ */
+
+//! @}
+
+
+// --- thread stuff -----------------------------------------------
+
+#ifdef FLEXT_THREADS
+ /*! \defgroup FLEXT_N_THREAD Flext thread handling
+
+ @{
+ */
+
+ /*! \brief Thread mutex
+ \sa pthreads documentation
+ */
+ class ThrMutex
+ {
+ public:
+ //! Construct thread mutex
+ ThrMutex(): cnt(0) { pthread_mutex_init(&mutex,NULL); }
+ //! Destroy thread mutex
+ ~ThrMutex() { pthread_mutex_destroy(&mutex); }
+
+ //! Lock thread mutex
+ int Lock() { cnt = 1; return pthread_mutex_lock(&mutex); }
+ //! Try to lock, but don't wait
+ int TryLock() { return pthread_mutex_trylock(&mutex); }
+ //! Unlock thread mutex
+ int Unlock() { cnt = 0; return pthread_mutex_unlock(&mutex); }
+
+ //! Lock thread mutex (increase lock count by one)
+ void Push() { if(!cnt++) Lock(); }
+ //! Unlock thread mutex if lock count reaches zero
+ void Pop() { if(!--cnt) Unlock(); }
+ protected:
+ pthread_mutex_t mutex;
+ int cnt;
+ };
+
+ /*! \brief Thread conditional
+ \sa pthreads documentation
+ */
+ class ThrCond:
+ public ThrMutex
+ {
+ public:
+ //! Construct thread conditional
+ ThrCond() { pthread_cond_init(&cond,NULL); }
+ //! Destroy thread conditional
+ ~ThrCond() { pthread_cond_destroy(&cond); }
+
+ //! Wait for condition
+ int Wait() { return pthread_cond_wait(&cond,&mutex); }
+
+ /*! \brief Wait for condition (for a certain time)
+ \param time Wait time in seconds
+ */
+ int TimedWait(float time)
+ {
+ timespec tm; tm.tv_sec = (long)time; tm.tv_nsec = (long)((time-(long)time)*1.e9);
+ return pthread_cond_timedwait(&cond,&mutex,&tm);
+ }
+
+ //! Signal condition
+ int Signal() { return pthread_cond_signal(&cond); }
+ //! Broadcast condition
+ int Broadcast() { return pthread_cond_broadcast(&cond); }
+ protected:
+ pthread_cond_t cond;
+ };
+//! @}
+#endif // FLEXT_THREADS
+
+protected:
+ static void Setup();
+};
+
+#endif
diff --git a/externals/grill/flext/source/flthr.cpp b/externals/grill/flext/source/flthr.cpp
new file mode 100644
index 00000000..fd780a1c
--- /dev/null
+++ b/externals/grill/flext/source/flthr.cpp
@@ -0,0 +1,237 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flthr.cpp
+ \brief Implementation of the flext thread functionality.
+*/
+
+#ifdef FLEXT_THREADS
+
+#include "flext.h"
+#include "flinternal.h"
+
+#ifdef MAXMSP
+#define SCHEDTICK 1
+#endif
+
+#ifdef NT
+#include <windows.h>
+#endif
+#include <errno.h>
+
+bool flext_base::StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname)
+{
+ static bool init = false;
+ static pthread_attr_t attr;
+#ifdef _DEBUG
+ if(!p) {
+ ERRINTERNAL();
+ return false;
+ }
+#endif
+ if(!init) {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
+ init = true;
+ }
+
+ // set thread priority one point below normal
+ // so thread construction won't disturb real-time audio
+ pthread_t id = pthread_self();
+ sched_param parm;
+ int policy;
+ pthread_getschedparam(id,&policy,&parm);
+ int prio = parm.sched_priority;
+ int schmin = sched_get_priority_min(policy);
+ if(prio > schmin) {
+ parm.sched_priority = prio-1;
+ pthread_setschedparam(id,policy,&parm);
+ }
+
+ pthread_t thrid;
+ int ret = pthread_create (&thrid,&attr,(void *(*)(void *))meth,p);
+
+ // set thread priority back to normal
+ parm.sched_priority = prio;
+ pthread_setschedparam(id,policy,&parm);
+
+ if(ret) {
+#ifdef _DEBUG
+ error((char *)(ret == EAGAIN?"%s - Unsufficient resources to launch thread!":"%s - Could not launch method!"),methname);
+#endif
+ delete p;
+ return false;
+ }
+ else {
+#ifdef MAXMSP
+ sched_yield();
+#endif
+ return true;
+ }
+}
+
+bool flext_base::PushThread()
+{
+ tlmutex.Lock();
+
+ // make an entry into thread list
+ thr_entry *nt = new thr_entry;
+ if(thrtail) thrtail->nxt = nt;
+ else thrhead = nt;
+ thrtail = nt;
+
+ {
+#ifdef NT
+ // set detached thread to lower priority class
+ DWORD err;
+ HANDLE thr = GetCurrentThread();
+ DWORD cl = GetThreadPriority(thr);
+ if(!cl && (err = GetLastError()))
+ post("flext - error getting thread priority");
+ else {
+ BOOL ret = SetThreadPriority(thr,cl-2);
+ if(!ret) {
+ err = GetLastError();
+ if(!err) post("flext - error setting thread priority");
+ }
+ }
+#else
+ // set initial detached thread priority two points below normal
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(nt->thrid,&policy,&parm))
+ post("flext - can't get thread parameters");
+ int prio = parm.sched_priority;
+ int schmin = sched_get_priority_min(policy);
+ if(prio > schmin) {
+ parm.sched_priority = prio-2;
+ if(pthread_setschedparam(nt->thrid,policy,&parm))
+ post("flext - can't set thread parameters");
+ }
+#endif
+ }
+
+ tlmutex.Unlock();
+
+#ifdef MAXMSP
+ clock_delay(yclk,0);
+#endif
+ return true;
+}
+
+void flext_base::PopThread()
+{
+ tlmutex.Lock();
+
+ pthread_t id = pthread_self();
+
+ thr_entry *prv = NULL,*ti;
+ for(ti = thrhead; ti; prv = ti,ti = ti->nxt)
+ if(ti->Is()) break;
+
+ if(ti) {
+ if(prv)
+ prv->nxt = ti->nxt;
+ else
+ thrhead = ti->nxt;
+ if(thrtail == ti) thrtail = prv;
+
+ ti->nxt = NULL;
+ delete ti;
+ }
+ else {
+#ifdef _DEBUG
+ post("%s - INTERNAL ERROR: Thread not found!",thisName());
+#endif
+ }
+
+ tlmutex.Unlock();
+}
+
+#ifdef MAXMSP
+void flext_base::YTick(flext_base *th)
+{
+ clock_delay(th->yclk,0);
+ qelem_set(th->qclk);
+ sched_yield();
+}
+#endif
+
+flext_base::thrid_t flext_base::GetThreadId()
+{
+ return pthread_self();
+}
+
+bool flext_base::ChangePriority(int dp,thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return false;
+ }
+ else {
+ parm.sched_priority += dp;
+ if(pthread_setschedparam(id,policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to change priority");
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+
+
+int flext_base::GetPriority(thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return -1;
+ }
+ return parm.sched_priority;
+}
+
+
+bool flext_base::SetPriority(int p,thrid_t id)
+{
+ sched_param parm;
+ int policy;
+ if(pthread_getschedparam(id,&policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to get parms");
+#endif
+ return false;
+ }
+ else {
+ parm.sched_priority = p;
+ if(pthread_setschedparam(id,policy,&parm) < 0) {
+#ifdef _DEBUG
+ post("flext - failed to change priority");
+#endif
+ return false;
+ }
+ }
+ return true;
+}
+
+flext_base::thr_params::thr_params(flext_base *c,int n): cl(c),var(new _data[n]) {}
+flext_base::thr_params::~thr_params() { if(var) delete[] var; }
+
+void flext_base::thr_params::set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any.args = new AtomAnything(s,argc,argv); }
+void flext_base::thr_params::set_list(int argc,const t_atom *argv) { var[0]._list.args = new AtomList(argc,argv); }
+
+#endif // FLEXT_THREADS
diff --git a/externals/grill/flext/source/flutil.cpp b/externals/grill/flext/source/flutil.cpp
new file mode 100644
index 00000000..509c3ab4
--- /dev/null
+++ b/externals/grill/flext/source/flutil.cpp
@@ -0,0 +1,68 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flutil.cpp
+ \brief Implementation of the various utility functions.
+*/
+
+#include "flext.h"
+#include <string.h>
+
+#ifdef NT
+#include <windows.h>
+#endif
+
+#ifdef MAXMSP
+#include <Timer.h>
+#include <Threads.h>
+#endif
+
+#ifdef unix
+#include <unistd.h>
+#endif
+
+//namespace flext {
+
+t_atom *flext::CopyList(int argc,const t_atom *argv)
+{
+ int i;
+ t_atom *dst = new t_atom[argc];
+ for(i = 0; i < argc; ++i) CopyAtom(dst+i,argv+i);
+ return dst;
+}
+
+void flext::CopyMem(void *dst,const void *src,int bytes)
+{
+#ifdef macintosh
+ BlockMoveData(src,dst,bytes);
+#else
+ memcpy(dst,src,bytes);
+#endif
+}
+
+void flext::Sleep(float s)
+{
+#ifdef NT
+ ::Sleep((long)(s*1000));
+#elif defined MAXMSP
+ UnsignedWide tick;
+ Microseconds(&tick);
+ double target = tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo+s*1.e6;
+ for(;;) {
+ Microseconds(&tick);
+ if(target <= tick.hi*((double)(1L<<((sizeof tick.lo)*4))*(double)(1L<<((sizeof tick.lo)*4)))+tick.lo) break;
+ YieldToAnyThread(); // should we really yield?
+ }
+#else
+ usleep((long)(s*1000000));
+#endif
+}
+
+//} // namespace flext
diff --git a/externals/grill/flext/source/flxlet.cpp b/externals/grill/flext/source/flxlet.cpp
new file mode 100755
index 00000000..881769da
--- /dev/null
+++ b/externals/grill/flext/source/flxlet.cpp
@@ -0,0 +1,88 @@
+/*
+
+flext - C++ layer for Max/MSP and pd (pure data) externals
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+/*! \file flxlet.cpp
+ \brief Implementation of the variable inlet/outlet functionality.
+*/
+
+#include "flext.h"
+#include "flinternal.h"
+#include <string.h>
+#include <stdarg.h>
+
+//namespace flext {
+
+flext_base::xlet::xlet(type t,const char *d):
+ tp(t),nxt(NULL)
+{
+ if(d) {
+ int ln = strlen(d);
+ desc = new char[ln];
+ strncpy(desc,d,ln);
+ }
+ else desc = NULL;
+}
+
+flext_base::xlet::~xlet()
+{
+ if(desc) delete[] desc;
+ if(nxt) delete nxt;
+}
+
+void flext_base::AddXlet(xlet::type tp,int mult,const char *desc,xlet *&root)
+{
+ if(!root && mult) { root = new xlet(tp,desc); --mult; }
+ if(mult) {
+ xlet *xi = root;
+ while(xi->nxt) xi = xi->nxt;
+ while(mult--) xi = xi->nxt = new xlet(tp,desc);
+ }
+}
+
+void flext_base::DescXlet(int ix,const char *desc,xlet *&root)
+{
+ post("%s - sorry, not implemented",thisName());
+}
+
+unsigned long flext_base::XletCode(xlet::type tp,...)
+{
+ unsigned long code = 0;
+
+ va_list marker;
+ va_start(marker,tp);
+ int cnt = 0;
+ xlet::type *args = NULL,arg = tp;
+ for(; arg; ++cnt) {
+#ifdef _DEBUG
+ if(cnt > 9) {
+ error("%s - Too many in/outlets defined - truncated to 9",thisName());
+ break;
+ }
+#endif
+
+ code = code*10+(int)arg;
+ arg = (xlet::type)va_arg(marker,int);
+ }
+ va_end(marker);
+
+ return code;
+}
+
+void flext_base::AddInlets(unsigned long code)
+{
+ for(; code; code /= 10) AddInlet((xlet::type)(code%10));
+}
+
+void flext_base::AddOutlets(unsigned long code)
+{
+ for(; code; code /= 10) AddOutlet((xlet::type)(code%10));
+}
+
+//} // namespace flext
diff --git a/externals/grill/flext/tutorial/adv1/adv1.cw b/externals/grill/flext/tutorial/adv1/adv1.cw
new file mode 100755
index 00000000..bd68d0e8
--- /dev/null
+++ b/externals/grill/flext/tutorial/adv1/adv1.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/adv1/adv1.dsp b/externals/grill/flext/tutorial/adv1/adv1.dsp
new file mode 100644
index 00000000..8917c44e
--- /dev/null
+++ b/externals/grill/flext/tutorial/adv1/adv1.dsp
@@ -0,0 +1,96 @@
+# Microsoft Developer Studio Project File - Name="adv1" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=adv1 - 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 "adv1.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 "adv1.mak" CFG="adv1 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "adv1 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "adv1 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "adv1"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "adv1 - 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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../msvc/adv1.dll" /libpath:"..\..\pd-msvc"
+# SUBTRACT LINK32 /nodefaultlib
+
+!ELSEIF "$(CFG)" == "adv1 - 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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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 "adv1 - Win32 Release"
+# Name "adv1 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/adv1/main.cpp b/externals/grill/flext/tutorial/adv1/main.cpp
new file mode 100755
index 00000000..f59ebddd
--- /dev/null
+++ b/externals/grill/flext/tutorial/adv1/main.cpp
@@ -0,0 +1,104 @@
+/*
+flext tutorial - advanced 1
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This is an example of a simplified prepend object
+*/
+
+#include <flext.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 400)
+#error You need at least flext version 0.4.0
+#endif
+
+
+class adv1:
+ public flext_base
+{
+ FLEXT_HEADER(adv1,flext_base)
+
+public:
+ // constructor with variable argument list
+ adv1(int argc,t_atom *argv);
+
+protected:
+ void m_any(const t_symbol *s,int argc,t_atom *argv); // method which digests anything
+
+ AtomList lst;
+private:
+ FLEXT_CALLBACK_A(m_any); // callback for method "m_any" (with anything argument)
+};
+
+// instantiate the class (constructor has a variable argument list)
+// note the two words in the string: prepend acts as an alias for adv1!
+FLEXT_NEW_V("adv1 prepend",adv1)
+
+
+
+// constructor
+
+adv1::adv1(int argc,t_atom *argv)
+{
+ AddInAnything(); // one inlet that can receive anything
+ AddOutAnything(); // one outlet for anything
+
+ // set up inlets and outlets
+ SetupInOut();
+
+ // register method
+ FLEXT_ADDMETHOD(0,m_any); // register method "m_any" for inlet 0
+
+ if(argc != 0) { // check for arg count
+ // store arg list
+ lst(argc,argv);
+ }
+ else {
+ // no args given
+ post("%s - no arguments given",thisName());
+
+ // tell flext that the initialization was not successful... object will not live
+ InitProblem();
+ }
+}
+
+
+
+// method
+
+void adv1::m_any(const t_symbol *s,int argc,t_atom *argv)
+{
+ // reserve space for as many atoms as possibly necessary
+ AtomList result(lst.Count()+argc+2);
+
+ // ix is our counter of atoms to output
+ int ix = 0;
+
+ int i = 0;
+ if(!IsSymbol(lst[0])) {
+ // if first element to prepend is no symbol then make it a "list"
+ SetSymbol(result[ix++],sym_list);
+ }
+ // copy atoms to prepend to result list
+ for(; i < lst.Count(); ++i) CopyAtom(&result[ix++],&lst[i]);
+
+ // if anything is no "list" or "float" then append it to result list
+ if(s != sym_list && s != sym_float
+#ifdef MAXMSP
+ && s != sym_int // in Max integers are system data types
+#endif
+ )
+ SetSymbol(result[ix++],s);
+
+ // append pending arguments to result list
+ for(i = 0; i < argc; ++i) CopyAtom(&result[ix++],argv+i);
+
+ // output result list as an anything
+ ToOutAnything(0,GetSymbol(result[0]),ix-1,result.Atoms()+1);
+}
+
+
diff --git a/externals/grill/flext/tutorial/build-pd-bcc.bat b/externals/grill/flext/tutorial/build-pd-bcc.bat
new file mode 100644
index 00000000..5a8e8a57
--- /dev/null
+++ b/externals/grill/flext/tutorial/build-pd-bcc.bat
@@ -0,0 +1,27 @@
+@echo --- Building flext tutorial examples with BorlandC++ ---
+
+@cd simple1
+@make -f ..\makefile.pd-bcc NAME=simple1 SETUPFUNCTION=simple1_setup
+@cd ..
+
+@cd simple2
+@make -f ..\makefile.pd-bcc NAME=simple2 SETUPFUNCTION=simple2_setup
+@cd ..
+
+@cd simple3
+@make -f ..\makefile.pd-bcc NAME=simple3 SETUPFUNCTION=simple3_setup
+@cd ..
+
+@cd adv1
+@make -f ..\makefile.pd-bcc NAME=adv1 SETUPFUNCTION=adv1_setup
+@cd ..
+
+@cd signal1
+@make -f ..\makefile.pd-bcc NAME=signal1~ SETUPFUNCTION=signal1_tilde_setup
+@cd ..
+
+@cd signal2
+@make -f ..\makefile.pd-bcc NAME=signal2~ SETUPFUNCTION=signal2_tilde_setup
+@cd ..
+
+
diff --git a/externals/grill/flext/tutorial/build-pd-cygwin.sh b/externals/grill/flext/tutorial/build-pd-cygwin.sh
new file mode 100644
index 00000000..1c34954a
--- /dev/null
+++ b/externals/grill/flext/tutorial/build-pd-cygwin.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+make -f makefile.pd-cygwin
diff --git a/externals/grill/flext/tutorial/build-pd-linux.sh b/externals/grill/flext/tutorial/build-pd-linux.sh
new file mode 100644
index 00000000..bd11c6c4
--- /dev/null
+++ b/externals/grill/flext/tutorial/build-pd-linux.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+make -f makefile.pd-linux
+
diff --git a/externals/grill/flext/tutorial/build-pd-msvc.bat b/externals/grill/flext/tutorial/build-pd-msvc.bat
new file mode 100644
index 00000000..f6eb9625
--- /dev/null
+++ b/externals/grill/flext/tutorial/build-pd-msvc.bat
@@ -0,0 +1,11 @@
+@echo --- Building flext tutorial examples with MSVC++ ---
+
+nmake /f makefile.pd-msvc NAME=simple1 DIR=simple1
+nmake /f makefile.pd-msvc NAME=simple2 DIR=simple2
+nmake /f makefile.pd-msvc NAME=simple3 DIR=simple3
+nmake /f makefile.pd-msvc NAME=adv1 DIR=adv1
+nmake /f makefile.pd-msvc NAME=signal1~ DIR=signal1
+nmake /f makefile.pd-msvc NAME=signal2~ DIR=signal2
+nmake /f makefile.pd-msvc NAME=thread1 DIR=thread1
+nmake /f makefile.pd-msvc NAME=thread2 DIR=thread2
+
diff --git a/externals/grill/flext/tutorial/config-pd-bcc.txt b/externals/grill/flext/tutorial/config-pd-bcc.txt
new file mode 100644
index 00000000..2ce2b2c3
--- /dev/null
+++ b/externals/grill/flext/tutorial/config-pd-bcc.txt
@@ -0,0 +1,21 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# tutorial examples
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=c:\programme\audio\pd
+
+# where is BorlandC++?
+BCCPATH=c:\programme\prog\bcc55
+
+# where do the flext libraries reside?
+FLEXTPATH=$(PDPATH)\flext
+
+# build directory for tutorial examples
+OUTPATH=.\pd-bcc
+
+
+
+
+
diff --git a/externals/grill/flext/tutorial/config-pd-cygwin.txt b/externals/grill/flext/tutorial/config-pd-cygwin.txt
new file mode 100644
index 00000000..a2ccf30c
--- /dev/null
+++ b/externals/grill/flext/tutorial/config-pd-cygwin.txt
@@ -0,0 +1,13 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# tutorial examples
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=/cygdrive/c/programme/audio/pd
+
+# where do the flext libraries reside?
+FLEXTPATH=${PDPATH}/flext
+
+# where should the examples be built?
+OUTPATH=./pd-cygwin
diff --git a/externals/grill/flext/tutorial/config-pd-linux.txt b/externals/grill/flext/tutorial/config-pd-linux.txt
new file mode 100644
index 00000000..3cfb4a9f
--- /dev/null
+++ b/externals/grill/flext/tutorial/config-pd-linux.txt
@@ -0,0 +1,19 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# tutorial examples
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where are the PD header files?
+PDPATH=/usr/local/include
+
+# where do the flext libraries reside?
+FLEXTPATH=/usr/local/lib/pd/flext
+
+# where should the examples be built? (relative path)
+OUTPATH=./pd-linux
+
+# install the examples? (yes/no)
+INSTALL=yes
+
+# where should the examples be installed?
+INSTPATH=${FLEXTPATH}/tutorial
diff --git a/externals/grill/flext/tutorial/config-pd-msvc.txt b/externals/grill/flext/tutorial/config-pd-msvc.txt
new file mode 100644
index 00000000..b68fdadb
--- /dev/null
+++ b/externals/grill/flext/tutorial/config-pd-msvc.txt
@@ -0,0 +1,16 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# tutorial examples
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+
+# where is PD?
+PDPATH=c:\programme\audio\pd
+
+# where is MS VC++?
+MSVCPATH=c:\programme\prog\microsoft visual studio\VC98
+
+# where do the flext libraries reside?
+FLEXTPATH=$(PDPATH)\flext
+
+# where should the examples be built?
+OUTPATH=.\pd-msvc
diff --git a/externals/grill/flext/tutorial/gpl.txt b/externals/grill/flext/tutorial/gpl.txt
new file mode 100755
index 00000000..5ea29a7d
--- /dev/null
+++ b/externals/grill/flext/tutorial/gpl.txt
@@ -0,0 +1,346 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+
diff --git a/externals/grill/flext/tutorial/license.txt b/externals/grill/flext/tutorial/license.txt
new file mode 100755
index 00000000..f0d1a975
--- /dev/null
+++ b/externals/grill/flext/tutorial/license.txt
@@ -0,0 +1,50 @@
+flext - C++ layer for Max/MSP and pd (pure data) externals
+Copyright (C) 2001,2002 Thomas Grill
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+In the official flext distribution, the GNU General Public License is
+in the file gpl.txt
+
+---------------------------------------------------------
+
+ OTHER COPYRIGHT NOTICES
+
+---------------------------------------------------------
+This package uses a lot of code from GEM by Mark Danks
+
+See the license text below:
+
+--- GEM --------------------------------------
+GEM - Graphics Environment for Multimedia
+Copyright (C) 1997-2000 Mark Danks
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+In the official GEM distribution, the GNU General Public License is
+in the file GnuGPL.LICENSE
+
diff --git a/externals/grill/flext/tutorial/makefile.pd-bcc b/externals/grill/flext/tutorial/makefile.pd-bcc
new file mode 100644
index 00000000..1e718176
--- /dev/null
+++ b/externals/grill/flext/tutorial/makefile.pd-bcc
@@ -0,0 +1,75 @@
+# flext tutorial examples
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# This is a make include file for BorlandC++
+# It can't be used on its own
+#
+# ---------------------------------------------
+
+!include ..\config-pd-bcc.txt
+
+OUTPATH=..\$(OUTPATH)
+
+TARGET=pdwin
+
+# includes, libs
+INCPATH=-I$(BCCPATH)\include -I$(PDPATH)\src -I$(FLEXTPATH)
+LIBPATH=-L$(BCCPATH)\lib -L$(PDPATH)\lib -L$(FLEXTPATH)
+LIBS=cw32.lib import32.lib C0D32.OBJ
+
+# compiler definitions and flags
+DEFS=-DPD -DNT
+CFLAGS=-6 -O2 -OS -ff -tWD
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+SRCS= main.cpp
+HDRS=
+
+#default target
+all: $(OUTPATH)\$(NAME).dll
+
+# remove build
+clean:
+ -del /s /q $(OUTPATH) > nul
+ rmdir $(OUTPATH)
+
+# -----------------------------------------------
+
+OBJS= $(SRCS:.cpp=.obj)
+
+$(SRCS): $(HDRS)
+ -touch $<
+
+.PATH.OBJ=$(OUTPATH)
+
+.cpp.obj:
+ bcc32 -c $(CFLAGS) $(DEFS) $(INCPATH) -n$(OUTPATH) $<
+
+$(OUTPATH):
+ -@if not exist $< mkdir $<
+
+$(OUTPATH)\pd.lib: $(PDPATH)\bin\pd.dll
+ implib -a $@ $**
+
+$(OUTPATH)\$(NAME).def:
+ @echo EXPORTS $(SETUPFUNCTION) = _$(SETUPFUNCTION) > $<
+
+$(OUTPATH)\$(NAME)~.dll : $(OUTPATH)\$(NAME).dll
+ -ren $** $<
+
+$(OUTPATH)\$(NAME).dll :: $(OUTPATH) $(OUTPATH)\$(NAME).def $(OUTPATH)\pd.lib
+
+$(OUTPATH)\$(NAME).dll :: $(OBJS)
+ ilink32 -C -Tpd $(LIBPATH) $** ,$<,,$(LIBS) $(OUTPATH)\pd.lib $(FLEXTPATH)\flext-$(TARGET).lib ,$(OUTPATH)\$(NAME).def
+ -@del $**
+ -@del $(OUTPATH)\*.i*
+ -@del $(OUTPATH)\*.map
+ -@del $(OUTPATH)\*.def
+ -@del $(OUTPATH)\*.tds
+
+
+
+
diff --git a/externals/grill/flext/tutorial/makefile.pd-cygwin b/externals/grill/flext/tutorial/makefile.pd-cygwin
new file mode 100644
index 00000000..b8a48403
--- /dev/null
+++ b/externals/grill/flext/tutorial/makefile.pd-cygwin
@@ -0,0 +1,58 @@
+# flext tutorial examples
+#
+# Makefile for gcc @ cygwin
+#
+# usage: make -f makefile.pd-cygwin
+#
+# -----------------------------------------------------
+#
+# note: the thread examples don't compile with cygwin
+#
+# -----------------------------------------------------
+
+include config-pd-cygwin.txt
+
+FLEXTLIB=$(FLEXTPATH)/flext-pdwin.lib
+
+INCLUDES=$(PDPATH)/src
+LIBPATH=$(PDPATH)/bin
+FLAGS=-DPD -DNT
+CFLAGS=-O6 -mcpu=pentiumpro
+LIBS=m pd
+
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+
+EXAMPLES=simple1 simple2 simple3 adv1 signal1~ signal2~ # thread1 thread2
+
+TARGETS=$(patsubst %,$(OUTPATH)/%.dll,$(EXAMPLES))
+
+# default target
+all: $(OUTPATH) $(TARGETS)
+
+
+$(OUTPATH)/%~.dll : $(OUTPATH)/%.dll
+ mv $^ $@
+
+$(SRCS): $(HDRS)
+ touch $@
+
+$(OUTPATH):
+ -mkdir $(OUTPATH)
+
+$(OUTPATH)/%.o : %/main.cpp
+ $(CXX) -c $(CFLAGS) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) $(FLEXTPATH)) $< -o $@
+
+$(OUTPATH)/%.dll : $(OUTPATH)/%.o $(FLEXTLIB)
+ $(CXX) $(LDFLAGS) -shared $(patsubst %,-L%,$(LIBPATH)) $^ $(patsubst %,-l%,$(LIBS)) -o $@
+ rm $<
+ chmod 755 $@
+
+
+.PHONY: clean
+clean:
+ rm -f $(OUTPATH)/*.o $(TARGETS)
+
diff --git a/externals/grill/flext/tutorial/makefile.pd-linux b/externals/grill/flext/tutorial/makefile.pd-linux
new file mode 100644
index 00000000..5c0a3cbc
--- /dev/null
+++ b/externals/grill/flext/tutorial/makefile.pd-linux
@@ -0,0 +1,57 @@
+# flext tutorial examples
+#
+# Makefile for gcc @ linux
+#
+# usage: make -f makefile.pd-linux
+#
+# -----------------------------------------------------
+
+include config-pd-linux.txt
+
+FLEXTLIB=$(FLEXTPATH)/flext_t.a # take threaded library for all
+
+
+# compiler+linker stuff ### EDIT! ###
+INCLUDES=$(PDPATH)/src
+LIBPATH=
+FLAGS=-DPD -DFLEXT_THREADS
+CFLAGS=-O6 -mcpu=pentiumpro
+LIBS=m
+
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+
+EXAMPLES=simple1 simple2 simple3 adv1 signal1~ signal2~ thread1 thread2
+
+
+TARGETS=$(patsubst %,$(OUTPATH)/%.pd_linux,$(EXAMPLES))
+
+# default target
+all: $(OUTPATH) $(TARGETS)
+
+
+$(OUTPATH)/%~.pd_linux : $(OUTPATH)/%.pd_linux
+ mv $^ $@
+
+$(SRCS): $(HDRS)
+ touch $@
+
+$(OUTPATH):
+ mkdir $(OUTPATH)
+
+$(OUTPATH)/%.o : %/main.cpp
+ $(CXX) -c $(CFLAGS) $(FLAGS) $(patsubst %,-I%,$(INCLUDES) $(FLEXTPATH)) $< -o $@
+
+$(OUTPATH)/%.pd_linux : $(OUTPATH)/%.o $(FLEXTLIB)
+ $(CXX) $(LDFLAGS) -shared $(patsubst %,-L%,$(LIBPATH)) $^ $(patsubst %,-l%,$(LIBS)) -o $@
+ chmod 755 $@
+
+
+.PHONY: clean
+clean:
+ rm -f $(OUTPATH)/*.o $(TARGETS)
+
+
diff --git a/externals/grill/flext/tutorial/makefile.pd-msvc b/externals/grill/flext/tutorial/makefile.pd-msvc
new file mode 100644
index 00000000..3478cb9e
--- /dev/null
+++ b/externals/grill/flext/tutorial/makefile.pd-msvc
@@ -0,0 +1,48 @@
+# flext - C++ layer for Max/MSP and pd (pure data) externals
+# Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+#
+# Makefile for MSVC++
+#
+#
+# IMPORTANT: Adjust some of the paths also in makefile-inc.msvc
+#
+# usage: make -f makefile.pd-msvc
+#
+# ---------------------------------------------------------------
+
+!include config-pd-msvc.txt
+
+# includes
+INCPATH=/I"$(MSVCPATH)\include" /I"$(PDPATH)\src" /I"$(FLEXTPATH)"
+LIBPATH=/LIBPATH:"$(MSVCPATH)\lib" /LIBPATH:"$(PDPATH)\bin" /LIBPATH:"$(FLEXTPATH)"
+LIBS=pd.lib pthreadVC.lib flext_t-pdwin.lib
+
+# compiler definitions and flags
+DEFS=/DPD /DNT /DFLEXT_THREADS
+
+CFLAGS=/GR /GD /G6 /Ox /MT
+
+
+# the rest can stay untouched
+# ----------------------------------------------
+
+# all the source files from the package
+SRCS=main.cpp
+HDRS=
+
+# -----------------------------------------------
+
+all: $(OUTPATH) $(OUTPATH)\$(NAME).dll
+
+$(OUTPATH):
+ -mkdir $(OUTPATH)
+
+$(OUTPATH)\$(NAME)~.dll : $(OUTPATH)\$(NAME).dll
+ -ren $** $<
+
+$(OUTPATH)\$(NAME).dll : $(DIR)\$(SRCS)
+ cl /c /LD $(CFLAGS) $(DEFS) $(INCPATH) $** /Fotemp.obj
+ link /DLL /out:$@ /INCREMENTAL:NO temp.obj $(LIBS) $(LIBPATH)
+ @-del $(OUTPATH)\*.exp
+ @-del $(OUTPATH)\*.lib
+ @-del temp.obj
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-adv1 b/externals/grill/flext/tutorial/maxmsp/ex-adv1
new file mode 100755
index 00000000..dc29619b
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-adv1
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-signal1 b/externals/grill/flext/tutorial/maxmsp/ex-signal1
new file mode 100755
index 00000000..ca80fc9f
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-signal1
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-signal2 b/externals/grill/flext/tutorial/maxmsp/ex-signal2
new file mode 100755
index 00000000..f7172d01
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-signal2
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-simple1 b/externals/grill/flext/tutorial/maxmsp/ex-simple1
new file mode 100755
index 00000000..efebcce6
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-simple1
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-simple2 b/externals/grill/flext/tutorial/maxmsp/ex-simple2
new file mode 100755
index 00000000..5515bc98
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-simple2
Binary files differ
diff --git a/externals/grill/flext/tutorial/maxmsp/ex-simple3 b/externals/grill/flext/tutorial/maxmsp/ex-simple3
new file mode 100755
index 00000000..62e048b7
--- /dev/null
+++ b/externals/grill/flext/tutorial/maxmsp/ex-simple3
Binary files differ
diff --git a/externals/grill/flext/tutorial/pd/ex-adv1.pd b/externals/grill/flext/tutorial/pd/ex-adv1.pd
new file mode 100644
index 00000000..7ff14d6e
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-adv1.pd
@@ -0,0 +1,14 @@
+#N canvas 175 265 667 312 12;
+#X msg 35 31 or two words;
+#X msg 167 31 2 3;
+#X msg 47 252 one 2 3;
+#X obj 85 154 print result;
+#X obj 69 123 adv1 one;
+#X obj 47 224 prepend set;
+#X text 154 216 you can also use "prepend" if "adv1" has already been
+loaded!;
+#X connect 0 0 4 0;
+#X connect 1 0 4 0;
+#X connect 4 0 3 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-signal1.pd b/externals/grill/flext/tutorial/pd/ex-signal1.pd
new file mode 100644
index 00000000..391e33a5
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-signal1.pd
@@ -0,0 +1,16 @@
+#N canvas 335 232 452 302 10;
+#X obj 233 98 hsl 128 15 0 1 0 0 empty empty empty 20 8 0 8 -260818
+-1 -1 0 1;
+#X obj 117 46 osc~ 440;
+#X obj 155 173 *~ 0.6;
+#X obj 147 218 dac~;
+#X obj 184 47 osc~ 880;
+#X floatatom 210 80 5 0 0;
+#X obj 155 139 signal1~;
+#X connect 0 0 6 2;
+#X connect 1 0 6 0;
+#X connect 2 0 3 0;
+#X connect 2 0 3 1;
+#X connect 4 0 6 1;
+#X connect 5 0 6 2;
+#X connect 6 0 2 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-signal2.pd b/externals/grill/flext/tutorial/pd/ex-signal2.pd
new file mode 100644
index 00000000..cdd7aaea
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-signal2.pd
@@ -0,0 +1,17 @@
+#N canvas 251 267 456 306 12;
+#X obj 89 68 signal2~;
+#X floatatom 52 117 5 0 0;
+#X floatatom 153 120 5 0 0;
+#X floatatom 251 120 5 0 0;
+#X floatatom 345 121 5 0 0;
+#X obj 90 30 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 29 136 sample rate;
+#X text 136 136 block size;
+#X text 116 29 bang to get audio system parameters;
+#X text 243 137 channels in and out;
+#X connect 0 0 1 0;
+#X connect 0 1 2 0;
+#X connect 0 2 3 0;
+#X connect 0 3 4 0;
+#X connect 5 0 0 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-simple1.pd b/externals/grill/flext/tutorial/pd/ex-simple1.pd
new file mode 100644
index 00000000..1be01595
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-simple1.pd
@@ -0,0 +1,10 @@
+#N canvas 197 285 460 310 12;
+#X floatatom 85 47 5 0 0;
+#X floatatom 85 142 5 0 0;
+#X msg 22 44 help;
+#X text 137 141 inverse;
+#X text 139 45 input;
+#X obj 85 90 simple1;
+#X connect 0 0 5 0;
+#X connect 2 0 5 0;
+#X connect 5 0 1 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-simple2.pd b/externals/grill/flext/tutorial/pd/ex-simple2.pd
new file mode 100644
index 00000000..8074cb13
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-simple2.pd
@@ -0,0 +1,13 @@
+#N canvas 197 285 454 304 12;
+#X obj 110 96 simple2 3;
+#X floatatom 98 51 5 0 0;
+#X floatatom 199 52 5 0 0;
+#X floatatom 108 150 5 0 0;
+#X msg 11 12 help;
+#X text 90 30 triggering;
+#X text 202 31 non-triggering;
+#X text 196 96 default argument;
+#X connect 0 0 3 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 1;
+#X connect 4 0 0 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-simple3.pd b/externals/grill/flext/tutorial/pd/ex-simple3.pd
new file mode 100644
index 00000000..e2867241
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-simple3.pd
@@ -0,0 +1,18 @@
+#N canvas 329 97 539 308 12;
+#X msg 11 12 help;
+#X msg 123 84 born;
+#X msg 172 85 to;
+#X msg 214 87 hula;
+#X msg 228 168 yeah;
+#X msg 228 130 hula 1;
+#X text 280 169 other symbol;
+#X text 57 12 issue help message;
+#X obj 148 231 simple3;
+#X text 261 88 tag without argument;
+#X text 297 128 tag and argument;
+#X connect 0 0 8 0;
+#X connect 1 0 8 0;
+#X connect 2 0 8 0;
+#X connect 3 0 8 0;
+#X connect 4 0 8 0;
+#X connect 5 0 8 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-thread1.pd b/externals/grill/flext/tutorial/pd/ex-thread1.pd
new file mode 100644
index 00000000..6358406c
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-thread1.pd
@@ -0,0 +1,34 @@
+#N canvas 105 266 672 310 12;
+#X obj 54 29 bng 25 250 50 0 empty empty start 0 -6 0 8 -258699 -1
+-1;
+#X floatatom 54 216 8 0 0;
+#X obj 54 182 thread1;
+#X floatatom 145 218 8 0 0;
+#X obj 145 184 thread1;
+#X floatatom 235 219 8 0 0;
+#X obj 235 185 thread1;
+#X floatatom 327 219 8 0 0;
+#X obj 327 185 thread1;
+#X floatatom 420 219 8 0 0;
+#X obj 420 185 thread1;
+#X obj 146 123 delay 200;
+#X obj 235 122 delay 200;
+#X obj 328 124 delay 200;
+#X obj 419 123 delay 200;
+#X text 93 23 click to start;
+#X text 141 41 (if you click twice \, the same thread is started a
+second time);
+#X connect 0 0 2 0;
+#X connect 0 0 11 0;
+#X connect 2 0 1 0;
+#X connect 4 0 3 0;
+#X connect 6 0 5 0;
+#X connect 8 0 7 0;
+#X connect 10 0 9 0;
+#X connect 11 0 4 0;
+#X connect 11 0 12 0;
+#X connect 12 0 6 0;
+#X connect 12 0 13 0;
+#X connect 13 0 8 0;
+#X connect 13 0 14 0;
+#X connect 14 0 10 0;
diff --git a/externals/grill/flext/tutorial/pd/ex-thread2.pd b/externals/grill/flext/tutorial/pd/ex-thread2.pd
new file mode 100644
index 00000000..26205b8d
--- /dev/null
+++ b/externals/grill/flext/tutorial/pd/ex-thread2.pd
@@ -0,0 +1,40 @@
+#N canvas 116 192 666 304 12;
+#X msg 91 131 stop;
+#X msg 262 135 stop;
+#X obj 206 42 bng 25 250 50 0 empty empty empty 0 -6 0 8 -258699 -1
+-1;
+#X obj 298 42 bng 25 250 50 0 empty empty empty 0 -6 0 8 -258699 -1
+-1;
+#X text 198 21 start;
+#X text 290 20 stop;
+#X msg 46 131 0;
+#X msg 217 135 0;
+#X msg 430 133 stop;
+#X msg 385 133 0;
+#X obj 411 172 thread2 50;
+#X obj 239 172 thread2 15;
+#X obj 73 171 thread2 3;
+#X floatatom 73 205 8 0 0;
+#X floatatom 239 205 8 0 0;
+#X floatatom 411 205 8 0 0;
+#X msg 140 131 text;
+#X msg 309 135 text;
+#X msg 477 133 text;
+#X connect 0 0 12 0;
+#X connect 1 0 11 0;
+#X connect 2 0 6 0;
+#X connect 2 0 7 0;
+#X connect 2 0 9 0;
+#X connect 3 0 0 0;
+#X connect 3 0 1 0;
+#X connect 3 0 8 0;
+#X connect 6 0 12 0;
+#X connect 7 0 11 0;
+#X connect 8 0 10 0;
+#X connect 9 0 10 0;
+#X connect 10 0 15 0;
+#X connect 11 0 14 0;
+#X connect 12 0 13 0;
+#X connect 16 0 12 0;
+#X connect 17 0 11 0;
+#X connect 18 0 10 0;
diff --git a/externals/grill/flext/tutorial/readme.txt b/externals/grill/flext/tutorial/readme.txt
new file mode 100644
index 00000000..ec05f1a1
--- /dev/null
+++ b/externals/grill/flext/tutorial/readme.txt
@@ -0,0 +1,36 @@
+flext - C++ layer for Max/MSP and pd (pure data) externals
+tutorial examples
+
+Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+----------------------------------------------------------------------------
+
+These are a few examples to demonstrate some flext features.
+Contribution of examples to the package is higly appreciated!
+
+----------------------------------------------------------------------------
+
+The package should at least compile (and is tested) with the following compilers:
+
+pd - Windows:
+-------------
+o Borland C++ 5.5 (free): edit "config-pd-bcc.txt" & run "build-pd-bcc.bat"
+
+o Microsoft Visual C++ 6: edit "config-pd-msvc.txt" & run "build-pd-msvc.bat"
+
+o Cygwin: edit "config-pd-cygwin.txt" & run "sh build-pd-cygwin.sh"
+
+pd - linux:
+-----------
+o GCC: edit "config-pd-linux.txt" & run "sh build-pd-linux.sh"
+
+Max/MSP - MacOS 9:
+------------------
+o Metrowerks CodeWarrior V6: edit & use the several ".cw" project files
+
+o Apple MPW-PR: edit & use the several "make.mpw" makefiles
+
+----------------------------------------------------------------------------
+
diff --git a/externals/grill/flext/tutorial/signal1/main.cpp b/externals/grill/flext/tutorial/signal1/main.cpp
new file mode 100644
index 00000000..14818e6f
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal1/main.cpp
@@ -0,0 +1,129 @@
+// signal1~ - a flext tutorial external written by Frank Barknecht
+//
+// This is a commented port of the pan~ example from the PD-Externals-Howto to
+// illustrate the usage of flext. You can get the original code at
+// http://iem.kug.ac.at/pd/externals-HOWTO/
+
+#include <flext.h>
+#include <math.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
+#error You need at least flext version 0.3.0
+#endif
+
+
+// A flext dsp external ("tilde object") inherits from the class flext_dsp
+class signal1:
+ public flext_dsp
+{
+ // Each external that is written in C++ needs to use #defines
+ // from flbase.h
+ //
+ // The define
+ //
+ // FLEXT_HEADER(NEW_CLASS, PARENT_CLASS)
+ //
+ // should be somewhere in your dsp file.
+ // A good place is here:
+
+ FLEXT_HEADER(signal1, flext_dsp)
+
+ public:
+ signal1():
+ f_pan(0) // initialize f_pan
+ {
+ // The constructor of your class is responsible for
+ // setting up inlets and outlets and for registering
+ // inlet-methods:
+
+ AddInSignal(2); // 2 audio ins
+ AddInFloat(); // 1 float in
+ AddOutSignal(); // 1 audio out [ == AddOutSignal(1) ]
+
+ SetupInOut(); // set up inlets and outlets.
+ // Must be called once!
+
+ // Now we need to bind the handler function to our
+ // panning inlet, which is inlet 2 (counting all inlets
+ // from 0). We want the function "setPan" to get
+ // called on incoming float messages:
+
+ FLEXT_ADDMETHOD(2,setPan);
+
+ // We're done constructing:
+ post("-- pan~ with flext ---");
+
+ } // end of constructor
+
+
+ protected:
+ // here we declare the virtual DSP function
+ virtual void m_signal(int n, float *const *in, float *const *out);
+ private:
+ float f_pan; // holds our panning factor
+
+ // Before we can use "setPan" as a handler, we must register this
+ // function as a callback to PD or Max. This is done using the
+ // FLEXT_CALLBACK* macros. There are several of them.
+ //
+ // FLEXT_CALLBACK_F is a shortcut, that registers a function
+ // expecting one float arg (thus ending in "_F"). There are
+ // other shortcuts that register other types of functions. Look
+ // into flext.h. No semicolon at the end of line!!!
+ FLEXT_CALLBACK_F(setPan)
+
+ // Now setPan can get declared and defined here.
+ void setPan(float f)
+ {
+ // set our private panning factor "f_pan" to the inlet
+ // value float "f" in the intervall [0,1]
+ f_pan = (f<0) ? 0.0f : (f>1) ? 1.0f : f ;
+
+ // if you want to debug if this worked, comment out the
+ // following line:
+ //post("Set panning to %.2f, maybe clipped from %.2f", f_pan,f);
+ } // end setPan
+}; // end of class declaration for signal1
+
+
+// Before we can run our signal1-class in PD, the object has to be registered as a
+// PD object. Otherwise it would be a simple C++-class, and what good would
+// that be for? Registering is made easy with the FLEXT_NEW_* macros defined
+// in flext.h. For tilde objects without arguments call:
+
+FLEXT_NEW_DSP("signal1~ signal1~", signal1)
+// T.Grill: there are two names for the object: signal1~ as main name and pan~ as its alias
+
+// Now we define our DSP function. It gets this arguments:
+//
+// int n: length of signal vector. Loop over this for your signal processing.
+// float *const *in, float *const *out:
+// These are arrays of the signals in the objects signal inlets rsp.
+// oulets. We come to that later inside the function.
+
+void signal1::m_signal(int n, float *const *in, float *const *out)
+{
+
+ const float *ins1 = in[0];
+ const float *ins2 = in[1];
+ // As said above "in" holds a list of the signal vectors in all inlets.
+ // After these two lines, ins1 holds the signal vector ofthe first
+ // inlet, index 0, and ins2 holds the signal vector of the second
+ // inlet, with index 1.
+
+ float *outs = out[0];
+ // Now outs holds the signal vector at the one signal outlet we have.
+
+ // We are now ready for the main signal loop
+ while (n--)
+ {
+
+ // The "++" after the pointers outs, ins1 and ins2 walks us
+ // through the signal vector with each n, of course. Before
+ // each step we change the signal value in the outlet *outs
+ // according to our panning factor "f_pan" and according to the
+ // signals at the two signal inlets, *ins1 and *ins2
+
+ *outs++ = (*ins1++) * (1-f_pan) + (*ins2++) * f_pan;
+ }
+} // end m_signal
diff --git a/externals/grill/flext/tutorial/signal1/signal1.cw b/externals/grill/flext/tutorial/signal1/signal1.cw
new file mode 100644
index 00000000..f273b763
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal1/signal1.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/signal1/signal1.dsp b/externals/grill/flext/tutorial/signal1/signal1.dsp
new file mode 100644
index 00000000..42916c07
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal1/signal1.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="signal1" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=signal1 - 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 "signal1.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 "signal1.mak" CFG="signal1 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "signal1 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "signal1 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "max/flext/tutorial/signal1"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "signal1 - 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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../msvc/signal1~.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "signal1 - 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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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 /out:"msvc-debug/signal1~.dll" /pdbtype:sept /libpath:"..\..\pd-msvc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "signal1 - Win32 Release"
+# Name "signal1 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/signal2/main.cpp b/externals/grill/flext/tutorial/signal2/main.cpp
new file mode 100644
index 00000000..1517b536
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal2/main.cpp
@@ -0,0 +1,80 @@
+/*
+flext tutorial - signal 2
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This is an object showing varous parameters of the pd audio system
+*/
+
+// include flext header
+#include <flext.h>
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
+#error You need at least flext version 0.3.0
+#endif
+
+
+// define the class that stands for a pd/Max object
+// Attention: the class name must be the same as the object name!! (without the ~)
+
+class signal2:
+ // inherit from flext dsp class
+ public flext_dsp
+{
+ // obligatory flext header (class name,base class name)
+ FLEXT_HEADER(signal2,flext_dsp)
+
+public:
+ // constructor
+ signal2();
+
+protected:
+ void m_bang(); // method for bang
+
+ // this virtual function is obligatory for objects derived from flext_dsp
+ virtual void m_signal(int n, float *const *in, float *const *out);
+
+private:
+ FLEXT_CALLBACK(m_bang); // callback for method "m_bang"
+};
+
+// instantiate the class
+FLEXT_NEW_DSP("signal2~",signal2)
+
+
+signal2::signal2()
+{
+ // define inlets:
+ // first inlet must always by of type anything (or signal for dsp objects)
+ AddInAnything(); // add one inlet for any message
+
+ // add outlets for sample rate, block size, audio in and out channel count
+ AddOutFloat(1);
+ AddOutInt(3); // although PD knows no int type, flext does!
+
+ // set up inlets and outlets - obligatory!
+ SetupInOut();
+
+ // register methods
+ FLEXT_ADDBANG(0,m_bang); // register method "m_bang" for bang message into inlet 0
+}
+
+void signal2::m_bang()
+{
+ // output various parameters of the pd audio system
+ ToOutFloat(0,Samplerate());
+ ToOutInt(1,Blocksize());
+ ToOutInt(2,ChannelsIn());
+ ToOutInt(3,ChannelsOut());
+}
+
+void signal2::m_signal(int, float *const *, float *const *)
+{
+ // do no dsp work
+}
+
diff --git a/externals/grill/flext/tutorial/signal2/signal2.cw b/externals/grill/flext/tutorial/signal2/signal2.cw
new file mode 100644
index 00000000..a7b29ba3
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal2/signal2.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/signal2/signal2.dsp b/externals/grill/flext/tutorial/signal2/signal2.dsp
new file mode 100644
index 00000000..c70ae670
--- /dev/null
+++ b/externals/grill/flext/tutorial/signal2/signal2.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="signal2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=signal2 - 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 "signal2.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 "signal2.mak" CFG="signal2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "signal2 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "signal2 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "max/flext/tutorial/signal2"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "signal2 - 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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../msvc/signal2~.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "signal2 - 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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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 /out:"msvc-debug/signal2~.dll" /pdbtype:sept /libpath:"..\..\pd-msvc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "signal2 - Win32 Release"
+# Name "signal2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/simple1/main.cpp b/externals/grill/flext/tutorial/simple1/main.cpp
new file mode 100755
index 00000000..38f12573
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple1/main.cpp
@@ -0,0 +1,78 @@
+/*
+flext tutorial - simple 1
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This is an example of a simple object doing a float inversion
+*/
+
+// include flext header
+#include <flext.h>
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
+#error You need at least flext version 0.3.0
+#endif
+
+
+// define the class that stands for a pd/Max object
+// Attention: the class name must be the same as the object name!! (without an eventual ~)
+
+class simple1:
+ // inherit from basic flext class
+ public flext_base
+{
+ // obligatory flext header (class name,base class name)
+ FLEXT_HEADER(simple1,flext_base)
+
+public:
+ // constructor
+ simple1();
+
+protected:
+ void m_float(float f); // method for float values
+
+private:
+ FLEXT_CALLBACK_1(m_float,float); // callback for method "m_float" (with one float argument)
+};
+
+// instantiate the class
+FLEXT_NEW("simple1",simple1)
+
+
+simple1::simple1()
+{
+ // define inlets:
+ // first inlet must always by of type anything (or signal for dsp objects)
+ AddInAnything(); // add one inlet for any message
+
+ // define outlets:
+ AddOutFloat(); // add one float outlet (has index 0)
+
+ // set up inlets and outlets - obligatory!
+ SetupInOut();
+
+ // register methods
+ FLEXT_ADDMETHOD(0,m_float); // register method (for float messages) "m_float" for inlet 0
+}
+
+void simple1::m_float(float f)
+{
+ float res;
+ if(f == 0) {
+ // special case 0
+ post("%s - zero can't be inverted!",thisName());
+ res = 0;
+ }
+ else
+ // normal case
+ res = 1/f;
+
+ // output value to outlet
+ ToOutFloat(0,res); // (0 stands for the outlet index 0 - the leftmost outlet)
+}
+
diff --git a/externals/grill/flext/tutorial/simple1/simple1.cw b/externals/grill/flext/tutorial/simple1/simple1.cw
new file mode 100755
index 00000000..d8b58eb1
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple1/simple1.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/simple1/simple1.dsp b/externals/grill/flext/tutorial/simple1/simple1.dsp
new file mode 100644
index 00000000..281042a2
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple1/simple1.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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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
diff --git a/externals/grill/flext/tutorial/simple2/main.cpp b/externals/grill/flext/tutorial/simple2/main.cpp
new file mode 100755
index 00000000..306a953b
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple2/main.cpp
@@ -0,0 +1,80 @@
+/*
+flext tutorial - simple 2
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This is an example of a simple object doing a float addition
+*/
+
+// include flext header
+#include <flext.h>
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
+#error You need at least flext version 0.3.0
+#endif
+
+
+class simple2:
+ public flext_base
+{
+ FLEXT_HEADER(simple2,flext_base)
+
+public:
+ // constructor with float argument
+ simple2(float init);
+
+protected:
+ void m_float1(float f);
+ void m_float2(float f);
+
+ // stored argument of right inlet
+ float arg;
+
+private:
+ // FLEXT_CALLBACK_F(...) is a shortcut for FLEXT_CALLBACK_1(...,float)
+ FLEXT_CALLBACK_F(m_float1); // callback for method "m_float1" (with one float argument)
+ FLEXT_CALLBACK_F(m_float2); // callback for method "m_float2" (with one float argument)
+};
+
+// instantiate the class (constructor has one float argument)
+FLEXT_NEW_1("simple2",simple2,float)
+
+
+simple2::simple2(float init):
+ arg(init) // store argument
+{
+ // define inlets
+ AddInAnything(); // first inlet of type anything (index 0)
+ AddInFloat(); // additional float inlet (index 1)
+
+ // define outlets
+ AddOutFloat(); // one float outlet (has index 0)
+
+ // set up inlets and outlets - obligatory!
+ SetupInOut();
+
+ // register methods
+ FLEXT_ADDMETHOD(0,m_float1); // register method (for floats) "m_float1" for inlet 0
+ FLEXT_ADDMETHOD(1,m_float2); // register method (for floats) "m_float2" for inlet 1
+}
+
+void simple2::m_float1(float f)
+{
+ float res;
+ res = arg+f;
+
+ // output value to outlet
+ ToOutFloat(0,res); // (0 stands for the outlet index 0)
+}
+
+void simple2::m_float2(float f)
+{
+ // store float
+ arg = f;
+}
+
diff --git a/externals/grill/flext/tutorial/simple2/simple2.cw b/externals/grill/flext/tutorial/simple2/simple2.cw
new file mode 100755
index 00000000..1bc9379f
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple2/simple2.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/simple2/simple2.dsp b/externals/grill/flext/tutorial/simple2/simple2.dsp
new file mode 100644
index 00000000..22b75a5e
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple2/simple2.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="simple2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=simple2 - 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 "simple2.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 "simple2.mak" CFG="simple2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "simple2 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "simple2 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "simple2"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "simple2 - 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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../msvc/simple2.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "simple2 - 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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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 "simple2 - Win32 Release"
+# Name "simple2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/simple3/main.cpp b/externals/grill/flext/tutorial/simple3/main.cpp
new file mode 100644
index 00000000..5d290f67
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple3/main.cpp
@@ -0,0 +1,90 @@
+/*
+flext tutorial - simple 3
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This is an example of an object digesting several "tagged" messages
+
+*/
+
+// include flext header
+#include <flext.h>
+
+// check for appropriate flext version
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 300)
+#error You need at least flext version 0.3.0
+#endif
+
+class simple3:
+ public flext_base
+{
+ FLEXT_HEADER(simple3,flext_base)
+
+public:
+ // constructor with variable argument list
+ simple3();
+
+protected:
+ void m_tag();
+ void m_tag_and_int(int i);
+ void m_sym(t_symbol *s);
+
+ // override default flext help function
+ virtual void m_help();
+
+private:
+
+ FLEXT_CALLBACK(m_tag); // callback for method "m_tag" (no arguments)
+ FLEXT_CALLBACK_I(m_tag_and_int); // callback for method "m_tag" (int arguments)
+ FLEXT_CALLBACK_S(m_sym); // callback for method "m_sym" (with one symbol argument)
+};
+
+// instantiate the class (constructor has a variable argument list)
+FLEXT_NEW("simple3",simple3)
+
+
+simple3::simple3()
+{
+ // define inlets
+ AddInAnything(); // add inlet of type anything (index 0)
+
+ // set up inlets and outlets
+ SetupInOut();
+
+ // register methods
+ FLEXT_ADDMETHOD_(0,"born",m_tag); // register method for tag "born"
+ FLEXT_ADDMETHOD_(0,"to",m_tag); // register method for tag "to"
+ FLEXT_ADDMETHOD_(0,"hula",m_tag); // register method for tag "hula"
+ FLEXT_ADDMETHOD_I(0,"hula",m_tag_and_int); // register method for tag "hula" and int argument
+
+ FLEXT_ADDMETHOD(0,m_sym); // register method for all other symbols
+}
+
+void simple3::m_tag()
+{
+ post("tag recognized");
+}
+
+void simple3::m_tag_and_int(int i)
+{
+ post("tag recognized (has int arg: %i)",i);
+}
+
+void simple3::m_sym(t_symbol *s)
+{
+ post("symbol: %s",GetString(s));
+}
+
+
+void simple3::m_help()
+{
+ // post a help message
+ // thisName() returns a char * for the object name
+ post("%s - example for tagged messages",thisName());
+}
+
+
diff --git a/externals/grill/flext/tutorial/simple3/simple3.cw b/externals/grill/flext/tutorial/simple3/simple3.cw
new file mode 100644
index 00000000..b29678f7
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple3/simple3.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/simple3/simple3.dsp b/externals/grill/flext/tutorial/simple3/simple3.dsp
new file mode 100644
index 00000000..8390b044
--- /dev/null
+++ b/externals/grill/flext/tutorial/simple3/simple3.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="simple3" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=simple3 - 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 "simple3.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 "simple3.mak" CFG="simple3 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "simple3 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "simple3 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "simple3"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "simple3 - 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 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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:"../msvc/simple3.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "simple3 - 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 /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /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 "simple3 - Win32 Release"
+# Name "simple3 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/thread1/main.cpp b/externals/grill/flext/tutorial/thread1/main.cpp
new file mode 100644
index 00000000..878cef76
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread1/main.cpp
@@ -0,0 +1,79 @@
+/*
+flext tutorial - threads 1
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This shows an example of a method running as a thread
+*/
+
+// define FLEXT_THREADS for thread usage. Flext must also have been compiled with that defined!
+#ifndef FLEXT_THREADS
+#define FLEXT_THREADS
+#endif
+
+#include <flext.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 301)
+#error You need at least flext version 0.3.1
+#endif
+
+
+class thread1:
+ public flext_base
+{
+ FLEXT_HEADER(thread1,flext_base)
+
+public:
+ thread1();
+
+protected:
+ void m_start(); // method function
+
+private:
+ // define threaded callback for method m_start (with boolean argument)
+ // the same syntax as with FLEXT_CALLBACK is used here
+ FLEXT_THREAD(m_start);
+};
+
+FLEXT_NEW("thread1",thread1)
+
+
+
+thread1::thread1()
+{
+ AddInAnything();
+ AddOutInt();
+ SetupInOut(); // set up inlets and outlets
+
+ FLEXT_ADDBANG(0,m_start); // register method
+}
+
+void thread1::m_start()
+{
+ // Please note that this functions needs about 10 seconds to complete
+ // Without threads it would block the real-time system
+
+ // Okay, that functionality would be far more elegant with timers
+ // ... but hey, it's a demo!
+
+ for(int i = 0; i < 20 && !ShouldExit(); ++i) {
+ ToOutInt(0,i); // output loop count
+
+ // wait for half a second
+ for(int j = 0; j < 5 && !ShouldExit(); ++j) Sleep(0.1f);
+ // note: we shall not block a thread for a longer time.
+ // The system might want to destroy the object in the meantime and
+ // expects thread termination.
+ // Flext waits for 1 second by default, then it aborts the thread brutally
+ }
+
+ // output a final zero
+ ToOutInt(0,0);
+}
+
+
+
diff --git a/externals/grill/flext/tutorial/thread1/thread1.cw b/externals/grill/flext/tutorial/thread1/thread1.cw
new file mode 100644
index 00000000..b26ff18b
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread1/thread1.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/thread1/thread1.dsp b/externals/grill/flext/tutorial/thread1/thread1.dsp
new file mode 100644
index 00000000..7ef7ca52
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread1/thread1.dsp
@@ -0,0 +1,104 @@
+# Microsoft Developer Studio Project File - Name="thread1" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=thread1 - 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 "thread1.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 "thread1.mak" CFG="thread1 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "thread1 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "thread1 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "thread1"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "thread1 - 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 /MT /W3 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /D "FLEXT_THREADS" /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_t-pdwin.lib pthreadVC.lib /nologo /dll /machine:I386 /out:"../msvc/thread1.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "thread1 - 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 /MTd /W3 /Gm /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /D "FLEXT_THREADS" /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_td-pdwin.lib pthreadVC.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\pd-msvc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "thread1 - Win32 Release"
+# Name "thread1 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+
+!IF "$(CFG)" == "thread1 - Win32 Release"
+
+# ADD CPP /GR-
+
+!ELSEIF "$(CFG)" == "thread1 - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/thread2/main.cpp b/externals/grill/flext/tutorial/thread2/main.cpp
new file mode 100644
index 00000000..ce2a170e
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread2/main.cpp
@@ -0,0 +1,132 @@
+/*
+flext tutorial - threads 2
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+-------------------------------------------------------------------------
+
+This shows an example of multiple threads and syncing with a thread conditional
+*/
+
+// define FLEXT_THREADS for thread usage. Flext must also have been compiled with that defined!
+#ifndef FLEXT_THREADS
+#define FLEXT_THREADS
+#endif
+
+#include <flext.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 301)
+#error You need at least flext version 0.3.1
+#endif
+
+
+class thread2:
+ public flext_base
+{
+ FLEXT_HEADER(thread2,flext_base)
+
+public:
+ thread2(int del);
+
+protected:
+ void m_start(int st);
+ void m_stop();
+ void m_text();
+
+ void m_textout();
+
+private:
+ FLEXT_THREAD_I(m_start); // define threaded callback for method m_start
+ FLEXT_CALLBACK(m_stop); // normal callback for m_stop
+ FLEXT_CALLBACK(m_text); // turn on console output
+
+ FLEXT_THREAD(m_textout); // text output
+
+ float delay;
+ volatile int count;
+
+ // caution: CodeWarrior seems to ignore volatile modifier!!
+ volatile bool stopit,running,blipping; // flags for running and stopping
+
+ // thread conditional for stop signal
+ ThrCond cond;
+};
+
+FLEXT_NEW_1("thread2",thread2,int)
+
+
+
+thread2::thread2(int del):
+ delay(del/1000.f),
+ stopit(false),
+ running(false),blipping(false)
+{
+ AddInAnything();
+ AddOutInt(2);
+ SetupInOut(); // set up inlets and outlets
+
+ FLEXT_ADDMETHOD(0,m_start); // register start for integer numbers (floats in PD)
+ FLEXT_ADDMETHOD_(0,"text",m_text); // register m_text method for "text" tag
+ FLEXT_ADDMETHOD_(0,"stop",m_stop); // register m_text method for "stop" tag
+}
+
+void thread2::m_start(int st)
+{
+ // if already running, just set back the counter
+ if(running) { count = st; return; }
+
+ running = true;
+
+ // loop until either the system exit flag or the "stopit" flag is set
+ for(count = st; !ShouldExit() && !stopit; ++count)
+ {
+ Sleep(delay);
+ ToOutInt(0,count); // output loop count
+ }
+
+ cond.Lock(); // lock conditional
+ running = false; // change state flag
+ cond.Signal(); // signal changed flag to watiting "stop" method
+ cond.Unlock(); // unlock conditional
+}
+
+void thread2::m_stop()
+{
+ cond.Lock(); // lock conditional
+ stopit = true; // set termination flag
+
+ while(*(&running) || *(&blipping)) // workaround for CodeWarrior!
+ {
+ cond.Wait(); // wait for signal by running threads
+ }
+
+ // --- Here, the threads should have stopped ---
+
+ stopit = false; // reset flag
+ cond.Unlock(); // unlock conditional
+}
+
+
+void thread2::m_text()
+{
+ FLEXT_CALLMETHOD(m_textout);
+}
+
+void thread2::m_textout()
+{
+ if(blipping) return;
+ blipping = true;
+
+ while(!ShouldExit() && !stopit) {
+ post("%i",count);
+ Sleep(1.f);
+ }
+
+ cond.Lock(); // lock conditional
+ blipping = false; // change state flag
+ cond.Signal(); // signal changed flag to watiting "stop" method
+ cond.Unlock(); // unlock conditional
+}
+
diff --git a/externals/grill/flext/tutorial/thread2/thread2.cw b/externals/grill/flext/tutorial/thread2/thread2.cw
new file mode 100755
index 00000000..b26ff18b
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread2/thread2.cw
Binary files differ
diff --git a/externals/grill/flext/tutorial/thread2/thread2.dsp b/externals/grill/flext/tutorial/thread2/thread2.dsp
new file mode 100644
index 00000000..da5e149e
--- /dev/null
+++ b/externals/grill/flext/tutorial/thread2/thread2.dsp
@@ -0,0 +1,95 @@
+# Microsoft Developer Studio Project File - Name="thread2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=thread2 - 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 "thread2.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 "thread2.mak" CFG="thread2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "thread2 - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "thread2 - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "max/flext/tutorial/thread2"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "thread2 - 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 /MT /W3 /GR- /GX- /O2 /I "..\..\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /D "FLEXT_THREADS" /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_t-pdwin.lib pthreadVC.lib /nologo /dll /machine:I386 /out:"../msvc/thread2.dll" /libpath:"..\..\pd-msvc"
+
+!ELSEIF "$(CFG)" == "thread2 - 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 /MTd /W3 /Gm /GR- /GX- /ZI /Od /I "..\..\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /D "FLEXT_THREADS" /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_td-pdwin.lib pthreadVC.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"..\..\pd-msvc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "thread2 - Win32 Release"
+# Name "thread2 - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/flext/tutorial/tutorial.dsw b/externals/grill/flext/tutorial/tutorial.dsw
new file mode 100644
index 00000000..5bc8001a
--- /dev/null
+++ b/externals/grill/flext/tutorial/tutorial.dsw
@@ -0,0 +1,161 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN!
+
+###############################################################################
+
+Project: "adv1"=.\adv1\adv1.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ adv1
+ .\adv1
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "flext"=..\flext.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ max/flext
+ ..
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "signal1"=.\signal1\signal1.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ max/flext/tutorial/signal1
+ .\signal1
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "signal2"=.\signal2\signal2.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ max/flext/tutorial/signal2
+ .\signal2
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "simple1"=.\simple1\simple1.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ simple1
+ .\simple1
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "simple2"=.\simple2\simple2.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ simple2
+ .\simple2
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "simple3"=.\simple3\simple3.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ simple3
+ .\simple3
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "thread1"=.\thread1\thread1.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ thread1
+ .\thread1
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "thread2"=.\thread2\thread2.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ max/flext/tutorial/thread2
+ .\thread2
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+