flext  0.6.0
flbase.h
Go to the documentation of this file.
1 /*
2 flext - C++ layer for Max and Pure Data externals
3 
4 Copyright (c) 2001-2015 Thomas Grill (gr@grrrr.org)
5 For information on usage and redistribution, and for a DISCLAIMER OF ALL
6 WARRANTIES, 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 
26 typedef 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
51  float defsig;
53 #endif
54 
55 #if FLEXT_SYS == FLEXT_SYS_MAX
56  long curinlet;
58 #endif
59 
62  FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) *data;
63 
65 };
66 
67 
69 
70 typedef std::map<const t_symbol *,FLEXT_TEMPINST(flext_class) *> LibMap;
71 
72 class flext_library;
73 
74 // ----------------------------------------------------------------------------
95 // ----------------------------------------------------------------------------
96 
98 class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj):
99  public flext
100 {
101  public:
102 
103 // --- creation -------------------------------------------------------
104 
109  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 
143  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
343 
347 #define FLEXT_ATTRIBUTES \
348 \
349 0
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) \
362 public: \
363 typedef NEW_CLASS thisType; \
364 typedef PARENT_CLASS thisParent; \
365 static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \
366 static void __free__(flext_hdr *hdr) { delete hdr->data; } \
367 static void __setup__(flext_obj::t_classid classid) { thisParent::__setup__(classid); }
368 
369 
370 #define FLEXT_REALHDR_S(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
371 public: \
372 typedef NEW_CLASS thisType; \
373 typedef PARENT_CLASS thisParent; \
374 static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \
375 static void __free__(flext_hdr *hdr) { delete hdr->data; } \
376 static 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) \
382 public: \
383 typedef NEW_CLASS thisType; \
384 typedef PARENT_CLASS thisParent; \
385 typedef typename thisParent::t_classid t_classid; \
386 static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \
387 static void __free__(flext_hdr *hdr) { delete hdr->data; } \
388 static void __setup__(flext_obj::t_classid classid) { thisParent::__setup__(classid); }
389 
390 
391 #define FLEXT_REALHDR_TS(NEW_CLASS, PARENT_CLASS,SETUPFUN) \
392 public: \
393 typedef NEW_CLASS thisType; \
394 typedef PARENT_CLASS thisParent; \
395 typedef typename thisParent::t_classid t_classid; \
396 static FLEXT_CLASSDEF(flext_obj) *__init__(int argc,t_atom *argv); \
397 static void __free__(flext_hdr *hdr) { delete hdr->data; } \
398 static 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) \
545 flext_obj *NEW_CLASS::__init__(int ,t_atom *) \
546 { \
547  return new NEW_CLASS; \
548 } \
549 FLEXT_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 } \
553 FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
554 
555 #define REAL_NEW_V(NAME,NEW_CLASS,DSP,NOI,LIB) \
556 flext_obj *NEW_CLASS::__init__(int argc,t_atom *argv) \
557 { \
558  return new NEW_CLASS(argc,argv); \
559 } \
560 FLEXT_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 } \
564 FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
565 
566 #define REAL_NEW_1(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1) \
567 flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
568 { \
569  return new NEW_CLASS(ARGCAST(argv[0],TYPE1)); \
570 } \
571 FLEXT_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 } \
575 FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
576 
577 #define REAL_NEW_2(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1,TYPE2) \
578 flext_obj *NEW_CLASS::__init__(int,t_atom *argv) \
579 { \
580  return new NEW_CLASS(ARGCAST(argv[0],TYPE1),ARGCAST(argv[1],TYPE2)); \
581 } \
582 FLEXT_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 } \
586 FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
587 
588 #define REAL_NEW_3(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1, TYPE2, TYPE3) \
589 flext_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 } \
593 FLEXT_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 } \
597 FLEXT_OBJ_SETUP(NEW_CLASS,DSP,LIB)
598 
599 #define REAL_NEW_4(NAME,NEW_CLASS,DSP,NOI,LIB, TYPE1,TYPE2, TYPE3, TYPE4) \
600 flext_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 } \
604 FLEXT_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 } \
608 FLEXT_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
FLEXT_ASSERT
#define FLEXT_ASSERT(b)
Definition: flstdc.h:284
LibMap
std::map< const t_symbol *, FLEXT_TEMPINST(flext_class) * > LibMap
Definition: flbase.h:68
flsupport.h
flext support functions and classes
flpopns.h
flext_library
Definition: fllib.cpp:117
flext_hdr::obj
t_sigobj obj
The obligatory object header.
Definition: flbase.h:48
FLEXT_TEMPLATE
#define FLEXT_TEMPLATE
Definition: flprefix.h:455
FLEXT_TEMPINST
typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_obj)) flext_obj
flext_class
Definition: fllib.cpp:138
FLEXT_SHARE
#define FLEXT_SHARE
Definition: flprefix.h:418
flpushns.h
flstdc.h
Definitions to unite Max/MSP and PD notions.
FLEXT_CLASSDEF
FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj)
flext_hdr
The obligatory PD or Max/MSP object header.
Definition: flbase.h:38