From d62e56f4df9594f72ce501f5e19c974fd18e7295 Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 22 Oct 2002 23:07:10 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r186, which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=187 --- externals/grill/flext/source/flsupport.h | 438 +++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 externals/grill/flext/source/flsupport.h (limited to 'externals/grill/flext/source/flsupport.h') diff --git a/externals/grill/flext/source/flsupport.h b/externals/grill/flext/source/flsupport.h new file mode 100644 index 00000000..148790ae --- /dev/null +++ b/externals/grill/flext/source/flsupport.h @@ -0,0 +1,438 @@ +/* + +flext - C++ layer for Max/MSP and pd (pure data) externals + +Copyright (c) 2001,2002 Thomas Grill (xovo@gmx.net) +For information on usage and redistribution, and for a DISCLAIMER OF ALL +WARRANTIES, see the file, "license.txt," in this distribution. + +*/ + +/*! \file flsupport.h + \brief flext support functions and classes +*/ + +#ifndef __FLSUPPORT_H +#define __FLSUPPORT_H + +#include "flstdc.h" + +#ifdef FLEXT_THREADS +#include +#endif + +class FLEXT_EXT flext { +public: +// --- buffer/array stuff ----------------------------------------- + + /*! \defgroup FLEXT_N_BUFFER Flext buffer handling + + @{ + */ + + //! Class for platform independent buffer handling + class buffer + { + public: + /*! \brief Construct buffer. + \param delayed = true: only sets name, needs another Set(NULL) to really initialize the buffer + \remark As externals can be created prior to the buffer objects they are pointing to, initialization should be done at loadbang! + */ + buffer(const t_symbol *s = NULL,bool delayed = false); + + //! Destroy buffer + ~buffer(); + + /*! \brief Check if the data is valid + */ + bool Ok() const { return sym != NULL && data != NULL; } + + /*! \brief Check and update if the buffer has been changed (e.g. resized) + */ + bool Update(); + + /*! \brief Set to specified buffer. + \param nameonly: if true sets name only, but doesn't look at buffer actually + */ + int Set(const t_symbol *s = NULL,bool nameonly = false); + + /*! \brief Declare buffer content as dirty. + \param refr: if true forces immediate graphics refresh + */ + void Dirty(bool refr = false); + + //! Get symbol of buffer + t_symbol *Symbol() const { return const_cast(sym); } + + //! Get literal name of buffer + const char *Name() const { return sym?sym->s_name:""; } + + /*! \brief Get pointer to buffer, channel and frame count. + \remark Channels are interleaved + */ + t_sample *Data() { return data; } + + //! Get channel count + int Channels() const { return chns; } + //! Get frame count + int Frames() const { return frames; } + //! Set frame count + void Frames(int fr,bool keep = false); + + //! Graphic auto refresh interval + void SetRefrIntv(float intv); + + protected: + const t_symbol *sym; + t_sample *data; + int chns,frames; +#ifdef PD + t_garray *arr; + float interval; + bool isdirty,ticking; + t_clock *tick; + + private: + static void cb_tick(buffer *b); +#endif + }; + +//! @} + +// --- various symbols -------------------------------------------- + + /*! \defgroup FLEXT_N_SYMBOL Flext atom/symbol handling + + @{ + */ + + //! Symbol constant for "float" + static const t_symbol *sym_float; + //! Symbol constant for "symbol" + static const t_symbol *sym_symbol; + //! Symbol constant for "bang" + static const t_symbol *sym_bang; + //! Symbol constant for "list" + static const t_symbol *sym_list; + //! Symbol constant for "anything" + static const t_symbol *sym_anything; + + /*! \brief Symbol constant for "int" + \note Only the Max/MSP system has this defined as an internal type + */ + static const t_symbol *sym_int; + + /*! Symbol constant for "pointer" + \note Only PD has this defined as an internal type + */ + static const t_symbol *sym_pointer; + +#ifdef PD + + /*! \brief Symbol constant for "signal" + \note PD only + */ + static const t_symbol *sym_signal; +#endif + + //! Make a symbol from a string + static const t_symbol *MakeSymbol(const char *s) { return gensym(const_cast(s)); } + + //! Get symbol string + static const char *GetString(const t_symbol *s) { return s->s_name; } + //! Check for symbol and get string + static const char *GetAString(const t_symbol *s) { return s?s->s_name:""; } + +//! @} + +// --- utilities -------------------------------------------------- + + /*! \defgroup FLEXT_C_UTIL Flext utility functions + + @{ + */ + + //! Copy an atom + static void CopyAtom(t_atom *dst,const t_atom *src) { *dst = *src; } + + //! Copy a list of atoms + static t_atom *CopyList(int argc,const t_atom *argv); + //! Copy a memory region + static void CopyMem(void *dst,const void *src,int bytes); + //! Sleep for an amount of time + static void Sleep(float s); + +//! @} + +// --- atom stuff ---------------------------------------- + + //! Set atom from another atom + static void SetAtom(t_atom &a,const t_atom &b) { CopyAtom(&a,&b); } + + //! Check whether the atom is nothing + static bool IsNothing(const t_atom &a) { return a.a_type == A_NULL; } + //! Set the atom to represent nothing + static void SetNothing(t_atom &a) { a.a_type = A_NULL; } + + //! Check whether the atom is a float + static bool IsFloat(const t_atom &a) { return a.a_type == A_FLOAT; } + //! Check whether the atom can be represented as a float + static bool CanbeFloat(const t_atom &a) { return IsFloat(a) || IsInt(a); } + //! Access the float value (without type check) + static float GetFloat(const t_atom &a) { return a.a_w.w_float; } + //! Set the atom to represent a float + static void SetFloat(t_atom &a,float v) { a.a_type = A_FLOAT; a.a_w.w_float = v; } + + //! Check whether the atom is a symbol + static bool IsSymbol(const t_atom &a) { return a.a_type == A_SYMBOL; } + //! Access the symbol value (without type check) + static t_symbol *GetSymbol(const t_atom &a) { return a.a_w.w_symbol; } + //! Check for a symbol and get its value + static t_symbol *GetASymbol(const t_atom &a) { return IsSymbol(a)?GetSymbol(a):NULL; } // NULL or empty symbol? + //! Set the atom to represent a symbol + static void SetSymbol(t_atom &a,const t_symbol *s) { a.a_type = A_SYMBOL; a.a_w.w_symbol = const_cast(s); } + + //! Check whether the atom is a string + static bool IsString(const t_atom &a) { return IsSymbol(a); } + //! Access the string value (without type check) + static const char *GetString(const t_atom &a) { t_symbol *s = GetSymbol(a); return s?GetString(s):NULL; } + //! Check for a string and get its value + static void GetAString(const t_atom &a,char *buf,int szbuf); + //! Set the atom to represent a string + static void SetString(t_atom &a,const char *c) { SetSymbol(a,gensym(const_cast(c))); } + + //! Check whether the atom can be represented as an integer + static bool CanbeInt(const t_atom &a) { return IsFloat(a) || IsInt(a); } + + //! Check whether the atom can be represented as a boolean + static bool CanbeBool(const t_atom &a) { return CanbeInt(a); } + //! Check for an boolean and get its value + static bool GetABool(const t_atom &a) { return GetAInt(a) != 0; } + +#ifdef PD + //! Check for a float and get its value + static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):0; } + + //! Check whether the atom is an integer + static bool IsInt(const t_atom &) { return false; } + //! Access the integer value (without type check) + static int GetInt(const t_atom &a) { return (int)GetFloat(a); } + //! Check for an integer and get its value + static int GetAInt(const t_atom &a) { return (int)GetAFloat(a); } + //! Set the atom to represent a integer (depending on the system) + static void SetInt(t_atom &a,int v) { a.a_type = A_FLOAT; a.a_w.w_float = (float)v; } + + //! Check whether the atom is a pointer + static bool IsPointer(const t_atom &a) { return a.a_type == A_POINTER; } + //! Access the pointer value (without type check) + static t_gpointer *GetPointer(const t_atom &a) { return a.a_w.w_gpointer; } + //! Check for a pointer and get its value + static t_gpointer *GetAPointer(const t_atom &a) { return IsPointer(a)?GetPointer(a):NULL; } + //! Set the atom to represent a pointer + static void SetPointer(t_atom &a,t_gpointer *p) { a.a_type = A_POINTER; a.a_w.w_gpointer = p; } + +#elif defined(MAXMSP) + //! Check for a float and get its value + static float GetAFloat(const t_atom &a) { return IsFloat(a)?GetFloat(a):(IsInt(a)?GetInt(a):0); } + + //! Check whether the atom is an int + static bool IsInt(const t_atom &a) { return a.a_type == A_INT; } + //! Access the integer value (without type check) + static int GetInt(const t_atom &a) { return a.a_w.w_long; } + //! Check for an integer and get its value + static int GetAInt(const t_atom &a) { return IsInt(a)?GetInt(a):(IsFloat(a)?GetFloat(a):0); } + //! Set the atom to represent an integer + static void SetInt(t_atom &a,int v) { a.a_type = A_INT; a.a_w.w_long = v; } + + //! Check whether the atom is a pointer + static bool IsPointer(const t_atom &) { return false; } + //! Access the pointer value (without type check) + static void *GetPointer(const t_atom &) { return NULL; } + //! Check for a pointer and get its value + static void *GetAPointer(const t_atom &) { return NULL; } +// void SetPointer(t_atom &,void *) {} +#endif + +// --- atom list stuff ------------------------------------------- + + /*! \defgroup FLEXT_N_ATOM Flext atom/list handling + + @{ + */ + + //! Class representing a list of atoms + class AtomList + { + public: + //! Construct list + AtomList(int argc = 0,const t_atom *argv = NULL); + //! Construct list + AtomList(const AtomList &a); + //! Destroy list + ~AtomList(); + + //! Clear list + AtomList &Clear() { return operator()(); } + + //! Set list + AtomList &operator()(int argc = 0,const t_atom *argv = NULL); + //! Set list by another AtomList + AtomList &operator =(const AtomList &a) { return operator()(a.Count(),a.Atoms()); } + + //! Get number of atoms in the list + int Count() const { return cnt; } + //! Get a reference to an indexed atom + t_atom &operator [](int ix) { return lst[ix]; } + //! Get a reference to an indexed atom + const t_atom &operator [](int ix) const { return lst[ix]; } + + //! Get a pointer to the list of atoms + t_atom *Atoms() { return lst; } + //! Get a pointer to the list of atoms + const t_atom *Atoms() const { return lst; } + + //! Append an atom to the list + AtomList &Append(const t_atom &a); + //! Append an atom list to the list + AtomList &Append(int argc,const t_atom *argv); + //! Append an atom list to the list + AtomList &Append(const AtomList &a) { return Append(a.Count(),a.Atoms()); } + //! Prepend an atom to the list + AtomList &Prepend(const t_atom &a); + //! Prepend an atom list to the list + AtomList &Prepend(int argc,const t_atom *argv); + //! Prepend an atom list to the list + AtomList &Prepend(const AtomList &a) { return Prepend(a.Count(),a.Atoms()); } + + //! Get a part of the list + AtomList GetPart(int offs,int len) const; + //! Set to a part of the list + AtomList &Part(int offs,int len) { return (*this = GetPart(offs,len)); } + + protected: + int cnt; + t_atom *lst; + }; + + + //! Class representing an "anything" + class AtomAnything: + public AtomList + { + public: + //! Construct anything + AtomAnything(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(h) {} + //! Construct anything + AtomAnything(const char *h,int argc = 0,const t_atom *argv = NULL): AtomList(argc,argv),hdr(MakeSymbol(h)) {} + //! Construct anything + AtomAnything(const AtomAnything &a): AtomList(a),hdr(a.hdr) {} + + //! Clear anything + AtomAnything &Clear() { return operator()(); } + + //! Get header symbol of anything + const t_symbol *Header() const { return hdr; } + + //! Set anything + AtomAnything &operator()(const t_symbol *h = NULL,int argc = 0,const t_atom *argv = NULL) + { + hdr = h; AtomList::operator()(argc,argv); + return *this; + } + + //! Set list by another AtomAnything + AtomAnything &operator =(const AtomAnything &a) { return operator()(a.Header(),a.Count(),a.Atoms()); } + + protected: + const t_symbol *hdr; + }; + +//! @} + +// --- clock stuff ------------------------------------------------ + + + /*! \defgroup FLEXT_N_CLOCK Flext clock functions + + At the moment there are none + + @{ + */ + +//! @} + + +// --- thread stuff ----------------------------------------------- + +#ifdef FLEXT_THREADS + /*! \defgroup FLEXT_N_THREAD Flext thread handling + + @{ + */ + + /*! \brief Thread mutex + \sa pthreads documentation + */ + class ThrMutex + { + public: + //! Construct thread mutex + ThrMutex(): cnt(0) { pthread_mutex_init(&mutex,NULL); } + //! Destroy thread mutex + ~ThrMutex() { pthread_mutex_destroy(&mutex); } + + //! Lock thread mutex + int Lock() { cnt = 1; return pthread_mutex_lock(&mutex); } + //! Try to lock, but don't wait + int TryLock() { return pthread_mutex_trylock(&mutex); } + //! Unlock thread mutex + int Unlock() { cnt = 0; return pthread_mutex_unlock(&mutex); } + + //! Lock thread mutex (increase lock count by one) + void Push() { if(!cnt++) Lock(); } + //! Unlock thread mutex if lock count reaches zero + void Pop() { if(!--cnt) Unlock(); } + protected: + pthread_mutex_t mutex; + int cnt; + }; + + /*! \brief Thread conditional + \sa pthreads documentation + */ + class ThrCond: + public ThrMutex + { + public: + //! Construct thread conditional + ThrCond() { pthread_cond_init(&cond,NULL); } + //! Destroy thread conditional + ~ThrCond() { pthread_cond_destroy(&cond); } + + //! Wait for condition + int Wait() { return pthread_cond_wait(&cond,&mutex); } + + /*! \brief Wait for condition (for a certain time) + \param time Wait time in seconds + */ + int TimedWait(float time) + { + timespec tm; tm.tv_sec = (long)time; tm.tv_nsec = (long)((time-(long)time)*1.e9); + return pthread_cond_timedwait(&cond,&mutex,&tm); + } + + //! Signal condition + int Signal() { return pthread_cond_signal(&cond); } + //! Broadcast condition + int Broadcast() { return pthread_cond_broadcast(&cond); } + protected: + pthread_cond_t cond; + }; +//! @} +#endif // FLEXT_THREADS + +protected: + static void Setup(); +}; + +#endif -- cgit v1.2.1