flext 0.6.2
flsupport.h
Go to the documentation of this file.
1/*
2flext - C++ layer for Max and Pure Data externals
3
4Copyright (c) 2001-2020 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
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
34
35typedef FLEXT_TEMPINST(FLEXT_SHARE FLEXT_CLASSDEF(flext_root)) flext_root;
36
43class FLEXT_SHARE FLEXT_CLASSDEF(flext_root) {
44public:
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
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
117#ifdef FLEXT_USE_CMEM
118# define NEWTHROW
119# define DELTHROW
120
121#else
122
123// MFC doesn't like global overloading of allocators
124// anyway, who likes MFC
125
126#if !defined(_MSC_VER) && !defined(__BORLANDC__)
127#if __cpp_noexcept_function_type
128# define NEWTHROW noexcept(false)
129# define DELTHROW noexcept(true)
130#else
131# define NEWTHROW throw(std::bad_alloc)
132# define DELTHROW throw()
133#endif
134#else
135# define NEWTHROW
136# define DELTHROW
137#endif
138
139// define global new/delete operators
140void *operator new(size_t bytes) NEWTHROW;
141void operator delete(void *blk) DELTHROW;
142#ifndef __MRC__ // doesn't allow new[] overloading?!
143void *operator new[](size_t bytes) NEWTHROW;
144void operator delete[](void *blk) DELTHROW;
145#endif
146
147#endif // FLEXT_USE_CMEM
148
149/************************************************************************/
150
152
153typedef FLEXT_TEMPINST(FLEXT_CLASSDEF(flext)) flext;
154
156
170class FLEXT_SHARE FLEXT_CLASSDEF(flext):
171 public flext_root
172{
176public:
177
178// --- version -----------------------------------------------
179
186 static int Version();
187
189 static const char *VersionStr();
190
191// --- special typedefs ---------------------------------------------
192
193// later!
194#if 0
195 typedef t_float Float;
196 typedef t_int Int;
197 typedef t_sample Sample;
198 typedef const t_symbol *Symbol;
199 typedef t_atom Atom;
200#endif
201
202// --- buffer/array stuff -----------------------------------------
203
209 class FLEXT_SHARE buffer:
210 public flext_root
211 {
212 public:
213
214#if FLEXT_SYS == FLEXT_SYS_PD
215 typedef bool lock_t;
216#elif FLEXT_SYS == FLEXT_SYS_MAX
217 typedef long lock_t;
218#else
219#error Not implemented
220#endif
221
222
223// PD 64-bit buffer handling macros
224#if FLEXT_SYS == FLEXT_SYS_PD
225# if PD_MINOR_VERSION >= 41
226 /* use new garray support that is 64-bit safe */
227# define FLEXT_PD_ARRAYGRAB garray_getfloatwords
228# define FLEXT_ARRAYTYPE t_word
229# define FLEXT_GETSAMPLE(x) ((x).w_float)
230# define _FLEXT_NEED_SAMPLE_CONV 1
231
232# else
233 /* use old garray support, not 64-bit safe */
234# define FLEXT_PD_ARRAYGRAB garray_getfloatarray
235# define FLEXT_ARRAYTYPE t_sample
236# define FLEXT_GETSAMPLE(x) (x)
237# define _FLEXT_NEED_SAMPLE_CONV 0
238# endif
239
240#elif FLEXT_SYS == FLEXT_SYS_MAX
241# define FLEXT_ARRAYTYPE float
242# define FLEXT_GETSAMPLE(x) (x)
243# define _FLEXT_NEED_SAMPLE_CONV 0
244#endif
245
246 class Element {
247 public:
248 Element() {}
250 operator FLEXT_ARRAYTYPE &() { return el; }
251 operator FLEXT_ARRAYTYPE () const { return el; }
252#if _FLEXT_NEED_SAMPLE_CONV
254 operator t_sample &() { return FLEXT_GETSAMPLE(el); }
255 operator t_sample () const { return FLEXT_GETSAMPLE(el); }
256#endif
257 protected:
259 };
260
266 buffer(const t_symbol *s = NULL,bool delayed = false);
267
269 ~buffer();
270
274 bool Ok() const
275 {
276 return sym
277#if FLEXT_SYS == FLEXT_SYS_PD
278 && arr
279#endif
280 && data;
281 }
282
286 bool Valid() const
287 {
288 FLEXT_ASSERT(sym);
289#if FLEXT_SYS == FLEXT_SYS_PD
290 return true;
291#elif FLEXT_SYS == FLEXT_SYS_MAX
292 const t_buffer *p = (const t_buffer *)sym->s_thing;
293 return p && p->b_valid;
294#else
295#error not implemented
296#endif
297 }
298
302 bool Update();
303
308 lock_t Lock();
309
314 void Unlock(lock_t prv);
315
320 int Set(const t_symbol *s = NULL,bool nameonly = false);
321
325 void Dirty(bool refr = false);
326
328 void ClearDirty();
329
333 bool IsDirty() const;
334
336 const t_symbol *Symbol() const { return sym; }
337
339 const char *Name() const { return sym?GetString(sym):""; }
340
344 Element *Data() { return data; }
345
346 const Element *Data() const { return data; }
347
349 int Channels() const { return chns; }
351 int Frames() const { return frames; }
353 void Frames(int fr,bool keep = false,bool zero = true);
354
356 inline Element operator [](int index) const { return data[index]; }
357
359 inline Element &operator [](int index) { return data[index]; }
360
362 void SetRefrIntv(float intv);
363
365 class Locker
366 {
367 public:
368 Locker(buffer &b): buf(b),lock(b.Lock()) {}
369 ~Locker() { buf.Unlock(lock); }
370 private:
371 buffer &buf;
372 lock_t lock;
373 };
374
375 protected:
377 const t_symbol *sym;
379 Element *data;
381 int chns;
383 int frames;
384#if FLEXT_SYS == FLEXT_SYS_PD
386 t_garray *arr;
388 float interval;
390 bool isdirty;
392 bool ticking;
394 t_clock *tick;
396 double cleantime;
397
398 private:
400 static void cb_tick(buffer *b);
401#elif FLEXT_SYS == FLEXT_SYS_MAX
403 long cleantime;
404#endif
405 };
406
407
409
410// --- utilities --------------------------------------------------
411
417 static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; }
418
420 static void CopyAtoms(int cnt,t_atom *dst,const t_atom *src);
421
423 static bool PrintAtom(const t_atom &a,char *buf,size_t bufsz);
424
428 static const char *ScanAtom(t_atom &a,const char *buf);
429
431 static t_atom *CopyList(int argc,const t_atom *argv);
432
434 static bool PrintList(int argc,const t_atom *argv,char *buf,size_t bufsz);
435
441 static int ScanList(int argc,t_atom *argv,const char *buf);
442
444 static void CopyMem(void *dst,const void *src,int bytes);
446 static void CopySamples(t_sample *dst,const t_sample *src,int cnt);
447 template<typename T> static void CopySamples(T *dst,const T *src,int cnt) { CopyMem(dst,src,sizeof(*src)*cnt); }
449 static void ZeroMem(void *dst,int bytes);
451 static void SetSamples(t_sample *dst,int cnt,t_sample s);
452 template<typename T> static void SetSamples(T *dst,int cnt,t_sample s) { for(int i = 0; i < cnt; ++i) dst[i] = s; }
454 static void ZeroSamples(t_sample *dst,int cnt) { SetSamples(dst,cnt,0); }
455 template<typename T> static void ZeroSamples(T *dst,int cnt) { ZeroMem(dst,sizeof(*dst)*cnt); }
456
457
459 static unsigned long AtomHash(const t_atom &a);
460
462
463// --- various symbols --------------------------------------------
464
470 static const t_symbol *sym__;
472 static const t_symbol *sym_float;
474 static const t_symbol *sym_symbol;
476 static const t_symbol *sym_bang;
478 static const t_symbol *sym_list;
480 static const t_symbol *sym_anything;
481
485 static const t_symbol *sym_int;
486
490 static const t_symbol *sym_pointer;
491
493 static const t_symbol *sym_signal;
494
496 static const t_symbol *MakeSymbol(const t_symbol *s) { return s; }
497
499 static const t_symbol *MakeSymbol(const char *s) { return ::gensym(const_cast<char *>(s)); }
501 static const char *GetString(const t_symbol *s) { return s->s_name; }
503 static const char *GetAString(const t_symbol *s,const char *def = NULL) { return s?GetString(s):def; }
504
505// --- atom stuff ----------------------------------------
506
508 static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); }
510 static int CmpAtom(const t_atom &a,const t_atom &b);
511
512 // there are some more comparison functions for t_atom types outside the class
513
515 static int GetType(const t_atom &a) { return a.a_type; }
516
518 static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; }
520 static void SetNothing(t_atom &a) { a.a_type = A_NULL; }
521
523 static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; }
524
526 static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); }
527
529 static float GetFloat(const t_atom &a) { return a.a_w.w_float; }
531 static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; }
532
534 static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; }
535
536#if FLEXT_SYS == FLEXT_SYS_PD
538 static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_symbol); }
540 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); }
541#elif FLEXT_SYS == FLEXT_SYS_MAX
543 static const t_symbol *GetSymbol(const t_atom &a) { return const_cast<const t_symbol *>(a.a_w.w_sym); }
545 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); }
546#else
547#error
548#endif
550 static const t_symbol *GetASymbol(const t_atom &a,const t_symbol *def = NULL) { return IsSymbol(a)?GetSymbol(a):def; } // NULL or empty symbol?
551
553 static bool IsString(const t_atom &a) { return IsSymbol(a); }
555 static const char *GetString(const t_atom &a) { const t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; }
557 static const char *GetAString(const t_atom &a,const char *def = NULL) { return IsSymbol(a)?GetAString(GetSymbol(a),def):def; }
559 static void GetAString(const t_atom &a,char *buf,size_t szbuf);
561 static void SetString(t_atom &a,const char *c) { SetSymbol(a,MakeSymbol(c)); }
562
564 static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); }
565
566#if FLEXT_SYS == FLEXT_SYS_PD
568 static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):def; }
569
571 static bool IsInt(const t_atom &) { return false; }
573 static int GetInt(const t_atom &a) { return (int)GetFloat(a); }
575 static int GetAInt(const t_atom &a,int def = 0) { return (int)GetAFloat(a,(float)def); }
577 static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; }
578
579#ifndef FLEXT_COMPATIBLE
581 static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; }
583 static bool CanbePointer(const t_atom &a) { return IsPointer(a); }
585 static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; }
587 static t_gpointer *GetAPointer(const t_atom &a,t_gpointer *def = NULL) { return IsPointer(a)?GetPointer(a):def; }
589 static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = (t_gpointer *)p; }
590#endif
591
592#elif FLEXT_SYS == FLEXT_SYS_MAX
594 static float GetAFloat(const t_atom &a,float def = 0) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):def); }
595
597 static bool IsInt(const t_atom &a) { return a.a_type == A_INT; }
599 static int GetInt(const t_atom &a) { return a.a_w.w_long; }
601 static int GetAInt(const t_atom &a,int def = 0) { return IsInt(a)?GetInt(a):(IsFloat(a)?(int)GetFloat(a):def); }
603 static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; }
604#else
605#error "Platform not supported"
606#endif
607
608 // bool type - based on int
609
611 static void SetBool(t_atom &a,bool v) { SetInt(a,v?1:0); }
613 static bool CanbeBool(const t_atom &a) { return CanbeInt(a); }
615 static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; }
617 static bool GetBool(const t_atom &a) { return GetInt(a) != 0; }
618
619// --- atom list stuff -------------------------------------------
620
623 : public flext_root
624 {
625 public:
627 AtomList(): cnt(0),lst(NULL) {}
629 explicit AtomList(int argc,const t_atom *argv = NULL): cnt(0),lst(NULL) { operator()(argc,argv); }
631 AtomList(const AtomList &a): cnt(0),lst(NULL) { operator =(a); }
633 virtual ~AtomList();
634
636 AtomList &Clear() { return operator()(); }
637
639 AtomList &Set(int argc,const t_atom *argv,int offs = 0,bool resize = false);
641 int Get(t_atom *argv,int mxsz = -1) const;
642
644 AtomList &operator()(int argc = 0,const t_atom *argv = NULL) { return Set(argc,argv,0,true); }
646 AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); }
647
649 int Compare(const AtomList &a) const;
650
651 bool operator <(const AtomList &a) const { return Compare(a) < 0; }
652 bool operator <=(const AtomList &a) const { return Compare(a) <= 0; }
653 bool operator >(const AtomList &a) const { return Compare(a) > 0; }
654 bool operator >=(const AtomList &a) const { return Compare(a) >= 0; }
655 bool operator ==(const AtomList &a) const { return Compare(a) == 0; }
656 bool operator !=(const AtomList &a) const { return Compare(a) != 0; }
657
659 int Count() const { return cnt; }
661 t_atom &operator [](int ix) { return lst[ix]; }
663 const t_atom &operator [](int ix) const { return lst[ix]; }
664
666 t_atom *Atoms() { return lst; }
668 const t_atom *Atoms() const { return lst; }
669
671 AtomList &Append(int argc,const t_atom *argv = NULL)
672 {
673 int c = Count();
674 Alloc(c+argc,0,c);
675 Set(argc,argv,c);
676 return *this;
677 }
678
680 AtomList &Prepend(int argc,const t_atom *argv = NULL)
681 {
682 int c = Count();
683 Alloc(c+argc,0,c,argc);
684 Set(argc,argv);
685 return *this;
686 }
687
689 AtomList &Append(const t_atom &a) { return Append(1,&a); }
691 AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); }
693 AtomList &Prepend(const t_atom &a) { return Prepend(1,&a); }
695 AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); }
696
698 void GetPart(int offs,int len,AtomList &ret) const;
700 AtomList &Part(int offs,int len) { GetPart(offs,len,*this); return *this; }
701
703 bool Print(char *buffer,int buflen) const { return flext::PrintList(Count(),Atoms(),buffer,buflen); }
704
708 int Scan(const char *buffer) { return flext::ScanList(Count(),Atoms(),buffer); }
709
710 protected:
711 virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
712 virtual void Free();
713
714 int cnt;
715 t_atom *lst;
716 };
717
719 : public AtomList
720 {
721 protected:
722 explicit AtomListStaticBase(int pc,t_atom *dt): precnt(pc),predata(dt) {}
723 virtual ~AtomListStaticBase();
724 virtual void Alloc(int sz,int keepix = -1,int keeplen = -1,int keepto = 0);
725 virtual void Free();
726
727 AtomListStaticBase &operator =(const AtomList &a) { AtomList::operator =(a); return *this; }
728 AtomListStaticBase &operator =(const AtomListStaticBase &a) { AtomList::operator =(a); return *this; }
729
730 const int precnt;
731 t_atom *const predata;
732 };
733
734 template<int PRE>
735 class AtomListStatic
736 : public AtomListStaticBase
737 {
738 public:
742 explicit AtomListStatic(int argc,const t_atom *argv = NULL): AtomListStaticBase(PRE,pre) { AtomList::operator()(argc,argv); }
744 explicit AtomListStatic(const AtomList &a): AtomListStaticBase(PRE,pre) { operator =(a); }
745
747 AtomListStatic &operator =(const AtomList &a) { AtomListStaticBase::operator =(a); return *this; }
748 AtomListStatic &operator =(const AtomListStatic &a) { AtomListStaticBase::operator =(a); return *this; }
749 protected:
750 t_atom pre[PRE];
751 };
752
755 public AtomList
756 {
757 public:
758 explicit AtomAnything(): hdr(NULL) {}
759
761 explicit AtomAnything(const t_symbol *h,int argc = 0,const t_atom *argv = NULL)
762 : AtomList(argc,argv),hdr(h?h:sym__)
763 {}
764
766 explicit AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL)
767 : AtomList(argc,argv),hdr(MakeSymbol(h))
768 {}
769
772 : AtomList(a),hdr(a.hdr)
773 {}
774
776 AtomAnything &Clear() { return operator()(); }
777
779 const t_symbol *Header() const { return hdr; }
780
782 void Header(const t_symbol *h) { hdr = h; }
783
785 AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL)
786 {
787 hdr = h; AtomList::operator()(argc,argv);
788 return *this;
789 }
790
792 AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); }
793
794 protected:
795 const t_symbol *hdr;
796 };
797
798
799 // double type - based on two floats
800
801#ifdef _MSC_VER
802#pragma optimize("p",off) // improve floating point precision consistency
803#endif
804 static t_atom *SetDouble(t_atom *dbl,double d)
805 {
806 float f = static_cast<float>(d);
807 float r = static_cast<float>(d-f);
808 SetFloat(dbl[0],f);
809 SetFloat(dbl[1],r);
810 return dbl;
811 }
812#ifdef _MSC_VER
813#pragma optimize("p",on)
814#endif
815
816 static double GetDouble(int argc,const t_atom *argv)
817 {
818 double d = argc >= 1?GetAFloat(argv[0]):0;
819 return argc >= 2?d+GetAFloat(argv[1]):d;
820 }
821
822 static AtomList &SetDouble(AtomList &l,double d) { SetDouble(l(2).Atoms(),d); return l; }
823
824 static double GetDouble(const AtomList &l) { return GetDouble(l.Count(),l.Atoms()); }
825
827
828
829// --- messages -------------------------------------------------------
830
835 class MsgBundle;
836
838 static MsgBundle *MsgNew();
839
841 static void MsgFree(MsgBundle *mb);
842
844 static void ToSysMsg(MsgBundle *mb);
845
847 static void ToOutMsg(MsgBundle *mb);
848
850 static void ToQueueMsg(MsgBundle *mb);
851
853
854
859 static bool Forward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
860 static bool Forward(const t_symbol *sym,const AtomAnything &args) { return Forward(sym,args.Header(),args.Count(),args.Atoms()); }
861 static bool Forward(const char *sym,const AtomAnything &args) { return Forward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
862 static bool Forward(const t_symbol *sym,int argc,const t_atom *argv) { return Forward(sym,sym_list,argc,argv); }
863 static bool Forward(const t_symbol *sym,const AtomList &args) { return Forward(sym,args.Count(),args.Atoms()); }
864 static bool Forward(const char *sym,const AtomList &args) { return Forward(MakeSymbol(sym),args.Count(),args.Atoms()); }
865
866 static bool SysForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
867 static bool SysForward(const t_symbol *sym,const AtomAnything &args) { return SysForward(sym,args.Header(),args.Count(),args.Atoms()); }
868 static bool SysForward(const char *sym,const AtomAnything &args) { return SysForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
869 static bool SysForward(const t_symbol *sym,int argc,const t_atom *argv) { return SysForward(sym,sym_list,argc,argv); }
870 static bool SysForward(const t_symbol *sym,const AtomList &args) { return SysForward(sym,args.Count(),args.Atoms()); }
871 static bool SysForward(const char *sym,const AtomList &args) { return SysForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
872
873 static bool QueueForward(const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
874 static bool QueueForward(const t_symbol *sym,const AtomAnything &args) { return QueueForward(sym,args.Header(),args.Count(),args.Atoms()); }
875 static bool QueueForward(const char *sym,const AtomAnything &args) { return QueueForward(MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
876 static bool QueueForward(const t_symbol *sym,int argc,const t_atom *argv) { return QueueForward(sym,sym_list,argc,argv); }
877 static bool QueueForward(const t_symbol *sym,const AtomList &args) { return QueueForward(sym,args.Count(),args.Atoms()); }
878 static bool QueueForward(const char *sym,const AtomList &args) { return QueueForward(MakeSymbol(sym),args.Count(),args.Atoms()); }
879
880 static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const t_symbol *s,int argc,const t_atom *argv);
881 static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomAnything &args) { return MsgForward(mb,sym,args.Header(),args.Count(),args.Atoms()); }
882 static bool MsgForward(MsgBundle *mb,const char *sym,const AtomAnything &args) { return MsgForward(mb,MakeSymbol(sym),args.Header(),args.Count(),args.Atoms()); }
883 static bool MsgForward(MsgBundle *mb,const t_symbol *sym,int argc,const t_atom *argv) { return MsgForward(mb,sym,sym_list,argc,argv); }
884 static bool MsgForward(MsgBundle *mb,const t_symbol *sym,const AtomList &args) { return MsgForward(mb,sym,args.Count(),args.Atoms()); }
885 static bool MsgForward(MsgBundle *mb,const char *sym,const AtomList &args) { return MsgForward(mb,MakeSymbol(sym),args.Count(),args.Atoms()); }
886
888
889
890
891// --- thread stuff -----------------------------------------------
892
897#if FLEXT_SYS == FLEXT_SYS_PD
898 #if PD_MINOR_VERSION >= 38 || (PD_MINOR_VERSION >= 37 && defined(PD_DEVEL_VERSION))
899 static void Lock() { sys_lock(); }
900 static void Unlock() { sys_unlock(); }
901 #else
902 // no system locking for old PD versions
903 static void Lock() {}
904 static void Unlock() {}
905 #endif
906#elif FLEXT_SYS == FLEXT_SYS_MAX
907 // Max 4.2 upwards!
908 static void Lock() { critical_enter(0); }
909 static void Unlock() { critical_exit(0); }
910#else
911#error
912#endif
913
915
921#ifdef FLEXT_THREADS
922 static bool IsThreadRegistered();
923#else
924 static bool IsThreadRegistered() { return false; }
925#endif
926
927#ifdef FLEXT_THREADS
928
930# if FLEXT_THREADS == FLEXT_THR_MP
931 typedef MPTaskID thrid_t;
932# elif FLEXT_THREADS == FLEXT_THR_POSIX
933 typedef pthread_t thrid_t;
934# elif FLEXT_THREADS == FLEXT_THR_WIN32
935 typedef DWORD thrid_t;
936# else
937# error Threading model not supported
938# endif
939
942 static thrid_t GetThreadId() {
943#if FLEXT_THREADS == FLEXT_THR_POSIX
944 return pthread_self();
945#elif FLEXT_THREADS == FLEXT_THR_MP
946 return MPCurrentTaskID();
947#elif FLEXT_THREADS == FLEXT_THR_WIN32
948 return GetCurrentThreadId();
949#else
950#error
951#endif
952 }
953
956 static thrid_t GetSysThreadId() { return thrid; }
957
959 static bool ShouldExit();
960
962 static bool IsThread(thrid_t t,thrid_t ref = GetThreadId()) {
963#if FLEXT_THREADS == FLEXT_THR_POSIX
964 return pthread_equal(ref,t) != 0;
965#else
966 return ref == t;
967#endif
968 }
969
970
975 public flext_root
976 {
977 public:
978 thr_params(int n = 1): cl(NULL),var(new _data[n]) {}
979 ~thr_params() { delete[] var; }
980
981 void set_any(const t_symbol *s,int argc,const t_atom *argv) { var[0]._any = new AtomAnything(s,argc,argv); }
982 void set_list(int argc,const t_atom *argv) { var[0]._list = new AtomList(argc,argv); }
983
985 union _data {
986 bool _bool;
987 float _float;
988 int _int;
992 void *_ext;
993 } *var;
994 };
995
996protected:
997
998 static thrid_t thrhelpid;
999 static thrid_t thrmsgid;
1000 static void ThrHelper(void *);
1001
1003 static thrid_t thrid; // the system thread
1004
1005private:
1006 static bool StartHelper(); // used in flext::Setup()
1007
1008public:
1009
1013 static void ThrYield() {
1014#if FLEXT_THREADS == FLEXT_THR_POSIX
1015 // for a preemptive system this should do nothing
1016 sched_yield();
1017#elif FLEXT_THREADS == FLEXT_THR_MP
1018 MPYield();
1019#elif FLEXT_THREADS == FLEXT_THR_WIN32
1021#else
1022#error
1023#endif
1024 }
1025
1028 static bool IsThreadPreemptive(thrid_t t = GetThreadId()) {
1029#if FLEXT_THREADS == FLEXT_THR_POSIX || FLEXT_THREADS == FLEXT_THR_WIN32
1030 return true;
1031#elif FLEXT_THREADS == FLEXT_THR_MP
1032 return MPTaskIsPreemptive(t);
1033#else
1034#error
1035#endif
1036 }
1037
1038
1041 static bool RelPriority(int dp,thrid_t ref = GetSysThreadId(),thrid_t thr = GetThreadId());
1042
1045 static int GetPriority(thrid_t thr = GetThreadId());
1046
1049 static bool SetPriority(int p,thrid_t thr = GetThreadId());
1050
1054 class FLEXT_SHARE ThrMutex:
1055 public flext_root
1056#if FLEXT_THREADS == FLEXT_THR_POSIX
1057 {
1058 public:
1063
1065 bool Lock() { return pthread_mutex_lock(&mutex) == 0; }
1069// bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1071 bool TryLock() { return pthread_mutex_trylock(&mutex) == 0; }
1073 bool Unlock() { return pthread_mutex_unlock(&mutex) == 0; }
1074
1075 protected:
1077// int cnt;
1078 };
1079#elif FLEXT_THREADS == FLEXT_THR_WIN32
1080 {
1081 public:
1086
1088 bool Lock() { ::EnterCriticalSection(&mutex); return true; }
1092// bool WaitForLock(double tm) { return pthread_mutex_lock(&mutex) == 0; }
1094 bool TryLock() { return ::TryEnterCriticalSection(&mutex) != 0; }
1096 bool Unlock() { ::LeaveCriticalSection(&mutex); return true; }
1097
1098 protected:
1100 };
1101#elif FLEXT_THREADS == FLEXT_THR_MP
1102 {
1103 public:
1108
1112// bool WaitForLock(double tm) { return MPEnterCriticalRegion(crit,tm*kDurationMicrosecond*1.e6) == noErr; }
1116 bool Unlock() { return MPExitCriticalRegion(crit) == noErr; }
1117
1118 protected:
1120 };
1121#else
1122#error "Not implemented"
1123#endif
1124
1128 class FLEXT_SHARE ThrCond
1130 :public ThrMutex
1131 {
1132 public:
1137
1139 bool Wait();
1140
1147 bool TimedWait(double ftime);
1148
1150 bool Signal() { return pthread_cond_signal(&cond) == 0; }
1151
1152 protected:
1154 };
1155#elif FLEXT_THREADS == FLEXT_THR_WIN32
1156 {
1157 public:
1161 ~ThrCond() { CloseHandle(cond); }
1162
1164 bool Wait() { return WaitForSingleObject(cond,INFINITE) == WAIT_OBJECT_0; }
1165
1172 bool TimedWait(double ftime) { return WaitForSingleObject(cond,(LONG)(ftime*1000)) == WAIT_OBJECT_0; }
1173
1175 bool Signal() { return SetEvent(cond) != 0; }
1176
1177 protected:
1178 HANDLE cond;
1179 };
1180#elif FLEXT_THREADS == FLEXT_THR_MP
1181 {
1182 public:
1184 ThrCond() { MPCreateEvent(&ev); }
1186 ~ThrCond() { MPDeleteEvent(ev); }
1187
1189 bool Wait() { return MPWaitForEvent(ev,NULL,kDurationForever) == noErr; }
1190
1194 bool TimedWait(double tm) { return MPWaitForEvent(ev,NULL,tm*kDurationMicrosecond*1.e6) == noErr; }
1195
1197 bool Signal() { return MPSetEvent(ev,1) == noErr; } // one bit needs to be set at least
1198
1199 protected:
1200 MPEventID ev;
1201 };
1202#else
1203#error "Not implemented"
1204#endif
1205
1206 protected:
1212 static bool PushThread();
1213
1218 static void PopThread();
1219
1220 public:
1226 static bool LaunchThread(void (*meth)(thr_params *p),thr_params *params = NULL);
1227
1235 static bool StopThread(void (*meth)(thr_params *p),thr_params *params = NULL,bool wait = false);
1236
1237
1239 static void RegisterThread(thrid_t id = GetThreadId());
1240
1242 static void UnregisterThread(thrid_t id = GetThreadId());
1243
1244#endif // FLEXT_THREADS
1245
1247
1248
1249 public:
1250// --- timer stuff -----------------------------------------------
1251
1264 static double GetTime()
1265 {
1266 #if FLEXT_SYS == FLEXT_SYS_PD
1267 return clock_gettimesince(0)*0.001;
1268 #elif FLEXT_SYS == FLEXT_SYS_MAX
1269 double tm;
1271 return tm*0.001;
1272 #else
1273 #error Not implemented
1274 #endif
1275 }
1276
1280 static double GetTimeGrain()
1281 {
1282 #if FLEXT_SYS == FLEXT_SYS_PD
1283 return 0;
1284 #elif FLEXT_SYS == FLEXT_SYS_MAX
1285 return 0.001;
1286 #else
1287 #error Not implemented
1288 #endif
1289 }
1290
1293 static double GetOSTime();
1294
1299 static void Sleep(double s);
1300
1304 class FLEXT_SHARE Timer:
1305 public flext_root
1306 {
1307 public:
1308 Timer(bool queued = false);
1309 virtual ~Timer();
1310
1312 void SetCallback(void (*cb)(void *data)) { clss = NULL,cback = cb; }
1314 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; }
1315
1317 bool Reset();
1319 bool At(double time,void *data = NULL,bool dopast = true);
1321 bool Delay(double time,void *data = NULL);
1323 bool Periodic(double time,void *data = NULL);
1325 bool Now(void *data = NULL) { return Delay(0,data); }
1326
1328 virtual void Work();
1329
1330 protected:
1331 static void callback(Timer *tmr);
1332
1333#if FLEXT_SYS == FLEXT_SYS_PD
1334 t_clock *clk;
1335#elif FLEXT_SYS == FLEXT_SYS_MAX
1336 static void queuefun(Timer *tmr);
1337 t_clock *clk;
1338 t_qelem *qelem;
1339#else
1340#error Not implemented
1341#endif
1342
1343 const bool queued;
1344 void (*cback)(void *data);
1346 void *userdata;
1347 double period;
1348 };
1349
1351
1353 static bool InDSP() { return indsp; }
1354
1355// --- SIMD functionality -----------------------------------------------
1356
1360 enum simd_type {
1361 simd_none = 0,
1362 simd_mmx = 0x01,
1363 simd_3dnow = 0x02,
1364 simd_sse = 0x04,
1365 simd_sse2 = 0x08,
1366 simd_altivec = 0x10
1367 };
1368
1370 static unsigned long GetSIMDCapabilities();
1371
1372
1373 static void MulSamples(t_sample *dst,const t_sample *src,t_sample mul,int cnt);
1374 static void MulSamples(t_sample *dst,const t_sample *src,const t_sample *mul,int cnt);
1375 static void AddSamples(t_sample *dst,const t_sample *src,t_sample add,int cnt);
1376 static void AddSamples(t_sample *dst,const t_sample *src,const t_sample *add,int cnt);
1377 static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,t_sample add,int cnt);
1378 static void ScaleSamples(t_sample *dst,const t_sample *src,t_sample mul,const t_sample *add,int cnt);
1379 static void ScaleSamples(t_sample *dst,const t_sample *src,const t_sample *mul,const t_sample *add,int cnt);
1380
1382
1383
1385
1386protected:
1387#ifdef __MRC__
1388 friend class flext_obj;
1389#endif
1390
1391 static void Setup();
1392
1393 static bool chktilde(const char *objname);
1394
1395 static unsigned long simdcaps;
1396
1397 static const t_symbol *sym_attributes;
1398 static const t_symbol *sym_methods;
1399
1400#if FLEXT_SYS == FLEXT_SYS_MAX
1401 static const t_symbol *sym_buffer;
1402 static const t_symbol *sym_size;
1403 static const t_symbol *sym_dirty;
1404#endif
1405
1407 static bool indsp;
1408};
1409
1410
1411// gcc doesn't like these to be included into the flext class (even if static)
1412inline bool operator ==(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) == 0; }
1413inline bool operator !=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) != 0; }
1414inline bool operator <(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) < 0; }
1415inline bool operator <=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) <= 0; }
1416inline bool operator >(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) > 0; }
1417inline bool operator >=(const t_atom &a,const t_atom &b) { return flext::CmpAtom(a,b) >= 0; }
1418
1420
1421#include "flpopns.h"
1422
1423#endif
Definition flclass.h:60
#define FLEXT_THR_POSIX
Definition flprefix.h:71
#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_THREADS
Definition flprefix.h:358
#define FLEXT_TEMPLATE
Definition flprefix.h:453
Definitions to unite Max/MSP and PD notions.
#define FLEXT_ASSERT(b)
Definition flstdc.h:316
t_symbol * t_symptr
Definition flstdc.h:255
#define FLEXT_CAST
Switch for compilation of derived virtual classes.
Definition fldefs.h:27
bool operator!=(const t_atom &a, const t_atom &b)
Definition flsupport.h:1413
bool operator==(const t_atom &a, const t_atom &b)
Definition flsupport.h:1412
bool operator>(const t_atom &a, const t_atom &b)
Definition flsupport.h:1416
bool operator<=(const t_atom &a, const t_atom &b)
Definition flsupport.h:1415
bool operator>=(const t_atom &a, const t_atom &b)
Definition flsupport.h:1417
bool operator<(const t_atom &a, const t_atom &b)
Definition flsupport.h:1414
#define DELTHROW
Definition flsupport.h:132
#define NEWTHROW
Definition flsupport.h:131