flext 0.6.2
flbase.h
Go to the documentation of this file.
1/*
2flext - C++ layer for Max and Pure Data externals
3
4Copyright (c) 2001-2015 Thomas Grill (gr@grrrr.org)
5For information on usage and redistribution, and for a DISCLAIMER OF ALL
6WARRANTIES, see the file, "license.txt," in this distribution.
7*/
8
15#ifndef __FLEXT_BASE_H
16#define __FLEXT_BASE_H
17
18#include "flstdc.h"
19#include "flsupport.h"
20#include <map>
21
22#include "flpushns.h"
23
25
26typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) flext_obj;
27
28// ----------------------------------------------------------------------------
36// ----------------------------------------------------------------------------
37
39{
48 t_sigobj obj;
49
50#if FLEXT_SYS == FLEXT_SYS_PD
52 t_float defsig;
53#endif
54
55#if FLEXT_SYS == FLEXT_SYS_MAX
57 long curinlet;
58#endif
59
62 FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *data;
63
65};
66
67
69
70typedef std::map<const t_symbol *,FLEXT_TEMPINST(flext_class) *> LibMap;
71
72class flext_library;
73
74// ----------------------------------------------------------------------------
95// ----------------------------------------------------------------------------
96
98class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj):
99 public flext
100{
101 public:
102
103// --- creation -------------------------------------------------------
104
110 FLEXT_CLASSDEF(flext_obj)();
111
113 virtual ~FLEXT_CLASSDEF(flext_obj)();
114
118 static void InitProblem() { init_ok = false; }
119
123// static void ProcessAttributes(bool attr); //{ process_attributes = attr; }
124
126 // this also guarantees that there are no instances of flext_obj
127 virtual bool Init();
128
130 virtual bool Finalize();
131
133 virtual void Exit();
134
136
137// --- info -------------------------------------------------------
138
144 t_canvas *thisCanvas() const { return m_canvas; }
145
147 t_sigobj *thisHdr() { FLEXT_ASSERT(x_obj); return &x_obj->obj; }
148 const t_sigobj *thisHdr() const { FLEXT_ASSERT(x_obj); return &x_obj->obj; }
150 const char *thisName() const { return GetString(m_name); }
152 const t_symbol *thisNameSym() const { return m_name; }
154 t_class *thisClass() const;
155
157 typedef FLEXT_TEMPINST(flext_class) *t_classid;
158
160 t_classid thisClassId() const { return clss; }
161
163 static t_class *getClass(t_classid id);
164
165 static bool HasAttributes(t_classid id);
166 static bool IsDSP(t_classid id);
167 static bool HasDSPIn(t_classid id);
168 static bool IsLib(t_classid id);
169
170 bool HasAttributes() const;
171 bool IsLib() const;
172 bool IsDSP() const;
173 bool HasDSPIn() const;
174
175#if FLEXT_SYS == FLEXT_SYS_MAX
176 // under Max/MSP it could be necessary to activate DSP also for message objects
177 // namely for those coexisting with DSP objects in a library
178 bool NeedDSP() const;
179#endif
180
182
183// --- help -------------------------------------------------------
184
193 static void DefineHelp(t_classid c,const char *ref,const char *dir = NULL,bool addtilde = false);
194
196 void DefineHelp(const char *ref,const char *dir = NULL,bool addtilde = false) { DefineHelp(thisClassId(),ref,dir,addtilde); }
197
199
200
201// --- internal stuff -------------------------------------------------------
202
208 protected:
209
211 mutable flext_hdr *x_obj;
212
215
216// static bool process_attributes;
217
218#if FLEXT_SYS == FLEXT_SYS_MAX
219 t_critical lock;
220 void Lock() { critical_enter(lock); }
221 void Unlock() { critical_exit(lock); }
222 static void SysLock() { critical_enter(0); }
223 static void SysUnlock() { critical_exit(0); }
224#elif FLEXT_SYS == FLEXT_SYS_PD
225 void Lock() {}
226 void Unlock() {}
227 static void SysLock() {}
228 static void SysUnlock() {}
229#else
230 #error
231#endif
232
233 class Locker
234 {
235 public:
236 Locker(flext_obj *o = NULL): obj(o) { if(obj) obj->Lock(); else SysLock(); }
237 Locker(flext_hdr *h): obj(h->data) { FLEXT_ASSERT(obj); obj->Lock(); }
238 ~Locker() { if(obj) obj->Unlock(); else SysUnlock(); }
239 protected:
240 flext_obj *obj;
241 };
242
243 private:
244
246 mutable t_canvas *m_canvas;
247
249 static bool init_ok;
250
251 // flags for init and exit procedure;
252 static bool initing;
253 static bool exiting;
254
255 public:
256
258 static void __setup__(t_classid);
259
263 static flext_hdr *m_holder;
265 static FLEXT_TEMPINST(flext_class) *m_holdclass;
267 static const t_symbol *m_holdname;
268
270 static int m_holdaargc;
271 static const t_atom *m_holdaargv;
272
276 const t_symbol *m_name;
277
281 static bool Initing() { return initing; }
282
284 static bool Exiting() { return exiting; }
285
286 // Definitions for library objects
287 static void lib_init(const char *name,void setupfun());
288 static void obj_add(bool lib,bool dsp,bool noi,bool attr,const char *idname,const char *names,void setupfun(t_classid),FLEXT_CLASSDEF(flext_obj) *(*newfun)(int,t_atom *),void (*freefun)(flext_hdr *),int argtp1,...);
289
290#if FLEXT_SYS == FLEXT_SYS_MAX
291 static flext_hdr *obj_new(const t_symbol *s,short argc,t_atom *argv);
292#else
293 static flext_hdr *obj_new(const t_symbol *s,int argc,t_atom *argv);
294#endif
295 static void obj_free(flext_hdr *o);
296
298 static bool GetParamSym(t_atom &dst,const t_symbol *s,t_canvas *c);
299
301 void GetCanvasArgs(AtomList &args) const;
302
304 void GetCanvasDir(char *buf,size_t bufsz) const;
305
306 protected:
307
308 // Current library class
309 static flext_library *curlib;
310
311 // static initialization (with constructor) doesn't work for Codewarrior
312 static LibMap *libnames;
313
314 static FLEXT_TEMPINST(flext_class) *FindName(const t_symbol *s,FLEXT_TEMPINST(flext_class) *o = NULL);
315
316#if FLEXT_SYS == FLEXT_SYS_PD
317 static t_class *buf_class;
318 static void cb_buffer_dsp(void *c,t_signal **sp);
319#endif
320
321#if FLEXT_SYS == FLEXT_SYS_MAX
322 static const t_symbol *sym__shP;
323#endif
324
326};
327
328
329// max. 4 creation args (see the following macros)
330#define FLEXT_MAXNEWARGS 4
331
332// max. 5 method args (see the following macros)
333#define FLEXT_MAXMETHARGS 5
334
335// prefixes for the macro generated handler functions
336#define FLEXT_CALL_PRE(F) flext_c_##F
337#define FLEXT_THR_PRE(F) flext_t_##F
338#define FLEXT_GET_PRE(F) flext_g_##F
339#define FLEXT_SET_PRE(F) flext_s_##F
340
341
342#ifndef FLEXT_ATTRIBUTES
347#define FLEXT_ATTRIBUTES \
348\
3490
350
351
352#elif FLEXT_ATTRIBUTES != 0 && FLEXT_ATTRIBUTES != 1
353#error "FLEXT_ATTRIBUTES must be 0 or 1"
354#endif
355
356// ----------------------------------------
357// These should be used in the header
358// ----------------------------------------
359
360
361#define FLEXT_REALHDR(NEW_CLASS, PARENT_CLASS) \
362public: \
363typedef NEW_CLASS thisType; \
364typedef PARENT_CLASS thisParent; \
365static FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *__init__(int argc,t_atom *argv); \
366static void __free__(flext_hdr *hdr) { delete hdr->data; } \
367static void __setup__(flext_obj::t_classid classid) { thisParent::__setup__(classid); }
368
369
370#define FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
371public: \
372typedef NEW_CLASS thisType; \
373typedef PARENT_CLASS thisParent; \
374static FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *__init__(int argc,t_atom *argv); \
375static void __free__(flext_hdr *hdr) { delete hdr->data; } \
376static void __setup__(flext_obj::t_classid classid) { \
377 thisParent::__setup__(classid); \
378 thisType::SETUPFUN(classid); \
379}
380
381#define FLEXT_REALHDR_T(NEW_CLASS, PARENT_CLASS) \
382public: \
383typedef NEW_CLASS thisType; \
384typedef PARENT_CLASS thisParent; \
385typedef typename thisParent::t_classid t_classid; \
386static FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *__init__(int argc,t_atom *argv); \
387static void __free__(flext_hdr *hdr) { delete hdr->data; } \
388static void __setup__(flext_obj::t_classid classid) { thisParent::__setup__(classid); }
389
390
391#define FLEXT_REALHDR_TS(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
392public: \
393typedef NEW_CLASS thisType; \
394typedef PARENT_CLASS thisParent; \
395typedef typename thisParent::t_classid t_classid; \
396static FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *__init__(int argc,t_atom *argv); \
397static void __free__(flext_hdr *hdr) { delete hdr->data; } \
398static void __setup__(flext_obj::t_classid classid) { \
399 thisParent::__setup__(classid); \
400 thisType::SETUPFUN(classid); \
401}
402
403
404// generate name of dsp/non-dsp setup function
405#if defined(FLEXT_USE_HEX_SETUP_NAME) && defined(FLEXT_SYS_PD)
406 #define FLEXT_STPF_0(NAME) setup_##NAME
407 #define FLEXT_STPF_1(NAME) setup_##NAME
408#elif FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX
409 #define FLEXT_STPF_0(NAME) NAME##_setup
410 #define FLEXT_STPF_1(NAME) NAME##_tilde_setup
411#else
412#error Platform not supported
413#endif
414
415#define FLEXT_STPF_(DSP) FLEXT_STPF_##DSP
416#define FLEXT_STPF(NAME,DSP) FLEXT_STPF_(DSP)(NAME)
417
418
419// --------------------------------------------------------------------------------------
420
421
422// used in library setup functions to register the individual objects in the library
423#define REAL_SETUP(cl,DSP) extern void FLEXT_STPF(cl,DSP)(); FLEXT_STPF(cl,DSP)();
424
425#ifdef FLEXT_USE_NAMESPACE
426 #define _FLEXT_REAL_SETUP_NAME(NAME) ::##NAME##_setup
427#else
428 #define _FLEXT_REAL_SETUP_NAME(NAME) NAME##_setup
429#endif
430
431// specify that to define the library itself
432#if FLEXT_SYS == FLEXT_SYS_PD
433# define REAL_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT void _FLEXT_REAL_SETUP_NAME(NAME)() { flext_obj::lib_init(#NAME,SETUPFUN); }
434#elif FLEXT_SYS == FLEXT_SYS_MAX
435# define REAL_LIB_SETUP(NAME,SETUPFUN) extern "C" FLEXT_EXT int main() { flext_obj::lib_init(#NAME,SETUPFUN); return 0; }
436#else
437# error Platform not supported
438#endif
439
440
441// --------------------------------------------------
442
443
444#define FLEXT_EXP_0 extern "C" FLEXT_EXT
445#define FLEXT_EXP_1
446#define FLEXT_EXP(LIB) FLEXT_EXP_##LIB
447
448#if FLEXT_SYS == FLEXT_SYS_PD
449#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP)
450#elif FLEXT_SYS == FLEXT_SYS_MAX
451#define FLEXT_OBJ_SETUP_0(NEW_CLASS,DSP) extern "C" FLEXT_EXT int main() { FLEXT_STPF(NEW_CLASS,DSP)(); return 0; }
452#else
453#error not implemented
454#endif
455
456#define FLEXT_OBJ_SETUP_1(NEW_CLASS,DSP)
457
458#define FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB) FLEXT_OBJ_SETUP_##LIB(NEW_CLASS,DSP)
459
460
461
462// ----------------------------------------
463// These definitions are used below
464// ----------------------------------------
465
466#if FLEXT_SYS == FLEXT_SYS_PD || FLEXT_SYS == FLEXT_SYS_MAX
467 // maybe that's not necessary
468 #define FLEXTTPN_NULL A_NULL
469 #if FLEXT_SYS == FLEXT_SYS_PD
470 #define FLEXTTPN_PTR A_POINTER
471 #else
472 #define FLEXTTPN_INT A_INT
473 #define FLEXTTPN_DEFINT A_DEFINT
474 #endif
475 #define FLEXTTPN_FLOAT A_FLOAT
476 #define FLEXTTPN_DEFFLOAT A_DEFFLOAT
477 #define FLEXTTPN_SYM A_SYMBOL
478 #define FLEXTTPN_DEFSYM A_DEFSYMBOL
479 #define FLEXTTPN_VAR A_GIMME
480#else
481 #define FLEXTTPN_NULL 0
482 #define FLEXTTPN_PTR 1
483 #define FLEXTTPN_INT 2
484 #define FLEXTTPN_FLOAT 3
485 #define FLEXTTPN_SYM 4
486 #define FLEXTTPN_VAR 5
487 #define FLEXTTPN_DEFINT 6
488 #define FLEXTTPN_DEFFLOAT 7
489 #define FLEXTTPN_DEFSYM 8
490#endif
491
492// Shortcuts for PD/Max type arguments
493#define FLEXTTYPE_void FLEXTTPN_NULL
494#define CALLBTYPE_void void
495#define FLEXTTYPE_float FLEXTTPN_FLOAT
496#define FLEXTTYPE_float0 FLEXTTPN_DEFFLOAT
497#define CALLBTYPE_float float
498#define FLEXTTYPE_t_float FLEXTTPN_FLOAT
499#define CALLBTYPE_t_float t_float
500
501#if FLEXT_SYS == FLEXT_SYS_PD
502#define FLEXTTYPE_int FLEXTTPN_FLOAT
503#define FLEXTTYPE_int0 FLEXTTPN_DEFFLOAT
504#define CALLBTYPE_int float
505#define FLEXTTYPE_bool FLEXTTPN_FLOAT
506#define FLEXTTYPE_bool0 FLEXTTPN_DEFFLOAT
507#define CALLBTYPE_bool float
508#elif FLEXT_SYS == FLEXT_SYS_MAX
509#define FLEXTTYPE_int FLEXTTPN_INT
510#define FLEXTTYPE_int0 FLEXTTPN_DEFINT
511#define CALLBTYPE_int int
512#define FLEXTTYPE_bool FLEXTTPN_INT
513#define FLEXTTYPE_bool0 FLEXTTPN_DEFINT
514#define CALLBTYPE_bool int
515#else
516#error Platform not supported
517#endif
518
519#define FLEXTTYPE_t_symptr FLEXTTPN_SYM
520#define FLEXTTYPE_t_symptr0 FLEXTTPN_DEFSYM
521#define CALLBTYPE_t_symptr t_symptr
522#define FLEXTTYPE_t_symtype FLEXTTYPE_t_symptr
523#define FLEXTTYPE_t_symtype0 FLEXTTYPE_t_symptr0
524#define CALLBTYPE_t_symtype t_symptr
525#define FLEXTTYPE_t_ptrtype FLEXTTPN_PTR
526#define CALLBTYPE_t_ptrtype t_ptrtype
527
528#define FLEXTTP(TP) FLEXTTYPE_ ## TP
529#define CALLBTP(TP) CALLBTYPE_ ## TP
530
531
532#define ARGMEMBER_bool(a) GetBool(a)
533#define ARGMEMBER_bool0(a) ARGMEMBER_bool(a)
534#define ARGMEMBER_int(a) GetInt(a)
535#define ARGMEMBER_int0(a) ARGMEMBER_int(a)
536#define ARGMEMBER_float(a) GetFloat(a)
537#define ARGMEMBER_float0(a) ARGMEMBER_float(a)
538#define ARGMEMBER_t_symptr(a) GetSymbol(a)
539#define ARGMEMBER_t_symptr0(a) ARGMEMBER_t_symptr(a)
540#define ARGMEMBER_t_symtype(a) ARGMEMBER_t_symptr(a)
541#define ARGMEMBER_t_symtype0(a) ARGMEMBER_t_symptr0(a)
542#define ARGCAST(a,tp) ARGMEMBER_##tp(a)
543
544#define REAL_NEW(NAME,NEW_CLASS,DSP,NOI,LIB) \
545flext_obj *NEW_CLASS::__init__(int ,t_atom *) \
546{ \
547 return new NEW_CLASS; \
548} \
549FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
550{ \
551 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,FLEXTTPN_NULL); \
552} \
553FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
554
555#define REAL_NEW_V(NAME,NEW_CLASS,DSP,NOI,LIB) \
556flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
557{ \
558 return new NEW_CLASS(argc,argv); \
559} \
560FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
561{ \
562 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,&NEW_CLASS::__free__,FLEXTTPN_VAR,FLEXTTPN_NULL); \
563} \
564FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
565
566#define REAL_NEW_1(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1) \
567flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
568{ \
569 return new NEW_CLASS(ARGCAST(argv[0],TYPE1)); \
570} \
571FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
572{ \
573 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTPN_NULL); \
574} \
575FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
576
577#define REAL_NEW_2(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1,TYPE2) \
578flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
579{ \
580 return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2)); \
581} \
582FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
583{ \
584 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTPN_NULL); \
585} \
586FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
587
588#define REAL_NEW_3(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1, TYPE2, TYPE3) \
589flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
590{ \
591 return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3)); \
592} \
593FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
594{ \
595 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),FLEXTTPN_NULL); \
596} \
597FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
598
599#define REAL_NEW_4(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1,TYPE2, TYPE3, TYPE4) \
600flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
601{ \
602 return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2),ARGCAST(argv[2],TYPE3),ARGCAST(argv[3],TYPE4)); \
603} \
604FLEXT_EXP(LIB) void FLEXT_STPF(NEW_CLASS,DSP)() \
605{ \
606 flext_obj::obj_add(LIB,DSP,NOI,FLEXT_ATTRIBUTES,#NEW_CLASS,NAME,NEW_CLASS::__setup__,NEW_CLASS::__init__,NEW_CLASS::__free__,FLEXTTP(TYPE1),FLEXTTP(TYPE2),FLEXTTP(TYPE3),FLEXTTP(TYPE4),FLEXTTPN_NULL); \
607} \
608FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
609
610
611// Shortcuts for method arguments:
612#define FLEXTARG_float a_float
613#define FLEXTARG_int a_int
614#define FLEXTARG_bool a_int
615#define FLEXTARG_t_float a_float
616#define FLEXTARG_t_symtype a_symbol
617#define FLEXTARG_t_symptr a_symbol
618#define FLEXTARG_t_ptrtype a_pointer
619
620#define FLEXTARG(TP) FLEXTARG_ ## TP
621
622#include "flpopns.h"
623
624#endif
Definition fllib.cpp:140
Definition fllib.cpp:118
std::map< const t_symbol *, FLEXT_TEMPINST(flext_class) * > LibMap
Definition flbase.h:70
#define FLEXT_TEMPINST(fun)
Definition flprefix.h:455
#define FLEXT_SHARE
Definition flprefix.h:416
#define FLEXT_CLASSDEF(CL)
Definition flprefix.h:381
#define FLEXT_TEMPLATE
Definition flprefix.h:453
Definitions to unite Max/MSP and PD notions.
#define FLEXT_ASSERT(b)
Definition flstdc.h:316
flext support functions and classes
t_sigobj obj
The obligatory object header.
Definition flbase.h:48
FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *data
This points to the actual polymorphic C++ class.
The obligatory PD or Max/MSP object header.
Definition flbase.h:39