Commit 3adf5235 authored by thomas's avatar thomas
Browse files

no message


git-svn-id: https://svn.grrrr.org/ext/trunk@47 4d9ac71a-51e6-0310-8455-cad1006bcd31
parent 7fff38ca
......@@ -37,13 +37,21 @@ o Metrowerks CodeWarrior V6: ok
for Max/MSP you will also need the Max/MSP SDK
for PD you need the source code (which is most likely part of the distribution)
----------------------------------------------------------------------------
Features:
- better readability of code compared to straight C externals
- faster development, more robust coding
- sharing of common methods, data by using base classes
----------------------------------------------------------------------------
Version history:
0.1.1:
- more emancipation from GEM code
- renamed virtually everything
- 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
......@@ -60,7 +68,8 @@ Platform restrictions:
- Max does not allow external libraries -> only one FLEXT_NEW* or FLEXT_TILDE_NEW* in a project
Restrictions in compatibility mode:
- Max allows only 9 float inlets
- Max allows only 9 float/int inlets
- Max allows no additional symbol inlets
......
......@@ -16,11 +16,6 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include <flstdc.h>
#ifdef __GNUC__
#include <typeinfo>
#else
#include <typeinfo.h>
#endif
class flext_obj;
......@@ -129,7 +124,7 @@ class FLEXT_EXT flext_obj
//////////
// This is a holder - don't touch it
static t_sigobj *m_holder;
static const char *m_holdname;
static const char *m_holdname; // hold object's name during construction
//////////
// The object's name in the patcher
......@@ -171,6 +166,8 @@ static void cb_setup(t_class *classPtr);
// Shortcuts for PD/Max type arguments
#define FLEXTTYPE_F A_FLOAT
#define FLEXTTYPE_float A_FLOAT
#define FLEXTTYPE_FI A_FLINT
#define FLEXTTYPE_flint A_FLINT
#define FLEXTTYPE_t_symbol A_SYMBOL
#define FLEXTTYPE_t_pointer A_POINTER
......@@ -267,7 +264,7 @@ static void cb_setup(t_class *classPtr);
#define FLEXT_CLREF(NAME,CLASS) gensym(NAME)
#define FLEXT_MAIN(MAINNAME) MAINNAME
#elif defined(MAXMSP)
#define FLEXT_NEWFN NULL; ::setup
#define FLEXT_NEWFN NULL; ::setup // very bad!!! I hope Mark Danks doesn't see that......
#define FLEXT_CLREF(NAME,CLASS) (t_messlist **)&(CLASS)
#define FLEXT_MAIN(MAINNAME) main
#endif
......
......@@ -14,7 +14,7 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#define DIRTY_INTERVAL 0 // buffer dirty check in msec
#endif
flext_base::buffer::buffer(t_symbol *bn):
flext_base::buffer::buffer(t_symbol *bn,BL delayed):
sym(NULL),data(NULL),
chns(0),frames(0)
{
......@@ -25,7 +25,7 @@ flext_base::buffer::buffer(t_symbol *bn):
tick = clock_new(this,(t_method)cb_tick);
#endif
if(bn) Set(bn);
if(bn) Set(bn,delayed);
}
flext_base::buffer::~buffer()
......@@ -35,7 +35,7 @@ flext_base::buffer::~buffer()
#endif
}
I flext_base::buffer::Set(t_symbol *s)
I flext_base::buffer::Set(t_symbol *s,BL nameonly)
{
I ret = 0;
......@@ -48,7 +48,7 @@ I flext_base::buffer::Set(t_symbol *s)
if(s && *s->s_name) sym = s;
if(sym) {
if(sym && !nameonly) {
#ifdef PD
I frames1;
F *data1;
......@@ -63,7 +63,7 @@ I flext_base::buffer::Set(t_symbol *s)
}
else if (!garray_getfloatarray(a, &frames1, &data1))
{
error("%s: bad template '%s'", thisName(),sym->s_name);
error("buffer: bad template '%s'", sym->s_name);
data = NULL;
frames = 0;
ret = -1;
......@@ -79,7 +79,7 @@ I flext_base::buffer::Set(t_symbol *s)
const _buffer *p = (const _buffer *)sym->s_thing;
if(NOGOOD(p)) {
post("%s: buffer object '%s' no good",thisName(),sym->s_name);
post("buffer: buffer object '%s' no good",sym->s_name);
ret = -1;
}
else {
......@@ -92,7 +92,7 @@ I flext_base::buffer::Set(t_symbol *s)
}
}
else {
error("%s: symbol '%s' not defined",thisName(), sym->s_name);
error("buffer: symbol '%s' not defined", sym->s_name);
ret = -1;
}
#endif
......@@ -117,14 +117,14 @@ V flext_base::buffer::Dirty(BL force)
_buffer *p = (_buffer *)sym->s_thing;
if(NOGOOD(p)) {
post("%s: buffer object '%s' no good",thisName(),sym->s_name);
post("buffer: buffer object '%s' no good",sym->s_name);
}
else {
p->b_modtime = gettime();
}
}
else {
error("%s: symbol '%s' not defined",thisName(),sym->s_name);
error("buffer: symbol '%s' not defined",sym->s_name);
}
#endif
}
......
No preview for this file type
......@@ -81,23 +81,25 @@ BL flext_base::setup_inout()
case xlet::tp_flint: {
C sym[] = "ft??";
if(ix >= 10) {
#ifdef MAXMSP
post("%s: Only 9 float inlets possible",thisName());
#else
if(compatibility)
// Max allows max. 9 inlets
post("%s: Only 9 float inlets allowed in compatibility mode",thisName());
ok = false;
else
sym[2] = '0'+ix/10,sym[3] = '0'+ix%10;
#endif
}
else
sym[2] = '0'+ix,sym[3] = 0;
inlet_new(x_obj, &x_obj->ob_pd, &s_float, gensym(sym));
if(ok) inlet_new(x_obj, &x_obj->ob_pd, &s_float, gensym(sym));
break;
}
case xlet::tp_sym:
inlet_new(x_obj, &x_obj->ob_pd, &s_symbol, &s_symbol);
if(compatibility) {
post("%s: No symbol inlets (apart from leftmost) in compatibility mode",thisName());
ok = false;
}
else
inlet_new(x_obj, &x_obj->ob_pd, &s_symbol, &s_symbol);
break;
case xlet::tp_sig:
inlet_new(x_obj, &x_obj->ob_pd, &s_signal, &s_signal);
......@@ -118,10 +120,20 @@ BL flext_base::setup_inout()
for(ix = incnt-1; ix >= insigs; --ix) {
switch(list[ix]) {
case xlet::tp_float:
floatin(x_obj,ix);
if(ix >= 10) {
post("%s: Only 9 float inlets possible",thisName());
ok = false;
}
else
floatin(x_obj,ix);
break;
case xlet::tp_flint:
intin(x_obj,ix);
if(ix >= 10) {
post("%s: Only 9 flint inlets possible",thisName());
ok = false;
}
else
intin(x_obj,ix);
break;
case xlet::tp_sig:
error("%s: Signal inlets must be at the left side",thisName());
......@@ -205,16 +217,16 @@ V flext_base::cb_setup(t_class *c)
{
add_method(c,cb_help,"help");
#ifdef MAXMSP
add_loadbang(c,cb_loadbang);
#ifdef MAXMSP
add_assist(c,cb_assist);
#endif
}
V flext_base::cb_help(V *c) { thisObject(c)->m_help(); }
#ifdef MAXMSP
V flext_base::cb_loadbang(V *c) { thisObject(c)->m_loadbang(); }
#ifdef MAXMSP
V flext_base::cb_assist(V *c,V * /*b*/,L msg,L arg,C *s) { thisObject(c)->m_assist(msg,arg,s); }
#endif
......@@ -274,7 +286,7 @@ V flext_dsp::cb_dsp(V *c,t_signal **sp)
obj->outvecs = new F *[out];
for(i = 0; i < out; ++i) obj->outvecs[i] = sp[in+i]->s_vec;
// with the following call derived classes can do some DSP setup
// 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
......
......@@ -14,7 +14,22 @@ WARRANTIES, see the file, "license.txt," in this distribution.
#include <flbase.h>
// ----------------------------
// a few type definitions for the lazy
#define F float
#define D double
#define I int
#define L long
#define C char
#define BL bool
#define V void
#define FI t_flint
// === flext_base ==================================================
// message only base object
class flext_base:
public flext_obj
......@@ -22,13 +37,16 @@ class flext_base:
FLEXT_HEADER(flext_base,flext_obj)
public:
// compatibility mode: flext allows only operations valid for all platforms
// true by default
// --- compatibility mode ----------------------------------------
// if set flext allows only operations valid for all platforms
// true by default!
static BL compatibility;
flext_base();
virtual ~flext_base();
// --- inheritable virtual methods --------------------------------
// called on "help" message: should post some text
virtual V m_help();
......@@ -38,22 +56,38 @@ public:
// quickhelp for inlets/outlets (Max/MSP only)
virtual V m_assist(L /*msg*/,L /*arg*/,C * /*s*/) {}
// --- buffer/array stuff -----------------------------------------
// class for platform independent buffer handling
class buffer
{
public:
buffer(t_symbol *s = NULL);
// construct buffer
// delayed = true: needs another Set(NULL) to initialize the buffer
// (in Max the externals are often created prior to the buffer objects)
buffer(t_symbol *s = NULL,BL delayed = false);
~buffer();
I Set(t_symbol *s = NULL);
V Dirty(BL force = false);
// set to another buffer
// nameonly = true: sets name only, no buffer data
I Set(t_symbol *s = NULL,BL nameonly = false);
// dirty buffer content
// refr = true: forces immediate graphics refresh
V Dirty(BL refr = false);
// get symbol (or literal name) of buffer
t_symbol *Symbol() { return sym; }
const C *Name() const { return sym?sym->s_name:""; }
// get pointer to buffer, channel and frame count
F *Data() { return data; }
I Channels() const { return chns; }
I Frames() const { return frames; }
// graphic auto refresh interval
#ifdef PD
V SetRefrIntv(F intv) { interval = intv; }
#else
......@@ -61,8 +95,6 @@ public:
#endif
protected:
const C *thisName() const { return typeid(*this).name(); }
t_symbol *sym;
F *data;
I chns,frames;
......@@ -76,9 +108,10 @@ public:
#endif
};
protected:
// inlets/outlets - all (also default) inlets must be defined
// --- inlet/outlet stuff -----------------------------------------
// define inlets/outlets - all (also default) inlets must be defined
V add_in_def() { AddInlet(xlet::tp_def,1); }
V add_in_float(I m = 1) { AddInlet(xlet::tp_float,m); }
V add_in_flint(I m = 1) { AddInlet(xlet::tp_flint,m); }
......@@ -101,6 +134,36 @@ protected:
// get pointer _after_wards
t_outlet *get_out(I ix) { return (outlets && ix < outcnt)?outlets[ix]:NULL; }
// output messages
V to_out_float(t_outlet *o,F f) { outlet_float(o,f); }
V to_out_float(I n,F f) { t_outlet *o = get_out(n); if(o) to_out_float(o,f); }
V to_out_flint(t_outlet *o,FI f) { outlet_flint(o,f); }
V to_out_flint(I n,FI f) { t_outlet *o = get_out(n); if(o) to_out_flint(o,f); }
V to_out_symbol(t_outlet *o,t_symbol *s);
V to_out_symbol(I n,t_symbol *s) { t_outlet *o = get_out(n); if(o) to_out_symbol(o,s); }
V to_out_list(t_outlet *o,I argc,t_atom *argv);
V to_out_list(I n,I argc,t_atom *argv) { t_outlet *o = get_out(n); if(o) to_out_list(o,argc,argv); }
V to_out_anything(t_outlet *o,I argc,t_atom *argv);
V to_out_anything(I n,I argc,t_atom *argv) { t_outlet *o = get_out(n); if(o) to_out_anything(o,argc,argv); }
// --- argument list stuff ----------------------------------------
// --- list creation stuff ----------------------------------------
// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
protected:
flext_base();
virtual ~flext_base();
private:
friend class flext_dsp;
struct xlet {
enum type {
tp_none = 0,tp_def,tp_float,tp_flint,tp_sym,tp_list,tp_sig
......@@ -116,27 +179,27 @@ protected:
V AddInlet(xlet::type tp,I mult) { AddXlet(tp,mult,inlist); }
V AddOutlet(xlet::type tp,I mult) { AddXlet(tp,mult,outlist); }
private:
xlet *inlist,*outlist;
I incnt,outcnt,insigs,outsigs;
t_outlet **outlets;
V AddXlet(xlet::type tp,I mult,xlet *&root);
// callback functions
static V cb_help(V *c);
#ifdef MAXMSP
static V cb_loadbang(V *c);
#ifdef MAXMSP
static V cb_assist(V *c,V *b,L msg,L arg,C *s);
#endif
};
// ----------------------------
// === flext_dsp ==================================================
// ----------------------------
// dsp enabled base object
class flext_dsp:
public flext_base
......@@ -144,9 +207,13 @@ class flext_dsp:
FLEXT_HEADER(flext_dsp,flext_base)
public:
flext_dsp();
~flext_dsp();
// returns current sample rate
F samplerate() const { return srate; }
// --- inheritable virtual methods --------------------------------
// called on every dsp init
virtual V m_dsp(I n,F *const *insigs,F *const *outsigs);
......@@ -155,26 +222,35 @@ public:
// called with "enable" message: pauses/resumes dsp
virtual V m_enable(BL on);
// returns current sample rate
F samplerate() const { return srate; }
protected:
// --- inlet/outlet stuff -----------------------------------------
// add signal inlet
V add_in_signal(I m = 1) { AddInlet(xlet::tp_sig,m); }
// add signal outlet
V add_out_signal(I m = 1) { AddOutlet(xlet::tp_sig,m); }
protected:
flext_dsp();
~flext_dsp();
private:
F srate;
BL enable;
// callback functions
static V cb_dsp(V *c,t_signal **s);
static V cb_enable(V *c,FI on);
// dsp stuff
static t_int *dspmeth(t_int *w);
F **invecs,**outvecs;
};
......
......@@ -16,16 +16,9 @@ once drifted apart in Max and PD. It is not elegant but helps.
#ifndef __FLSTDC_H
#define __FLSTDC_H
#define F float
#define D double
#define I int
#define L long
#define C char
#define BL bool
#define V void
#define BIGFLOAT 1.e10
#define BIGLONG 0x7fffffffL
#ifdef __cplusplus
// namespace std {
#endif
#if !defined(PD) && !defined(MAXMSP)
#error Either PD or MAXMSP must be defined
......@@ -71,6 +64,8 @@ typedef t_float t_flint;
#define newout_list(clss) outlet_new(clss,&s_list)
#define newout_symbol(clss) outlet_new(clss,&s_symbol)
#define outlet_flint(o,v) outlet_float(o,v)
#elif defined(MAXMSP)
......@@ -125,9 +120,9 @@ typedef _outlet t_outlet;
#define newout_list(clss) outlet_new(clss,"list")
#define newout_symbol(clss) outlet_new(clss,"symbol")
#endif
#define outlet_flint(o,v) outlet_int(o,v)
#define FI t_flint
#endif
#ifdef _LOG
......@@ -138,12 +133,12 @@ typedef _outlet t_outlet;
#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
#define LOG(s) ((V)0)
#define LOG1(s,v1) ((V)0)
#define LOG2(s,v1,v2) ((V)0)
#define LOG3(s,v1,v2,v3) ((V)0)
#define LOG4(s,v1,v2,v3,v4) ((V)0)
#define LOG5(s,v1,v2,v3,v4,v5) ((V)0)
#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
......@@ -153,6 +148,11 @@ typedef _outlet t_outlet;
#define FLEXT_EXT
#endif
#ifdef __cplusplus
// } // namespace std
#endif
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment