flext  0.6.0
flsupport.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 
13 #ifndef __FLSUPPORT_H
14 #define __FLSUPPORT_H
15 
16 #include "flstdc.h"
17 #include <new>
18 #include <cstring>
19 
20 
21 #include "flpushns.h"
22 
23 #if C74_MAX_SDK_VERSION >= 0x0610
24 // really bad: post and error are #defines in Max SDK >= 610
25 #undef post
26 #undef error
27 #endif
28 
33 FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_root);
34 
35 typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root;
36 
43 class FLEXT_SHARE FLEXT_CLASSDEF(flext_root) {
44 public:
45 // --- console output -----------------------------------------------
46 
48  static void post(const char *fmt,...);
50  static void error(const char *fmt,...);
51 
52 // --- memory -------------------------------------------------------
53 
58 #ifdef FLEXT_NOGLOBALNEW
59 #error FLEXT_NOGLOBALNEW is deprecated, define FLEXT_USE_CMEM instead
60 #define FLEXT_USE_CMEM
61 #endif
62 
63 #ifdef FLEXT_USE_CMEM
64  inline void *operator new(size_t bytes) { return ::operator new(bytes); }
65  inline void operator delete(void *blk) { ::operator delete(blk); }
66 
67  inline void *operator new[](size_t bytes) { return ::operator new[](bytes); }
68  inline void operator delete[](void *blk) { ::operator delete[](blk); }
69 
70  static bool MemCheck(void *) { return true; }
71 #else
72 
76  void *operator new(size_t bytes);
78  void operator delete(void *blk);
79 
80 #ifndef __MRC__ // doesn't allow new[] overloading?!
81  inline void *operator new[](size_t bytes) { return operator new(bytes); }
82  inline void operator delete[](void *blk) { operator delete(blk); }
83 #endif
84 
85 #ifdef FLEXT_DEBUGMEM
86  static bool MemCheck(void *blk);
87 #else
88  static bool MemCheck(void *) { return true; }
89 #endif
90 
91 #endif // USECMEM
92 
93 #ifndef __BORLANDC__
94  inline void *operator new(size_t,void *p) { return p; }
95  inline void operator delete(void *,void *) {}
96 #ifndef __MRC__
97  inline void *operator new[](size_t,void *p) { return p; }
98  inline void operator delete[](void *,void *) {}
99 #endif
100 #endif
101 
103  static void *NewAligned(size_t bytes,int bitalign = 128);
104  // same with templated type
105  template<typename T>
106  static T *NewAligned(size_t times,int bitalign = 128) { return static_cast<T *>(NewAligned(times*sizeof(T),bitalign)); }
108  static void FreeAligned(void *blk);
110  static bool IsAligned(void *ptr,int bitalign = 128) {
111  return (reinterpret_cast<size_t>(ptr)&(bitalign-1)) == 0;
112  }
114 };
115 
116 #ifndef FLEXT_USE_CMEM
117 /************************************************************************/
118 // MFC doesn't like global overloading of allocators
119 // anyway, who likes MFC
120 
121 #if !defined(_MSC_VER) && !defined(__BORLANDC__)
122 #define NEWTHROW throw(std::bad_alloc)
123 #define DELTHROW throw()
124 #else
125 #define NEWTHROW
126 #define DELTHROW
127 #endif
128 
129 // define global new/delete operators
130 inline void *operator new(size_t bytes) NEWTHROW { return flext_root::operator new(bytes); }
131 inline void operator delete(void *blk) DELTHROW { flext_root::operator delete(blk); }
132 #ifndef __MRC__ // doesn't allow new[] overloading?!
133 inline void *operator new[](size_t bytes) NEWTHROW { return flext_root::operator new[](bytes); }
134 inline void operator delete[](void *blk) DELTHROW { flext_root::operator delete[](blk); }
135 #endif
136 
137 #endif // FLEXT_USE_CMEM
138 
139 /************************************************************************/
140 
141 FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext);
142 
143 typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext)) flext;
144 
145 FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_base);
146 
160 class FLEXT_SHARE FLEXT_CLASSDEF(flext):
161  public flext_root
162 {
166 public:
167 
168 // --- version -----------------------------------------------
169 
176  static int Version();
177 
179  static const char *VersionStr();
180 
181 // --- special typedefs ---------------------------------------------
182 
183 // later!
184 #if 0
185  typedef t_float Float;
186  typedef t_int Int;
187  typedef t_sample Sample;
188  typedef const t_symbol *Symbol;
189  typedef t_atom Atom;
190 #endif
191 
192 // --- buffer/array stuff -----------------------------------------
193 
198  class FLEXT_SHARE buffer:
200  public flext_root
201  {
202  public:
203 
204 #if FLEXT_SYS == FLEXT_SYS_PD
205  typedef bool lock_t;
206 #elif FLEXT_SYS == FLEXT_SYS_MAX
207  typedef long lock_t;
208 #else
209 #error Not implemented
210 #endif
211 
212 
213 // PD 64-bit buffer handling macros
214 #if FLEXT_SYS == FLEXT_SYS_PD
215 # if PD_MINOR_VERSION >= 41
216  /* use new garray support that is 64-bit safe */
217 # define FLEXT_PD_ARRAYGRAB garray_getfloatwords
218 # define FLEXT_ARRAYTYPE t_word
219 # define FLEXT_GETSAMPLE(x) ((x).w_float)
220 
221 # else
222  /* use old garray support, not 64-bit safe */
223 # define FLEXT_PD_ARRAYGRAB garray_getfloatarray
224 # define FLEXT_ARRAYTYPE t_sample
225 # define FLEXT_GETSAMPLE(x) (x)
226 # endif
227 
228 #elif FLEXT_SYS == FLEXT_SYS_MAX
229 # define FLEXT_ARRAYTYPE t_sample
230 # define FLEXT_GETSAMPLE(x) (x)
231 #endif
232 
233  class Element {
234  public:
235  Element() {}
236  Element(t_sample s) { FLEXT_GETSAMPLE(el) = s; }
237  operator t_sample &() { return FLEXT_GETSAMPLE(el); }
238  operator t_sample () const { return FLEXT_GETSAMPLE(el); }
239  protected:
240  FLEXT_ARRAYTYPE el;
241  };
242 
248  buffer(const t_symbol *s = NULL,bool delayed = false);
249 
251  ~buffer();
252 
256  bool Ok() const
257  {
258  return sym
259 #if FLEXT_SYS == FLEXT_SYS_PD
260  && arr
261 #endif
262  && data;
263  }
264 
268  bool Valid() const
269  {
270  FLEXT_ASSERT(sym);
271 #if FLEXT_SYS == FLEXT_SYS_PD
272  return true;
273 #elif FLEXT_SYS == FLEXT_SYS_MAX
274  const t_buffer *p = (const t_buffer *)sym->s_thing;
275  return p && p->b_valid;
276 #else
277 #error not implemented
278 #endif
279  }
280 
284  bool Update();
285 
290  lock_t Lock();
291 
296  void Unlock(lock_t prv);
297 
302  int Set(const t_symbol *s = NULL,bool nameonly = false);
303 
307  void Dirty(bool refr = false);
308 
310  void ClearDirty();
311 
315  bool IsDirty() const;
316 
318  const t_symbol *Symbol() const { return sym; }
319 
321  const char *Name() const { return sym?GetString(sym):""; }
322 
326  Element *Data() { return data; }
327 
328  const Element *Data() const { return data; }
329 
331  int Channels() const { return chns; }
333  int Frames() const { return frames; }
335  void Frames(int fr,bool keep = false,bool zero = true);
336 
338  inline t_sample operator [](int index) const { return data[index]; }
339 
341  inline t_sample &operator [](int index) { return data[index]; }
342 
344  void SetRefrIntv(float intv);
345 
347  class Locker
348  {
349  public:
350  Locker(buffer &b): buf(b),lock(b.Lock()) {}
351  ~Locker() { buf.Unlock(lock); }
352  private:
353  buffer &buf;
354  lock_t lock;
355  };
356 
357  protected:
359  const t_symbol *sym;
361  Element *data;
363  int chns;
365  int frames;
366 #if FLEXT_SYS == FLEXT_SYS_PD
367  t_garray *arr;
370  float interval;
372  bool isdirty;
374  bool ticking;
376  t_clock *tick;
378  double cleantime;
379 
380  private:
382  static void cb_tick(buffer *b);
383 #elif FLEXT_SYS == FLEXT_SYS_MAX
384  long cleantime;
386 #endif
387  };
388 
389 
391 
392 // --- utilities --------------------------------------------------
393 
398  static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
400 
402  static void CopyAtoms(int cnt,t_atom *dst,const t_atom *src);
403 
405  static bool PrintAtom(const t_atom &a,char *buf,size_t bufsz);
406 
410  static const char *ScanAtom(t_atom &a,const char *buf);
411 
413  static t_atom *CopyList(int argc,const t_atom *argv);
414 
416  static bool PrintList(int argc,const t_atom *argv,char *buf,size_t bufsz);
417 
423  static int ScanList(int argc,t_atom *argv,const char *buf);
424 
426  static void CopyMem(void *dst,const void *src,int bytes);
428  static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
429  template<typename T> static void CopySamples(T *dst,const T *src,int cnt) { CopyMem(dst,src,sizeof(*src)*cnt); }
431  static void ZeroMem(void *dst,int bytes);
433  static void SetSamples(t_sample *dst,int cnt,t_sample s);
434  template<typename T> static void SetSamples(T *dst,int cnt,t_sample s) { for(int i = 0; i < cnt; ++i) dst[i] = s; }
436  static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
437  template<typename T> static void ZeroSamples(T *dst,int cnt) { ZeroMem(dst,sizeof(*dst)*cnt); }
438 
439 
441  static unsigned long AtomHash(const t_atom &a);
442 
444 
445 // --- various symbols --------------------------------------------
446 
451  static const t_symbol *sym__;
454  static const t_symbol *sym_float;
456  static const t_symbol *sym_symbol;
458  static const t_symbol *sym_bang;
460  static const t_symbol *sym_list;
462  static const t_symbol *sym_anything;
463 
467  static const t_symbol *sym_int;
468 
472  static const t_symbol *sym_pointer;
473 
475  static const t_symbol *sym_signal;
476 
478  static const t_symbol *MakeSymbol(const t_symbol *s) { return s; }
479 
481  static const t_symbol *MakeSymbol(const char *s) { return ::gensym(const_cast<char *>(s)); }
483  static const char *GetString(const t_symbol *s) { return s->s_name; }
485  static const char *GetAString(const t_symbol *s,const char *def = NULL) { return s?GetString(s):def; }
486 
487 // --- atom stuff ----------------------------------------
488 
490  static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
492  static int CmpAtom(const t_atom &a,const t_atom &b);
493 
494  // there are some more comparison functions for t_atom types outside the class
495 
497  static int GetType(const t_atom &a) { return a.a_type; }
498 
500  static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
502  static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
503 
505  static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
506 
508  static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
509 
511  static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
513  static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
514 
516  static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
517 
518 #if FLEXT_SYS == FLEXT_SYS_PD
519  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_symbol); }
522  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); }
523 #elif FLEXT_SYS == FLEXT_SYS_MAX
524  static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_sym); }
527  static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_sym = const_cast<t_symbol *>(s); }
528 #else
529 #error
530 #endif
531  static const t_symbol *GetASymbol(const t_atom &a,const t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
533 
535  static bool IsString(const t_atom &a) { return IsSymbol(a); }
537  static const char *GetString(const t_atom &a) { const t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
539  static const char *GetAString(const t_atom &a,const char *def = NULL) { return IsSymbol(a)?GetAString(GetSymbol(a),def):def; }
541  static void GetAString(const t_atom &a,char *buf,size_t szbuf);
543  static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
544 
546  static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
547 
548 #if FLEXT_SYS == FLEXT_SYS_PD
549  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
551 
553  static bool IsInt(const t_atom &) { return false; }
555  static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
557  static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
559  static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
560 
561 #ifndef FLEXT_COMPATIBLE
562  static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
565  static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
567  static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
569  static t_gpointer *GetAPointer(const t_atom &a,t_gpointer *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
571  static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
572 #endif
573 
574 #elif FLEXT_SYS == FLEXT_SYS_MAX
575  static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
577 
579  static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
581  static int GetInt(const t_atom &a) { return a.a_w.w_long; }
583  static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
585  static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
586 #else
587 #error "Platform not supported"
588 #endif
589 
590  // bool type - based on int
591 
593  static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
595  static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
597  static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
599  static bool GetBool(const t_atom &a) { return GetInt(a) != 0; }
600 
601 // --- atom list stuff -------------------------------------------
602 
604  class FLEXT_SHARE AtomList
605  : public flext_root
606  {
607  public:
609  AtomList(): cnt(0),lst(NULL) {}
611  explicit AtomList(int argc,const t_atom *argv = NULL): cnt(0),lst(NULL) { operator()(argc,argv); }
613  AtomList(const AtomList &a): cnt(0),lst(NULL) { operator =(a); }
615  virtual ~AtomList();
616 
618  AtomList &Clear() { return operator()(); }
619 
621  AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
623  int Get(t_atom *argv,int mxsz = -1) const;
624 
626  AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
628  AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
629 
631  int Compare(const AtomList &a) const;
632 
633  bool operator <(const AtomList &a) const { return Compare(a) < 0; }
634  bool operator <=(const AtomList &a) const { return Compare(a) <= 0; }
635  bool operator >(const AtomList &a) const { return Compare(a) > 0; }
636  bool operator >=(const AtomList &a) const { return Compare(a) >= 0; }
637  bool operator ==(const AtomList &a) const { return Compare(a) == 0; }
638  bool operator !=(const AtomList &a) const { return Compare(a) != 0; }
639 
641  int Count() const { return cnt; }
643  t_atom &operator [](int ix) { return lst[ix]; }
645  const t_atom &operator [](int ix) const { return lst[ix]; }
646 
648  t_atom *Atoms() { return lst; }
650  const t_atom *Atoms() const { return lst; }
651 
653  AtomList &Append(int argc,const t_atom *argv = NULL)
654  {
655  int c = Count();
656  Alloc(c+argc,0,c);
657  Set(argc,argv,c);
658  return *this;
659  }
660 
662  AtomList &Prepend(int argc,const t_atom *argv = NULL)
663  {
664  int c = Count();
665  Alloc(c+argc,0,c,argc);
666  Set(argc,argv);
667  return *this;
668  }
669 
671  AtomList &Append(const t_atom &a) { return Append(1,&a); }
673  AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
675  AtomList &Prepend(const t_atom &a) { return Prepend(1,&a); }
677  AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
678 
680  void GetPart(int offs,int len,AtomList &ret) const;
682  AtomList &Part(int offs,int len) { GetPart(offs,len,*this); return *this; }
683 
685  bool Print(char *buffer,int buflen) const { return flext::PrintList(Count(),Atoms(),buffer,buflen); }
686 
690  int Scan(const char *buffer) { return flext::ScanList(Count(),Atoms(),buffer); }
691 
692  protected:
693  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
694  virtual void Free();
695 
696  int cnt;
697  t_atom *lst;
698  };
699 
700  class FLEXT_SHARE AtomListStaticBase
701  : public AtomList
702  {
703  protected:
704  explicit AtomListStaticBase(int pc,t_atom *dt): precnt(pc),predata(dt) {}
705  virtual ~AtomListStaticBase();
706  virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
707  virtual void Free();
708 
709  AtomListStaticBase &operator =(const AtomList &a) { AtomList::operator =(a); return *this; }
710  AtomListStaticBase &operator =(const AtomListStaticBase &a) { AtomList::operator =(a); return *this; }
711 
712  const int precnt;
713  t_atom *const predata;
714  };
715 
716  template<int PRE>
717  class AtomListStatic
718  : public AtomListStaticBase
719  {
720  public:
722  explicit AtomListStatic(): AtomListStaticBase(PRE,pre) {}
724  explicit AtomListStatic(int argc,const t_atom *argv = NULL): AtomListStaticBase(PRE,pre) { AtomList::operator()(argc,argv); }
726  explicit AtomListStatic(const AtomList &a): AtomListStaticBase(PRE,pre) { operator =(a); }
727 
729  AtomListStatic &operator =(const AtomList &a) { AtomListStaticBase::operator =(a); return *this; }
730  AtomListStatic &operator =(const AtomListStatic &a) { AtomListStaticBase::operator =(a); return *this; }
731  protected:
732  t_atom pre[PRE];
733  };
734 
736  class FLEXT_SHARE AtomAnything:
737  public AtomList
738  {
739  public:
740  explicit AtomAnything(): hdr(NULL) {}
741 
743  explicit AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL)
744  : AtomList(argc,argv),hdr(h?h:sym__)
745  {}
746 
748  explicit AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL)
749  : AtomList(argc,argv),hdr(MakeSymbol(h))
750  {}
751 
753  AtomAnything(const AtomAnything &a)
754  : AtomList(a),hdr(a.hdr)
755  {}
756 
758  AtomAnything &Clear() { return operator()(); }
759 
761  const t_symbol *Header() const { return hdr; }
762 
764  void Header(const t_symbol *h) { hdr = h; }
765 
767  AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
768  {
769  hdr = h; AtomList::operator()(argc,argv);
770  return *this;
771  }
772 
774  AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
775 
776  protected:
777  const t_symbol *hdr;
778  };
779 
780 
781  // double type - based on two floats
782 
783 #ifdef _MSC_VER
784 #pragma optimize("p",off) // improve floating point precision consistency
785 #endif
786  static t_atom *SetDouble(t_atom *dbl,double d)
787  {
788  float f = static_cast<float>(d);
789  float r = static_cast<float>(d-f);
790  SetFloat(dbl[0],f);
791  SetFloat(dbl[1],r);
792  return dbl;
793  }
794 #ifdef _MSC_VER
795 #pragma optimize("p",on)
796 #endif
797 
798  static double GetDouble(int argc,const t_atom *argv)
799  {
800  double d = argc >= 1?GetAFloat(argv[0]):0;
801  return argc >= 2?d+GetAFloat(argv[1]):d;
802  }
803 
804  static AtomList &SetDouble(AtomList &l,double d) { SetDouble(l(2).Atoms(),d); return l; }
805 
806  static double GetDouble(const AtomList &l) { return GetDouble(l.Count(),l.Atoms()); }
807 
809 
810 
811 // --- messages -------------------------------------------------------
812 
817  class MsgBundle;
818 
820  static MsgBundle *MsgNew();
821 
823  static void MsgFree(MsgBundle *mb);
824 
826  static void ToSysMsg(MsgBundle *mb);
827 
829  static void ToOutMsg(MsgBundle *mb);
830 
832  static void ToQueueMsg(MsgBundle *mb);
833 
835 
836 
841  static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
842  static bool Forward(const t_symbol *sym,const AtomAnything &args) { return Forward(sym,args.Header(),args.Count(),args.Atoms()); }
843  static bool Forward(const char *sym,const AtomAnything &args) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
844  static bool Forward(const t_symbol *sym,int argc,const t_atom *argv) { return Forward(sym,sym_list,argc,argv); }
845  static bool Forward(const t_symbol *sym,const AtomList &args) { return Forward(sym,args.Count(),args.Atoms()); }
846  static bool Forward(const char *sym,const AtomList &args) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms()); }
847 
848  static bool SysForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
849  static bool SysForward(const t_symbol *sym,const AtomAnything &args) { return SysForward(sym,args.Header(),args.Count(),args.Atoms()); }
850  static bool SysForward(const char *sym,const AtomAnything &args) { return SysForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
851  static bool SysForward(const t_symbol *sym,int argc,const t_atom *argv) { return SysForward(sym,sym_list,argc,argv); }
852  static bool SysForward(const t_symbol *sym,const AtomList &args) { return SysForward(sym,args.Count(),args.Atoms()); }
853  static bool SysForward(const char *sym,const AtomList &args) { return SysForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
854 
855  static bool QueueForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
856  static bool QueueForward(const t_symbol *sym,const AtomAnything &args) { return QueueForward(sym,args.Header(),args.Count(),args.Atoms()); }
857  static bool QueueForward(const char *sym,const AtomAnything &args) { return QueueForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
858  static bool QueueForward(const t_symbol *sym,int argc,const t_atom *argv) { return QueueForward(sym,sym_list,argc,argv); }
859  static bool QueueForward(const t_symbol *sym,const AtomList &args) { return QueueForward(sym,args.Count(),args.Atoms()); }
860  static bool QueueForward(const char *sym,const AtomList &args) { return QueueForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
861 
862  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
863  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomAnything &args) { return MsgForward(mb,sym,args.Header(),args.Count(),args.Atoms()); }
864  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomAnything &args) { return MsgForward(mb,MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
865  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,int argc,const t_atom *argv) { return MsgForward(mb,sym,sym_list,argc,argv); }
866  static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomList &args) { return MsgForward(mb,sym,args.Count(),args.Atoms()); }
867  static bool MsgForward(MsgBundle *mb,const char *sym,const AtomList &args) { return MsgForward(mb,MakeSymbol(sym),args.Count(),args.Atoms()); }
868 
870 
871 
872 
873 // --- thread stuff -----------------------------------------------
874 
879 #if FLEXT_SYS == FLEXT_SYS_PD
880  #if PD_MINOR_VERSION >= 38 || (PD_MINOR_VERSION >= 37 && defined(PD_DEVEL_VERSION))
881  static void Lock() { sys_lock(); }
882  static void Unlock() { sys_unlock(); }
883  #else
884  // no system locking for old PD versions
885  static void Lock() {}
886  static void Unlock() {}
887  #endif
888 #elif FLEXT_SYS == FLEXT_SYS_MAX
889  // Max 4.2 upwards!
890  static void Lock() { critical_enter(0); }
891  static void Unlock() { critical_exit(0); }
892 #else
893 #error
894 #endif
895 
897 
902 #ifdef FLEXT_THREADS
904  static bool IsThreadRegistered();
905 #else
906  static bool IsThreadRegistered() { return false; }
907 #endif
908 
909 #ifdef FLEXT_THREADS
910 
912 # if FLEXT_THREADS == FLEXT_THR_MP
913  typedef MPTaskID thrid_t;
914 # elif FLEXT_THREADS == FLEXT_THR_POSIX
915  typedef pthread_t thrid_t;
916 # elif FLEXT_THREADS == FLEXT_THR_WIN32
917  typedef DWORD thrid_t;
918 # else
919 # error Threading model not supported
920 # endif
921 
924  static thrid_t GetThreadId() {
925 #if FLEXT_THREADS == FLEXT_THR_POSIX
926  return pthread_self();
927 #elif FLEXT_THREADS == FLEXT_THR_MP
928  return MPCurrentTaskID();
929 #elif FLEXT_THREADS == FLEXT_THR_WIN32
930  return GetCurrentThreadId();
931 #else
932 #error
933 #endif
934  }
935 
938  static thrid_t GetSysThreadId() { return thrid; }
939 
941  static bool ShouldExit();
942 
944  static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
945 #if FLEXT_THREADS == FLEXT_THR_POSIX
946  return pthread_equal(ref,t) != 0;
947 #else
948  return ref == t;
949 #endif
950  }
951 
952 
956  class FLEXT_SHARE thr_params:
957  public flext_root
958  {
959  public:
960  thr_params(int n = 1): cl(NULL),var(new _data[n]) {}
961  ~thr_params() { delete[] var; }
962 
963  void set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any = new AtomAnything(s,argc,argv); }
964  void set_list(int argc,const t_atom *argv) { var[0]._list = new AtomList(argc,argv); }
965 
966  FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) *cl;
967  union _data {
968  bool _bool;
969  float _float;
970  int _int;
971  t_symptr _t_symptr;
972  AtomAnything *_any;
973  AtomList *_list;
974  void *_ext;
975  } *var;
976  };
977 
978 protected:
979 
980  static thrid_t thrhelpid;
981  static thrid_t thrmsgid;
982  static void ThrHelper(void *);
983 
985  static thrid_t thrid; // the system thread
986 
987 private:
988  static bool StartHelper(); // used in flext::Setup()
989 
990 public:
991 
995  static void ThrYield() {
996 #if FLEXT_THREADS == FLEXT_THR_POSIX
997  // for a preemptive system this should do nothing
998  sched_yield();
999 #elif FLEXT_THREADS == FLEXT_THR_MP
1000  MPYield();
1001 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1002  SwitchToThread();
1003 #else
1004 #error
1005 #endif
1006  }
1007 
1010  static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
1011 #if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
1012  return true;
1013 #elif FLEXT_THREADS == FLEXT_THR_MP
1014  return MPTaskIsPreemptive(t);
1015 #else
1016 #error
1017 #endif
1018  }
1019 
1020 
1023  static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),thrid_t thr = GetThreadId());
1024 
1027  static int GetPriority(thrid_t thr = GetThreadId());
1028 
1031  static bool SetPriority(int p,thrid_t thr = GetThreadId());
1032 
1036  class FLEXT_SHARE ThrMutex:
1037  public flext_root
1038 #if FLEXT_THREADS == FLEXT_THR_POSIX
1039  {
1040  public:
1042  ThrMutex() { pthread_mutex_init(&mutex,NULL); }
1044  ~ThrMutex() { pthread_mutex_destroy(&mutex); }
1045 
1047  bool Lock() { return pthread_mutex_lock(&mutex) == 0; }
1051 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1053  bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
1055  bool Unlock() { return pthread_mutex_unlock(&mutex) == 0; }
1056 
1057  protected:
1058  pthread_mutex_t mutex;
1059 // int cnt;
1060  };
1061 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1062  {
1063  public:
1065  ThrMutex() { ::InitializeCriticalSection(&mutex); }
1067  ~ThrMutex() { ::DeleteCriticalSection(&mutex); }
1068 
1070  bool Lock() { ::EnterCriticalSection(&mutex); return true; }
1074 // bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1076  bool TryLock() { return ::TryEnterCriticalSection(&mutex) != 0; }
1078  bool Unlock() { ::LeaveCriticalSection(&mutex); return true; }
1079 
1080  protected:
1081  CRITICAL_SECTION mutex;
1082  };
1083 #elif FLEXT_THREADS == FLEXT_THR_MP
1084  {
1085  public:
1087  ThrMutex() { MPCreateCriticalRegion(&crit); }
1089  ~ThrMutex() { MPDeleteCriticalRegion(crit); }
1090 
1092  bool Lock() { return MPEnterCriticalRegion(crit,kDurationForever) == noErr; }
1094 // bool WaitForLock(double tm) { return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
1096  bool TryLock() { return MPEnterCriticalRegion(crit,kDurationImmediate) == noErr; }
1098  bool Unlock() { return MPExitCriticalRegion(crit) == noErr; }
1099 
1100  protected:
1101  MPCriticalRegionID crit;
1102  };
1103 #else
1104 #error "Not implemented"
1105 #endif
1106 
1110  class FLEXT_SHARE ThrCond
1111 #if FLEXT_THREADS == FLEXT_THR_POSIX
1112  :public ThrMutex
1113  {
1114  public:
1116  ThrCond() { pthread_cond_init(&cond,NULL); }
1118  ~ThrCond() { pthread_cond_destroy(&cond); }
1119 
1121  bool Wait();
1122 
1129  bool TimedWait(double ftime);
1130 
1132  bool Signal() { return pthread_cond_signal(&cond) == 0; }
1133 
1134  protected:
1135  pthread_cond_t cond;
1136  };
1137 #elif FLEXT_THREADS == FLEXT_THR_WIN32
1138  {
1139  public:
1141  ThrCond() { cond = CreateEvent(NULL,FALSE,FALSE,NULL); }
1143  ~ThrCond() { CloseHandle(cond); }
1144 
1146  bool Wait() { return WaitForSingleObject(cond,INFINITE) == WAIT_OBJECT_0; }
1147 
1154  bool TimedWait(double ftime) { return WaitForSingleObject(cond,(LONG)(ftime*1000)) == WAIT_OBJECT_0; }
1155 
1157  bool Signal() { return SetEvent(cond) != 0; }
1158 
1159  protected:
1160  HANDLE cond;
1161  };
1162 #elif FLEXT_THREADS == FLEXT_THR_MP
1163  {
1164  public:
1166  ThrCond() { MPCreateEvent(&ev); }
1168  ~ThrCond() { MPDeleteEvent(ev); }
1169 
1171  bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
1172 
1176  bool TimedWait(double tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
1177 
1179  bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
1180 
1181  protected:
1182  MPEventID ev;
1183  };
1184 #else
1185 #error "Not implemented"
1186 #endif
1187 
1188  protected:
1194  static bool PushThread();
1195 
1200  static void PopThread();
1201 
1202  public:
1208  static bool LaunchThread(void (*meth)(thr_params *p),thr_params *params = NULL);
1209 
1217  static bool StopThread(void (*meth)(thr_params *p),thr_params *params = NULL,bool wait = false);
1218 
1219 
1221  static void RegisterThread(thrid_t id = GetThreadId());
1222 
1224  static void UnregisterThread(thrid_t id = GetThreadId());
1225 
1226 #endif // FLEXT_THREADS
1227 
1229 
1230 
1231  public:
1232 // --- timer stuff -----------------------------------------------
1233 
1246  static double GetTime()
1247  {
1248  #if FLEXT_SYS == FLEXT_SYS_PD
1249  return clock_gettimesince(0)*0.001;
1250  #elif FLEXT_SYS == FLEXT_SYS_MAX
1251  double tm;
1252  clock_getftime(&tm);
1253  return tm*0.001;
1254  #else
1255  #error Not implemented
1256  #endif
1257  }
1258 
1262  static double GetTimeGrain()
1263  {
1264  #if FLEXT_SYS == FLEXT_SYS_PD
1265  return 0;
1266  #elif FLEXT_SYS == FLEXT_SYS_MAX
1267  return 0.001;
1268  #else
1269  #error Not implemented
1270  #endif
1271  }
1272 
1275  static double GetOSTime();
1276 
1281  static void Sleep(double s);
1282 
1286  class FLEXT_SHARE Timer:
1287  public flext_root
1288  {
1289  public:
1290  Timer(bool queued = false);
1291  virtual ~Timer();
1292 
1294  void SetCallback(void (*cb)(void *data)) { clss = NULL,cback = cb; }
1296  void SetCallback(FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) &th,bool (*cb)(FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) *th,void *data)) { clss = &th,cback = (void (*)(void *))cb; }
1297 
1299  bool Reset();
1301  bool At(double time,void *data = NULL,bool dopast = true);
1303  bool Delay(double time,void *data = NULL);
1305  bool Periodic(double time,void *data = NULL);
1307  bool Now(void *data = NULL) { return Delay(0,data); }
1308 
1310  virtual void Work();
1311 
1312  protected:
1313  static void callback(Timer *tmr);
1314 
1315 #if FLEXT_SYS == FLEXT_SYS_PD
1316  t_clock *clk;
1317 #elif FLEXT_SYS == FLEXT_SYS_MAX
1318  static void queuefun(Timer *tmr);
1319  t_clock *clk;
1320  t_qelem *qelem;
1321 #else
1322 #error Not implemented
1323 #endif
1324 
1325  const bool queued;
1326  void (*cback)(void *data);
1327  FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) *clss;
1328  void *userdata;
1329  double period;
1330  };
1331 
1333 
1335  static bool InDSP() { return indsp; }
1336 
1337 // --- SIMD functionality -----------------------------------------------
1338 
1342  enum simd_type {
1343  simd_none = 0,
1344  simd_mmx = 0x01,
1345  simd_3dnow = 0x02,
1346  simd_sse = 0x04,
1347  simd_sse2 = 0x08,
1348  simd_altivec = 0x10
1349  };
1350 
1352  static unsigned long GetSIMDCapabilities();
1353 
1354 
1355  static void MulSamples(t_sample *dst,const t_sample *src,t_sample mul,int cnt);
1356  static void MulSamples(t_sample *dst,const t_sample *src,const t_sample *mul,int cnt);
1357  static void AddSamples(t_sample *dst,const t_sample *src,t_sample add,int cnt);
1358  static void AddSamples(t_sample *dst,const t_sample *src,const t_sample *add,int cnt);
1359  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,t_sample add,int cnt);
1360  static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,const t_sample *add,int cnt);
1361  static void ScaleSamples(t_sample *dst,const t_sample *src,const t_sample *mul,const t_sample *add,int cnt);
1362 
1364 
1365 
1367 
1368 protected:
1369 #ifdef __MRC__
1370  friend class flext_obj;
1371 #endif
1372 
1373  static void Setup();
1374 
1375  static bool chktilde(const char *objname);
1376 
1377  static unsigned long simdcaps;
1378 
1379  static const t_symbol *sym_attributes;
1380  static const t_symbol *sym_methods;
1381 
1382 #if FLEXT_SYS == FLEXT_SYS_MAX
1383  static const t_symbol *sym_buffer;
1384  static const t_symbol *sym_size;
1385  static const t_symbol *sym_dirty;
1386 #endif
1387 
1389  static bool indsp;
1390 };
1391 
1392 
1393 // gcc doesn't like these to be included into the flext class (even if static)
1394 inline bool operator ==(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) == 0; }
1395 inline bool operator !=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) != 0; }
1396 inline bool operator <(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) < 0; }
1397 inline bool operator <=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) <= 0; }
1398 inline bool operator >(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) > 0; }
1399 inline bool operator >=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) >= 0; }
1400 
1402 
1403 #include "flpopns.h"
1404 
1405 #endif
FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_root)
bool operator<(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1396
bool operator<=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1397
t_symbol * t_symptr
Definition: flstdc.h:225
#define FLEXT_ASSERT(b)
Definition: flstdc.h:284
bool operator==(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1394
#define FLEXT_THR_POSIX
Definition: flprefix.h:80
#define FLEXT_TEMPLATE
Definition: flprefix.h:455
#define NEWTHROW
Definition: flsupport.h:122
#define DELTHROW
Definition: flsupport.h:123
#define FLEXT_SHARE
Definition: flprefix.h:418
bool operator>=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1399
Definitions to unite Max/MSP and PD notions.
bool operator>(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1398
typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root
bool operator!=(const t_atom &a, const t_atom &b)
Definition: flsupport.h:1395