Commit 4f489341 authored by thomas's avatar thomas
Browse files

no message


git-svn-id: https://svn.grrrr.org/ext/trunk@150 4d9ac71a-51e6-0310-8455-cad1006bcd31
parent c4cca012
......@@ -102,7 +102,7 @@ SOURCE=.\flbuf.cpp
# End Source File
# Begin Source File
SOURCE=.\flcwmax.h
SOURCE=.\flclass.h
# End Source File
# Begin Source File
......@@ -122,6 +122,10 @@ SOURCE=.\flext.h
# End Source File
# Begin Source File
SOURCE=.\flinternal.h
# End Source File
# Begin Source File
SOURCE=.\flstdc.h
# End Source File
# End Target
......
flext - C++ layer for Max/MSP and pd (pure data) externals
version 0.2.2
version 0.2.3
Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net)
For information on usage and redistribution, and for a DISCLAIMER OF ALL
......@@ -70,6 +70,10 @@ see flext.h for the documented base classes
Version history:
0.2.3:
- restructured files and started usable inline documentation
- found that there was no means to output a bang?! Ugh! -> corrected
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)
......
......@@ -10,56 +10,60 @@ WARRANTIES, see the file, "license.txt," in this distribution.
// This is all derived from GEM by Mark Danks
/*! \file flbase.h
\brief Declares the internal flext base classes
!Lacking Details.!
*/
#ifndef __FLEXT_BASE_H
#define __FLEXT_BASE_H
#include <flstdc.h>
class flext_obj;
/*-----------------------------------------------------------------
-------------------------------------------------------------------
CLASS
flext_hdr
The obligatory object header
// ----------------------------------------------------------------------------
/*! \struct flext_hdr
\brief The obligatory PD or MaxMSP object header
DESCRIPTION
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 vtable.
-----------------------------------------------------------------*/
*/
// ----------------------------------------------------------------------------
struct FLEXT_EXT flext_hdr
{
//////////
// The obligatory object header
t_sigobj obj; // MUST reside at memory offset 0
/*! \brief The obligatory object header
MUST reside at memory offset 0
*/
t_sigobj obj;
#ifdef PD
float defsig; // float signal holder for pd
//! PD only: float signal holder for pd
float defsig;
#endif
#if defined(MAXMSP)
long curinlet; // current inlet used by proxy objects
//! MaxMSP only: current inlet used by proxy objects
long curinlet;
#endif
//////////
// Our data structure
/*! \brief Our data structure
This points to the actual polymorphic C++ class
*/
flext_obj *data;
};
/*-----------------------------------------------------------------
-------------------------------------------------------------------
CLASS
flext_obj
The base class for all externs written in C++
DESCRIPTION
// ----------------------------------------------------------------------------
/*! \class flext_obj
\brief The mother of base classes for all externs written in C++
Each extern which is written in C++ needs to use the #defines at the
end of this header file.
......@@ -76,8 +80,9 @@ DESCRIPTION
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:
......@@ -99,50 +104,46 @@ class FLEXT_EXT flext_obj
// ---------------------
//////////
// Constructor
//! Constructor
flext_obj();
//////////
// Destructor
//! Destructor
virtual ~flext_obj() = 0;
//////////
// Get the object's canvas
//! Get the object's canvas
t_canvas *getCanvas() { return(m_canvas); }
protected:
//////////
// The object header
//! The object header
flext_hdr *x_obj;
private:
//////////
// The canvas (patcher) that the object is in
//! The canvas (patcher) that the object is in
t_canvas *m_canvas;
public:
//////////
// Creation callback
//! Creation callback
static void callb_setup(t_class *) {}
//////////
// --------------------
// This is a holder - don't touch it
static flext_hdr *m_holder;
static const char *m_holdname; // hold object's name during construction
//////////
// The object's name in the patcher
//! The object's name in the patcher
const char *m_name;
#ifdef _DEBUG
//! check whether the object's name has a trailing tilde
static bool check_tilde(const char *objname,const char *setupfun);
#endif
#ifdef MAXMSP
/*! definitions for MaxMSP external libraries */
union lib_arg {
int i;
float f;
......@@ -156,12 +157,12 @@ class FLEXT_EXT flext_obj
#endif
};
// This has a dummy arg so that NT won't complain
//! This has a dummy arg so that NT won't complain
inline void *operator new(size_t, void *location, void *) { return location; }
////////////////////////////////////////
// ----------------------------------------
// This should be used in the header
////////////////////////////////////////
// ----------------------------------------
#ifdef PD
#define FLEXT_GETCLASS(obj) ((t_class *)((t_object *)(obj))->te_g.g_pd)
......@@ -170,9 +171,7 @@ inline void *operator new(size_t, void *location, void *) { return location; }
#endif
// Header without setup callback
#define FLEXT_HEADER(NEW_CLASS, PARENT_CLASS) \
#define FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) \
public: \
typedef NEW_CLASS thisType; \
static void callb_free(flext_hdr *hdr) \
......@@ -187,9 +186,7 @@ inline const char *thisName() const { return m_name; } \
static NEW_CLASS *thisObject(void *c) { return (NEW_CLASS *)((flext_hdr *)c)->data; }
// Header with setup callback
#define FLEXT_HEADER_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
#define FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
public: \
typedef NEW_CLASS thisType; \
static void callb_free(flext_hdr *hdr) \
......@@ -205,6 +202,7 @@ inline const char *thisName() const { return m_name; } \
static NEW_CLASS *thisObject(void *c) { return (NEW_CLASS *)((flext_hdr *)c)->data; }
#define REAL_NEW(NAME,NEW_CLASS,SETUP_FUNCTION) REAL_INST(0,NAME,NEW_CLASS,SETUP_FUNCTION)
#define REAL_NEW_G(NAME,NEW_CLASS,SETUP_FUNCTION) REAL_INST_G(0,NAME,NEW_CLASS,SETUP_FUNCTION)
#define REAL_NEW_1(NAME,NEW_CLASS,SETUP_FUNCTION,TYPE1) REAL_INST_1(0,NAME,NEW_CLASS,SETUP_FUNCTION,TYPE1)
......@@ -227,97 +225,13 @@ static NEW_CLASS *thisObject(void *c) { return (NEW_CLASS *)((flext_hdr *)c)->da
#define REAL_LIB_3(NAME,NEW_CLASS,SETUP_FUNCTION,TYPE1,TYPE2,TYPE3) REAL_NEWLIB_3(NAME,NEW_CLASS,SETUP_FUNCTION,TYPE1,TYPE2,TYPE3)
#endif
////////////////////////////////////////
// This should be the first thing in the implementation file
////////////////////////////////////////
//
// NO ARGUMENTS
/////////////////////////////////////////////////
#define FLEXT_NEW(NAME,NEW_CLASS) \
REAL_NEW(NAME,NEW_CLASS, _setup) \
REAL_EXT(NEW_CLASS, _setup)
#define FLEXT_NEW_TILDE(NAME,NEW_CLASS) \
REAL_NEW(NAME,NEW_CLASS, _tilde_setup) \
REAL_EXT(NEW_CLASS, _tilde_setup)
// --------------------------------------------------------------------------------------
#define FLEXT_LIB(NAME,NEW_CLASS) REAL_LIB(NAME,NEW_CLASS, _setup)
#define FLEXT_LIB_TILDE(NAME,NEW_CLASS) REAL_LIB(NAME,NEW_CLASS, _tilde_setup)
//
// ONE ARGUMENT
/////////////////////////////////////////////////
#define FLEXT_NEW_1(NAME,NEW_CLASS, TYPE) \
REAL_NEW_1(NAME,NEW_CLASS, _setup, TYPE) \
REAL_EXT(NEW_CLASS, _setup)
#define FLEXT_NEW_TILDE_1(NAME,NEW_CLASS, TYPE) \
REAL_NEW_1(NAME,NEW_CLASS, _tilde_setup, TYPE) \
REAL_EXT(NEW_CLASS, _tilde_setup)
#define FLEXT_LIB_1(NAME,NEW_CLASS, TYPE) REAL_LIB_1(NAME,NEW_CLASS, _setup,TYPE)
#define FLEXT_LIB_TILDE_1(NAME,NEW_CLASS, TYPE) REAL_LIB_1(NAME,NEW_CLASS, _tilde_setup, TYPE)
//
// GIMME ARGUMENT
/////////////////////////////////////////////////
#define FLEXT_NEW_G(NAME,NEW_CLASS) \
REAL_NEW_G(NAME,NEW_CLASS, _setup) \
REAL_EXT(NEW_CLASS, _setup)
#define FLEXT_NEW_TILDE_G(NAME,NEW_CLASS) \
REAL_NEW_G(NAME,NEW_CLASS,_tilde_setup) \
REAL_EXT(NEW_CLASS, _tilde_setup)
#define FLEXT_LIB_G(NAME,NEW_CLASS) REAL_LIB_G(NAME,NEW_CLASS, _setup)
#define FLEXT_LIB_TILDE_G(NAME,NEW_CLASS) REAL_LIB_G(NAME,NEW_CLASS, _tilde_setup)
//
// TWO ARGUMENTS
/////////////////////////////////////////////////
#define FLEXT_NEW_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
REAL_NEW_2(NAME,NEW_CLASS, _setup, TYPE1, TYPE2) \
REAL_EXT(NEW_CLASS, _setup)
#define FLEXT_NEW_TILDE_2(NAME,NEW_CLASS, TYPE1, TYPE2) \
REAL_NEW_2(NAME,NEW_CLASS, _tilde_setup, TYPE1, TYPE2) \
REAL_EXT(NEW_CLASS, _tilde_setup)
#define FLEXT_LIB_2(NAME,NEW_CLASS, TYPE1, TYPE2) REAL_LIB_2(NAME,NEW_CLASS, _setup, TYPE1, TYPE2)
#define FLEXT_LIB_TILDE_2(NAME,NEW_CLASS, TYPE1, TYPE2) REAL_LIB_2(NAME,NEW_CLASS, _tilde_setup, TYPE1, TYPE2)
//
// THREE ARGUMENTS
/////////////////////////////////////////////////
#define FLEXT_NEW_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
REAL_NEW_3(NAME,NEW_CLASS, _setup, TYPE1, TYPE2, TYPE3) \
REAL_EXT(NEW_CLASS, _setup)
#define FLEXT_NEW_TILDE_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) \
REAL_NEW_3(NAME,NEW_CLASS, _tilde_setup, TYPE1, TYPE2, TYPE3) \
REAL_EXT(NEW_CLASS, _tilde_setup)
#define FLEXT_LIB_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) REAL_LIB_3(NAME,NEW_CLASS, _setup,TYPE1, TYPE2, TYPE3)
#define FLEXT_LIB_TILDE_3(NAME,NEW_CLASS, TYPE1, TYPE2, TYPE3) REAL_LIB_3(NAME,NEW_CLASS, _tilde_setup, TYPE1, TYPE2, TYPE3)
/*
// MaxMSP doesn't seem to be able to handle more than 3 creation arguments! -> USE GIMME
//
// FOUR ARGUMENTS
/////////////////////////////////////////////////
#define FLEXT_NEW_4(NAME,NEW_CLASS, TYPE, TTWO, TTHREE, TFOUR) \
REAL_NEW_4(NAME,NEW_CLASS, _setup, _class, TYPE, TTWO, TTHREE, TFOUR)
#define FLEXT_NEW_TILDE_4(NAME,NEW_CLASS, TYPE, TTWO, TTHREE, TFOUR) \
REAL_NEW_4(NAME,NEW_CLASS, _tilde_setup, _class, TYPE, TTWO, TTHREE, TFOUR)
*/
//////////////////////////////////////////////////////
// --------------------------------------------------
// This is to be called in the library setup function
//////////////////////////////////////////////////////
// ---------------------------------------------------
#define FLEXT_EXP_0 extern "C" FLEXT_EXT
#define FLEXT_EXP_1
......@@ -332,19 +246,23 @@ extern void cl##_tilde_setup(); \
cl##_tilde_setup()
#ifdef PD
#define FLEXT_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT void NAME##_setup() { SETUPFUN(); }
#else // MAXMSP
#define FLEXT_LIB_SETUP(NAME,SETUPFUN) \
extern "C" FLEXT_EXT int main() { \
SETUPFUN(); \
::setup((t_messlist **)&flext_obj::lib_class,(t_newmethod)&flext_obj::libfun_new,(t_method)flext_obj::libfun_free,sizeof(flext_hdr), 0,A_GIMME,A_NULL); \
return 0; \
}
#endif
////////////////////////////////////////
// ----------------------------------------
// These definitions are used below
////////////////////////////////////////
// ----------------------------------------
// Shortcuts for PD/Max type arguments
#define FLEXTTYPE_void A_NULL
......@@ -404,16 +322,15 @@ return 0; \
#endif
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// These should never be called or used directly!!!
//
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// no args
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST(LIB,NAME,NEW_CLASS, SETUP_FUNCTION) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS () \
......@@ -455,9 +372,9 @@ void NEW_CLASS ## SETUP_FUNCTION() \
}
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// one arg
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST_1(LIB,NAME,NEW_CLASS, SETUP_FUNCTION, TYPE1) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS (TYPE1 arg1) \
......@@ -500,9 +417,9 @@ void NEW_CLASS ## SETUP_FUNCTION() \
}
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// gimme arg
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST_G(LIB,NAME,NEW_CLASS, SETUP_FUNCTION) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS (t_symbol *s,int argc,t_atom *argv) \
......@@ -545,9 +462,9 @@ void NEW_CLASS ## SETUP_FUNCTION() \
}
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// two args
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST_2(LIB,NAME,NEW_CLASS, SETUP_FUNCTION, TYPE1, TYPE2) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS (TYPE1 arg1, TYPE2 arg2) \
......@@ -590,9 +507,9 @@ void NEW_CLASS ## SETUP_FUNCTION() \
}
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// three args
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST_3(LIB,NAME,NEW_CLASS, SETUP_FUNCTION, TYPE1,TYPE2,TYPE3) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS (TYPE1 arg1,TYPE2 arg2,TYPE3 arg3) \
......@@ -634,9 +551,9 @@ void NEW_CLASS ## SETUP_FUNCTION() \
NEW_CLASS::callb_setup(flext_obj::lib_class); \
}
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
// four args
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------
#define REAL_INST_4(LIB,NAME,NEW_CLASS, SETUP_FUNCTION, TYPE1,TYPE2,TYPE3,TYPE4) \
static t_class * NEW_CLASS ## _class; \
flext_hdr* class_ ## NEW_CLASS (TYPE1 arg1,TYPE2 arg2,TYPE3 arg3,TYPE4 arg4) \
......@@ -678,6 +595,19 @@ void NEW_CLASS ## SETUP_FUNCTION() \
NEW_CLASS::callb_setup(flext_obj::lib_class); \
}
// 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_ptrtype a_pointer
#define FLEXTARG(TP) FLEXTARG_ ## TP
#endif
......
/*
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 Declares the user accessible flext base classes
!Lacking Details.!
*/
#ifndef __FLCLASS_H
#define __FLCLASS_H
//! include the header file declaring the base classes
#include <flbase.h>
#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 flext_base
\brief message only base object
*/
class flext_base:
public flext_obj
{
FLEXT_HEADER_S(flext_base,flext_obj,Setup)
public:
// --- 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 --------------------------------
//! 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 void m_method_(int inlet,const t_symbol *s,int argc,t_atom *argv);
// --- buffer/array stuff -----------------------------------------
//! \class 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(t_symbol *s = NULL,bool delayed = false);
//! Destroy buffer
~buffer();
/*! \brief Set to specified buffer.
@param nameonly: if true sets name only, but doesn't look at buffer actually
*/
int Set(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 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
*/
float *Data() { return data; }
//! Get channel count
int Channels() const { return chns; }
//! Get frame count
int Frames() const { return frames; }
//! Graphic auto refresh interval
void SetRefrIntv(float intv);
protected:
t_symbol *sym;
float *data;
int chns,frames;
#ifdef PD
float interval;
bool isdirty,ticking;
t_clock *tick;
private:
static void cb_tick(buffer *b);
#endif
};
// --- inlet/outlet stuff -----------------------------------------
// define inlets/outlets - all (also default) inlets must be defined
// argument m specifies multiple inlet/outlet count
// void AddInDef() { AddInlet(xlet::tp_def,1); }
//! add inlet(s) for anythings
void AddInAnything(int m = 1) { AddInlet(xlet::tp_any,m); } // leftmost or via proxy
//! add inlet(s) for floats
void AddInFloat(int m = 1) { AddInlet(xlet::tp_float,m); }
//! add inlet(s) for flints
void AddInFlint(int m = 1) { AddInlet(xlet::tp_flint,m); }
//! add inlet(s) for symbols
void AddInSymbol(int m = 1) { AddInlet(xlet::tp_sym,m); }
//! add inlet(s) for lists
void AddInList(int m = 1) { AddInlet(xlet::tp_list,m); } // via proxy
//! add outlet(s) for anythings
void AddOutAnything(int m = 1) { AddOutlet(xlet::tp_any,m); }
//! add outlet(s) for floats
void AddOutFloat(int m = 1) { AddOutlet(xlet::tp_float,m); }
//! add outlet(s) for flints
void AddOutFlint(int m = 1) { AddOutlet(xlet::tp_flint,m); }
//! add outlet(s) for symbols
void AddOutSymbol(int m = 1) { AddOutlet(xlet::tp_sym,m); }
//! add outlet(s) for lists
void AddOutList(int m = 1) { AddOutlet(xlet::tp_list,m); }
/*! \brief set up inlets and outlets
\remark Must be called ONCE to actually set up the defined inlets/outlets.
\return True on successful creation of all inlets and outlets
*/
bool SetupInOut();
//! 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;
//! get pointer to outlet (_after_ calling setup_inout()!)
outlet *GetOut(int ix) { return (outlets && ix < outcnt)?outlets[ix]:NULL; }
// output messages (index n starts with 0)
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); }