flclass.h 25.1 KB
Newer Older
thomas's avatar
thomas committed
1
2
3
4
5
6
7
8
9
10
11
/* 

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 flclass.h
thomas's avatar
thomas committed
12
	\brief User accessible flext base classes
thomas's avatar
thomas committed
13
14
15
16
17
18
    
*/

#ifndef __FLCLASS_H
#define __FLCLASS_H

thomas's avatar
thomas committed
19
// include the header file declaring the base classes
thomas's avatar
thomas committed
20
#include "flbase.h"
thomas's avatar
thomas committed
21
#include "flsupport.h"
thomas's avatar
thomas committed
22
23
24
25
26
27
28
29
30
31
32

#ifdef _MSC_VER
#pragma warning(disable: 4786)
#endif

#ifdef __BORLANDC__
#pragma warn -8008 // Condition is always false
#pragma warn -8057 // Parameter is never used
#pragma warn -8066 // Unreachable code
#endif

thomas's avatar
thomas committed
33

thomas's avatar
thomas committed
34
35
// === flext_base ==================================================

thomas's avatar
thomas committed
36
37
38
//class qmsg;
//class thr_entry;

thomas's avatar
thomas committed
39
40
41
/*! \brief Flext message only base object
*/

thomas's avatar
thomas committed
42

thomas's avatar
thomas committed
43
class flext_base: 
thomas's avatar
thomas committed
44
45
46
47
	public flext_obj
{
	FLEXT_HEADER_S(flext_base,flext_obj,Setup)
	
thomas's avatar
thomas committed
48
49
	friend class flext_obj;

thomas's avatar
thomas committed
50
51
52
	/*!	\defgroup FLEXT_CLASS Flext base class
		@{ 
	*/
thomas's avatar
thomas committed
53
54
public:

thomas's avatar
thomas committed
55
	/*!	\defgroup FLEXT_C_BASE Basic class functionality
thomas's avatar
thomas committed
56
57
58
		@{ 
	*/

thomas's avatar
thomas committed
59
60
61
62
63
64
65
66
// ---  compatibility mode ----------------------------------------

	/*! \brief Cross-platform compatibility flag.
		If set flext allows only operations valid for all platforms.
		Set to true by default!
	*/
	static bool compatibility;  

thomas's avatar
thomas committed
67
68
//!		@} FLEXT_C_BASE

thomas's avatar
thomas committed
69
70
// --- inheritable virtual methods --------------------------------

thomas's avatar
thomas committed
71
	/*!	\defgroup FLEXT_C_VIRTUAL Virtual base class functions
thomas's avatar
thomas committed
72
73
74
75

		@{ 
	*/

thomas's avatar
thomas committed
76
77
78
79
80
81
	//! called on "help" message: should post some text
	virtual void m_help();
	
	//! called on patcher load (not on mere object creation!)
	virtual void m_loadbang() {}

thomas's avatar
thomas committed
82
	//! quickhelp for inlets/outlets (gets called in Max/MSP only)
thomas's avatar
thomas committed
83
84
85
86
87
	virtual void m_assist(long /*msg*/,long /*arg*/,char * /*s*/) {}

	/*!	\brief Called for every incoming message.
		All method handling is done in there
		\return True if a handler was found and called
thomas's avatar
thomas committed
88
		\todo Once, there should be a const modifier for argv
thomas's avatar
thomas committed
89
	*/
thomas's avatar
thomas committed
90
	virtual bool m_methodmain(int inlet,const t_symbol *s,int argc,const t_atom *argv);
thomas's avatar
thomas committed
91

thomas's avatar
thomas committed
92
93
94
	/*! \brief Called for every unhandled message (by m_methodmain)
		\todo Once, there should be a const modifier for argv
	*/
thomas's avatar
thomas committed
95
	virtual bool m_method_(int inlet,const t_symbol *s,int argc,const t_atom *argv);
thomas's avatar
thomas committed
96

thomas's avatar
thomas committed
97
//!		@} FLEXT_C_VIRTUAL
thomas's avatar
thomas committed
98

thomas's avatar
thomas committed
99

thomas's avatar
thomas committed
100
101
// --- inlet/outlet stuff -----------------------------------------	

thomas's avatar
thomas committed
102
103
104
	/*!	\defgroup FLEXT_C_INOUT Flext in-/outlet functions
		\note These must be called in the class' constructor
		\note All (also default) inlets must be defined
thomas's avatar
thomas committed
105
106
		@{ 
	*/
thomas's avatar
thomas committed
107

thomas's avatar
thomas committed
108
	/*!	\defgroup FLEXT_C_IO_ADD Announce in-/outlet functions
thomas's avatar
thomas committed
109
110
111
		@{ 
	*/

thomas's avatar
thomas committed
112
113
114
115
	// argument m specifies multiple inlet/outlet count
	
//	void AddInDef() { AddInlet(xlet::tp_def,1); }

thomas's avatar
thomas committed
116
	/*! \brief Add inlet(s) for anythings
thomas's avatar
thomas committed
117
		\remark That's the one to choose for the left-most (first) inlet unless it's a signal inlet.
thomas's avatar
thomas committed
118
	*/
thomas's avatar
thomas committed
119
	void AddInAnything(int m = 1) { AddInlet(xlet::tp_any,m); } 
thomas's avatar
thomas committed
120
121
122
	/*! \brief Add inlet(s) for anythings (with description)
		\remark That's the one to choose for the left-most (first) inlet unless it's a signal inlet.
	*/
thomas's avatar
thomas committed
123
	void AddInAnything(const char *desc,int m = 1) { AddInlet(xlet::tp_any,m,desc); } 
thomas's avatar
thomas committed
124
	//! Add inlet(s) for floats
thomas's avatar
thomas committed
125
	void AddInFloat(int m = 1) { AddInlet(xlet::tp_float,m); }
thomas's avatar
thomas committed
126
	//! Add inlet(s) for floats (with description)
thomas's avatar
thomas committed
127
	void AddInFloat(const char *desc,int m = 1) { AddInlet(xlet::tp_float,m,desc); }
thomas's avatar
thomas committed
128
	//! Add inlet(s) for integers
thomas's avatar
thomas committed
129
	void AddInInt(int m = 1) { AddInlet(xlet::tp_int,m); }
thomas's avatar
thomas committed
130
	//! Add inlet(s) for integers (with description)
thomas's avatar
thomas committed
131
	void AddInInt(const char *desc,int m = 1) { AddInlet(xlet::tp_int,m,desc); }
thomas's avatar
thomas committed
132
	//! Add inlet(s) for symbols
thomas's avatar
thomas committed
133
	void AddInSymbol(int m = 1) { AddInlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
134
	//! Add inlet(s) for symbol (with description)
thomas's avatar
thomas committed
135
	void AddInSymbol(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
136
	//! Add inlet(s) for bang
thomas's avatar
thomas committed
137
	void AddInBang(int m = 1) { AddInlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
138
	//! Add inlet(s) for bangs (with description)
thomas's avatar
thomas committed
139
	void AddInBang(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
140
	//! Add inlet(s) for lists
thomas's avatar
thomas committed
141
	void AddInList(int m = 1) { AddInlet(xlet::tp_list,m); }  
thomas's avatar
thomas committed
142
	//! Add inlet(s) for lists (with description)
thomas's avatar
thomas committed
143
	void AddInList(const char *desc,int m = 1) { AddInlet(xlet::tp_list,m,desc); }  
thomas's avatar
thomas committed
144
	
thomas's avatar
thomas committed
145
	//! Add outlet(s) for anythings
thomas's avatar
thomas committed
146
	void AddOutAnything(int m = 1) { AddOutlet(xlet::tp_any,m); }
thomas's avatar
thomas committed
147
	//! Add outlet(s) for anythings (with description)
thomas's avatar
thomas committed
148
	void AddOutAnything(const char *desc,int m = 1) { AddOutlet(xlet::tp_any,m,desc); }
thomas's avatar
thomas committed
149
	//! Add outlet(s) for floats
thomas's avatar
thomas committed
150
	void AddOutFloat(int m = 1) { AddOutlet(xlet::tp_float,m); }
thomas's avatar
thomas committed
151
	//! Add outlet(s) for floats (with description)
thomas's avatar
thomas committed
152
	void AddOutFloat(const char *desc,int m = 1) { AddOutlet(xlet::tp_float,m,desc); }
thomas's avatar
thomas committed
153
	//! Add outlet(s) for integers
thomas's avatar
thomas committed
154
	void AddOutInt(int m = 1) { AddOutlet(xlet::tp_int,m); }
thomas's avatar
thomas committed
155
	//! Add outlet(s) for integers (with description)
thomas's avatar
thomas committed
156
	void AddOutInt(const char *desc,int m = 1) { AddOutlet(xlet::tp_int,m,desc); }
thomas's avatar
thomas committed
157
	//! Add outlet(s) for symbols
thomas's avatar
thomas committed
158
	void AddOutSymbol(int m = 1) { AddOutlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
159
	//! Add outlet(s) for symbols (with description)
thomas's avatar
thomas committed
160
	void AddOutSymbol(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
161
	//! Add outlet(s) for bangs
thomas's avatar
thomas committed
162
	void AddOutBang(int m = 1) { AddOutlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
163
	//! Add outlet(s) for bangs (with description)
thomas's avatar
thomas committed
164
	void AddOutBang(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
165
	//! Add outlet(s) for lists
thomas's avatar
thomas committed
166
	void AddOutList(int m = 1) { AddOutlet(xlet::tp_list,m); }
thomas's avatar
thomas committed
167
	//! Add outlet(s) for lists (with description)
thomas's avatar
thomas committed
168
	void AddOutList(const char *desc,int m = 1) { AddOutlet(xlet::tp_list,m,desc); }
thomas's avatar
thomas committed
169

thomas's avatar
thomas committed
170
	//! \deprecated inlets and outlets are now set up automatically
thomas's avatar
thomas committed
171
	bool SetupInOut() { return true; }
thomas's avatar
thomas committed
172

thomas's avatar
thomas committed
173
174
175
176
177
178
	//!	@} FLEXT_C_IO_ADD 

	/*!	\defgroup FLEXT_C_IO_MISC Miscellanous in-/outlet functionality
		@{ 
	*/

thomas's avatar
thomas committed
179
	//! Get number of inlets
thomas's avatar
thomas committed
180
	int CntIn() const { return incnt; }
thomas's avatar
thomas committed
181
	//! Get number of outlets
thomas's avatar
thomas committed
182
	int CntOut() const { return outcnt; }
thomas's avatar
thomas committed
183
	//! Get number of signal inlets
thomas's avatar
thomas committed
184
	int CntInSig() const { return insigs; }
thomas's avatar
thomas committed
185
	//! Get number of signal outlets
thomas's avatar
thomas committed
186
187
188
189
	int CntOutSig() const { return outsigs; }

	class outlet;

thomas's avatar
thomas committed
190
191
192
	//! Retrieve currently processed message tag (NULL if no message processing)
	const t_symbol *thisTag() const { return curtag; }

thomas's avatar
thomas committed
193
	//! Get pointer to outlet (not in the constructor!)
thomas's avatar
thomas committed
194
	outlet *GetOut(int ix) const { return (outlets && ix < outcnt)?outlets[ix]:NULL; }
thomas's avatar
thomas committed
195

thomas's avatar
thomas committed
196
	//! Get pointer to attribute outlet 
thomas's avatar
thomas committed
197
	outlet *GetOutAttr() const { return outattr; }
thomas's avatar
thomas committed
198

thomas's avatar
thomas committed
199
200
201
202
203
204
	//! @} FLEXT_C_IO_MISC

	/*!	\defgroup FLEXT_C_IO_OUT Output data to inlets/outlets
		@{ 
	*/

thomas's avatar
thomas committed
205
	// output messages 
thomas's avatar
thomas committed
206

thomas's avatar
thomas committed
207
	//! Output bang (to appointed outlet)
thomas's avatar
thomas committed
208
	void ToOutBang(outlet *o) const;
thomas's avatar
thomas committed
209
	//! Output bang (index n starts with 0)
thomas's avatar
thomas committed
210
	void ToOutBang(int n) const { outlet *o = GetOut(n); if(o) ToOutBang(o); }
thomas's avatar
thomas committed
211

thomas's avatar
thomas committed
212
	//! Output float (to appointed outlet)
thomas's avatar
thomas committed
213
	void ToOutFloat(outlet *o,float f) const; 
thomas's avatar
thomas committed
214
	//! Output float (index n starts with 0)
thomas's avatar
thomas committed
215
	void ToOutFloat(int n,float f) const { outlet *o = GetOut(n); if(o) ToOutFloat(o,f); }
thomas's avatar
thomas committed
216

thomas's avatar
thomas committed
217
	//! Output integer (to appointed outlet)
thomas's avatar
thomas committed
218
	void ToOutInt(outlet *o,int f) const; 
thomas's avatar
thomas committed
219
	//! Output integer (index n starts with 0)
thomas's avatar
thomas committed
220
	void ToOutInt(int n,int f) const { outlet *o = GetOut(n); if(o) ToOutInt(o,f); }
thomas's avatar
thomas committed
221
	
thomas's avatar
thomas committed
222
	//! Output symbol (to appointed outlet)
thomas's avatar
thomas committed
223
	void ToOutSymbol(outlet *o,const t_symbol *s) const; 
thomas's avatar
thomas committed
224
	//! Output symbol (index n starts with 0)
thomas's avatar
thomas committed
225
	void ToOutSymbol(int n,const t_symbol *s) const { outlet *o = GetOut(n); if(o) ToOutSymbol(o,s); }
thomas's avatar
thomas committed
226
	//! Output string aka symbol (to appointed outlet)
thomas's avatar
thomas committed
227
	void ToOutString(outlet *o,const char *s) const { ToOutSymbol(o,MakeSymbol(s)); }
thomas's avatar
thomas committed
228
	//! Output string aka symbol (index n starts with 0)
thomas's avatar
thomas committed
229
	void ToOutString(int n,const char *s) const { outlet *o = GetOut(n); if(o) ToOutString(o,s); }
thomas's avatar
thomas committed
230

thomas's avatar
thomas committed
231
	//! Output list (to appointed outlet)
thomas's avatar
thomas committed
232
	void ToOutList(outlet *o,int argc,const t_atom *argv) const; 
thomas's avatar
thomas committed
233
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
234
	void ToOutList(int n,int argc,const t_atom *argv) const { outlet *o = GetOut(n); if(o) ToOutList(o,argc,argv); }
thomas's avatar
thomas committed
235
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
236
	void ToOutList(int n,const AtomList &list) const { ToOutList(n,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
237
	
thomas's avatar
thomas committed
238
	//! Output anything (to appointed outlet)
thomas's avatar
thomas committed
239
	void ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) const; 
thomas's avatar
thomas committed
240
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
241
	void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const  { outlet *o = GetOut(n); if(o) ToOutAnything(o,const_cast<t_symbol *>(s),argc,argv); }
thomas's avatar
thomas committed
242
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
243
	void ToOutAnything(int n,const AtomAnything &any) const { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
244
	
thomas's avatar
thomas committed
245
246
247
248
249
250
251
	//! @} FLEXT_C_IO_OUT

	/*!	\defgroup FLEXT_C_IO_QUEUE Low-priority output of data to inlets/outlets
		@{ 
	*/

	//! Output bang (to appointed outlet)
thomas's avatar
thomas committed
252
	void ToQueueBang(outlet *o) const; 
thomas's avatar
thomas committed
253
	//! Output bang (index n starts with 0)
thomas's avatar
thomas committed
254
	void ToQueueBang(int n) const { outlet *o = GetOut(n); if(o) ToQueueBang(o); }
thomas's avatar
thomas committed
255
256

	//! Output float (to appointed outlet)
thomas's avatar
thomas committed
257
	void ToQueueFloat(outlet *o,float f) const; 
thomas's avatar
thomas committed
258
	//! Output float (index n starts with 0)
thomas's avatar
thomas committed
259
	void ToQueueFloat(int n,float f) const { outlet *o = GetOut(n); if(o) ToQueueFloat(o,f); }
thomas's avatar
thomas committed
260
261

	//! Output integer (to appointed outlet)
thomas's avatar
thomas committed
262
	void ToQueueInt(outlet *o,int f) const; 
thomas's avatar
thomas committed
263
	//! Output integer (index n starts with 0)
thomas's avatar
thomas committed
264
	void ToQueueInt(int n,int f) const { outlet *o = GetOut(n); if(o) ToQueueInt(o,f); }
thomas's avatar
thomas committed
265
266

	//! Output symbol (to appointed outlet)
thomas's avatar
thomas committed
267
	void ToQueueSymbol(outlet *o,const t_symbol *s) const; 
thomas's avatar
thomas committed
268
	//! Output symbol (index n starts with 0)
thomas's avatar
thomas committed
269
	void ToQueueSymbol(int n,const t_symbol *s) const { outlet *o = GetOut(n); if(o) ToQueueSymbol(o,s); }
thomas's avatar
thomas committed
270
	//! Output string aka symbol (to appointed outlet)
thomas's avatar
thomas committed
271
	void ToQueueString(outlet *o,const char *s) const { ToQueueSymbol(o,MakeSymbol(s)); }
thomas's avatar
thomas committed
272
	//! Output string aka symbol (to appointed outlet)
thomas's avatar
thomas committed
273
	void ToQueueString(int n,const char *s) const { ToQueueSymbol(n,MakeSymbol(s)); }
thomas's avatar
thomas committed
274
275

	//! Output list (to appointed outlet)
thomas's avatar
thomas committed
276
	void ToQueueList(outlet *o,int argc,const t_atom *argv) const; 
thomas's avatar
thomas committed
277
	//! Output list (to appointed outlet)
thomas's avatar
thomas committed
278
	void ToQueueList(outlet *o,const AtomList &list) const { ToQueueList(o,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
279
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
280
	void ToQueueList(int n,int argc,const t_atom *argv) const { outlet *o = GetOut(n); if(o) ToQueueList(o,argc,argv); }
thomas's avatar
thomas committed
281
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
282
	void ToQueueList(int n,const AtomList &list) const  { ToQueueList(n,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
283
284

	//! Output anything (to appointed outlet)
thomas's avatar
thomas committed
285
	void ToQueueAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv) const; 
thomas's avatar
thomas committed
286
	//! Output anything (to appointed outlet)
thomas's avatar
thomas committed
287
	void ToQueueAnything(outlet *o,const AtomAnything &any) const  { ToQueueAnything(o,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
288
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
289
	void ToQueueAnything(int n,const t_symbol *s,int argc,const t_atom *argv)  const { outlet *o = GetOut(n); if(o) ToQueueAnything(o,s,argc,argv); }
thomas's avatar
thomas committed
290
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
291
	void ToQueueAnything(int n,const AtomAnything &any) const  { ToQueueAnything(n,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
292

thomas's avatar
thomas committed
293
294
295
//!		@} FLEXT_C_IO_QUEUE

//!	@} FLEXT_C_INOUT
thomas's avatar
thomas committed
296

thomas's avatar
thomas committed
297

thomas's avatar
thomas committed
298
299
300
301
// --- message handling -------------------------------------------

	enum metharg {
		a_null = 0,
thomas's avatar
thomas committed
302
		a_float,a_int,
thomas's avatar
thomas committed
303
		a_symbol,a_pointer,
thomas's avatar
thomas committed
304
305
		a_list,a_any,
		a_LIST,a_ANY
thomas's avatar
thomas committed
306
307
	};

thomas's avatar
thomas committed
308
	typedef bool (*methfun)(flext_base *c);
thomas's avatar
thomas committed
309

thomas's avatar
thomas committed
310
	/*!	\defgroup FLEXT_C_ADDMETHOD Method handling
thomas's avatar
thomas committed
311
312
313
314
		\internal
		@{ 
	*/

thomas's avatar
thomas committed
315
	void AddMethodDef(int inlet,const char *tag = NULL); // call virtual function for tag && inlet
thomas's avatar
thomas committed
316
317
	void AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...); 

thomas's avatar
thomas committed
318
	void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_list,a_null); }
thomas's avatar
thomas committed
319
	void AddMethod(int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_list,a_null); }
thomas's avatar
thomas committed
320
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,tag,(methfun)m,a_null); }  // pure method
thomas's avatar
thomas committed
321
322
	void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_any,a_null); } // anything
	void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_any,a_null); } // anything
thomas's avatar
thomas committed
323
	void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol
thomas's avatar
thomas committed
324
	void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol
thomas's avatar
thomas committed
325
326
327
	void AddMethod(int inlet,bool (*m)(flext_base *,float &)) { AddMethod(inlet,"float",(methfun)m,a_float,a_null); }  // single float
	void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_null); } // list of 2 floats
	void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(inlet,"list",(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats
thomas's avatar
thomas committed
328
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
329
	void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"float",(methfun)m,a_int,a_null); }  // single float
thomas's avatar
thomas committed
330
#elif FLEXT_SYS == FLEXT_SYS_MAX
thomas's avatar
thomas committed
331
	void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(inlet,"int",(methfun)m,a_int,a_null); }  // single float
thomas's avatar
thomas committed
332
333
#else
#error
thomas's avatar
thomas committed
334
#endif
thomas's avatar
thomas committed
335
336
	void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_null); } // list of 2 floats
	void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(inlet,"list",(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats
thomas's avatar
thomas committed
337
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
thomas's avatar
thomas committed
338
339
340
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
thomas's avatar
thomas committed
341
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
thomas's avatar
thomas committed
342
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
thomas's avatar
thomas committed
343
344
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(inlet,tag,(methfun)m,a_float,a_null); }  // method+float
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(inlet,tag,(methfun)m,a_int,a_null); } // method+int
thomas's avatar
thomas committed
345

thomas's avatar
thomas committed
346
	//! Set Max/MSP style of distributing list elements over (message) inlets
thomas's avatar
thomas committed
347
348
	void SetDist(bool d = true) { distmsgs = d; }

thomas's avatar
thomas committed
349
//!		@} FLEXT_C_ADDMETHOD
thomas's avatar
thomas committed
350

thomas's avatar
thomas committed
351
// --- bind/unbind ---------------------------------------
thomas's avatar
thomas committed
352

thomas's avatar
thomas committed
353
354
355
356
357
	/*!	\defgroup FLEXT_C_BIND Methods for binding a flext class to a symbol

		@{ 
	*/

thomas's avatar
thomas committed
358
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
359
360
361
362
	//! Bind object to a symbol
	bool Bind(const t_symbol *s) { pd_bind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
	//! Unbind object from a symbol
	bool Unbind(const t_symbol *s) { pd_unbind(&thisHdr()->ob_pd,const_cast<t_symbol *>(s)); return true; }
thomas's avatar
thomas committed
363
#else
thomas's avatar
thomas committed
364
365
366
367
	//! Bind object to a symbol
	bool Bind(const t_symbol *s) { if(s->s_thing) return false; else { const_cast<t_symbol *>(s)->s_thing = (t_object *)thisHdr(); return true; } }
	//! Unbind object from a symbol
	bool Unbind(const t_symbol *s) { if(s->s_thing != (t_object *)thisHdr()) return false; else { const_cast<t_symbol *>(s)->s_thing = NULL; return true; } }
thomas's avatar
thomas committed
368
#endif
thomas's avatar
thomas committed
369
370
371
372
	//! Bind object to a symbol (as string)
	bool Bind(const char *c) { return Bind(MakeSymbol(c)); }  
	//! Unbind object from a symbol (as string)
	bool Unbind(const char *c) { return Unbind(MakeSymbol(c)); }  
thomas's avatar
thomas committed
373

thomas's avatar
thomas committed
374
/*
thomas's avatar
thomas committed
375
376
	// Low level

thomas's avatar
thomas committed
377
378
379
380
381
382
	//! Bind object to a symbol
	static void DoUnbind(t_symbol *s,flext_obj *o);
	//! Unbind object from a symbol
	static void DoBind(const t_symbol *s,flext_obj *o);
	//! Get bound object of a symbol
	static t_class **GetBound(const t_symbol *s) { return (t_class **)s->s_thing; }
thomas's avatar
thomas committed
383
*/
thomas's avatar
thomas committed
384

thomas's avatar
thomas committed
385
386
//!		@} FLEXT_C_BIND

thomas's avatar
thomas committed
387
// --- thread stuff -----------------------------------------------
thomas's avatar
thomas committed
388

thomas's avatar
thomas committed
389
#ifdef FLEXT_THREADS
thomas's avatar
thomas committed
390
	/*!	\defgroup FLEXT_C_THREAD Thread handling 
thomas's avatar
thomas committed
391
392
393
394
395
396
397

		@{ 
	*/

	/*! \brief Check if current thread should terminate
		\todo Check for currently running thread
	*/
thomas's avatar
thomas committed
398
	bool ShouldExit() const { return shouldexit; }
thomas's avatar
thomas committed
399

thomas's avatar
thomas committed
400
	//! Check if current thread is the realtime system's thread
thomas's avatar
thomas committed
401
	bool IsSystemThread() const { pthread_t cur = pthread_self(); return pthread_equal(cur,thrid) != 0; }
thomas's avatar
thomas committed
402

thomas's avatar
thomas committed
403
404
405
	/*! \brief Yield to other threads
		\remark A call to this is only needed for systems with cooperative multitasking like MacOS<=9
	*/
thomas's avatar
thomas committed
406
	static void ThrYield() { sched_yield(); }
thomas's avatar
thomas committed
407

thomas's avatar
thomas committed
408
409
	typedef pthread_t thrid_t;

thomas's avatar
thomas committed
410
411
412
413
	/*! \brief Get current thread id
	*/
	static thrid_t GetThreadId();

thomas's avatar
thomas committed
414
415
416
417
418
	/*! \brief Increase/Decrease priority of a thread
	*/
	static bool ChangePriority(int dp,thrid_t thr = GetThreadId());

	/*! \brief Get priority of a thread
thomas's avatar
thomas committed
419
	*/
thomas's avatar
thomas committed
420
421
422
423
424
	static int GetPriority(thrid_t thr = GetThreadId());

	/*! \brief Set priority of a thread
	*/
	static bool SetPriority(int p,thrid_t thr = GetThreadId());
thomas's avatar
thomas committed
425

thomas's avatar
thomas committed
426

thomas's avatar
thomas committed
427
428
#endif // FLEXT_THREADS

thomas's avatar
thomas committed
429
//!		@}  FLEXT_C_THREAD
thomas's avatar
thomas committed
430

thomas's avatar
thomas committed
431
432
// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

thomas's avatar
thomas committed
433
434
protected:

thomas's avatar
thomas committed
435
436
// --- thread stuff -----------------------------------------------

thomas's avatar
thomas committed
437
#ifdef FLEXT_THREADS
thomas's avatar
thomas committed
438
439
440
441

	/*! \brief Thread parameters
		\internal
	*/
thomas's avatar
thomas committed
442
443
	class thr_params:
		public flext 
thomas's avatar
thomas committed
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
	{
	public:
		thr_params(flext_base *c,int n = 1);
		~thr_params();

		void set_any(const t_symbol *s,int argc,const t_atom *argv);
		void set_list(int argc,const t_atom *argv);

		flext_base *cl;
		union _data {
			bool _bool;
			float _float;
			int _int;
			t_symptr _t_symptr;
			struct { AtomAnything *args; } _any;
			struct { AtomList *args; } _list;
			struct { void *data; } _ext;
		} *var;
	};

thomas's avatar
thomas committed
464
465
466
	/*! \brief This represents an entry to the list of active method threads
		\internal
	*/
thomas's avatar
thomas committed
467
468
469
470
471
	class thr_entry 
	{
	public:
		thr_entry(pthread_t id = pthread_self()): thrid(id),nxt(NULL) {}

thomas's avatar
thomas committed
472
		//! \brief Check if this class represents the current thread
thomas's avatar
thomas committed
473
474
475
476
477
478
		bool Is(pthread_t id = pthread_self()) const { return pthread_equal(thrid,id) != 0; }

		pthread_t thrid;
		thr_entry *nxt;
	};

thomas's avatar
thomas committed
479
480
481
	/*! \brief Start a method thread
		\internal
	*/
thomas's avatar
thomas committed
482
	static bool StartThread(void *(*meth)(thr_params *p),thr_params *p,char *methname);
thomas's avatar
thomas committed
483
484
485
486
487

	/*! \brief Add current thread to list of active threads
		\return true on success
		\internal
	*/
thomas's avatar
thomas committed
488
	bool PushThread();
thomas's avatar
thomas committed
489
490
491
492

	/*! \brief Remove current thread from list of active threads
		\internal
	*/
thomas's avatar
thomas committed
493
	void PopThread();
thomas's avatar
thomas committed
494
#endif
thomas's avatar
thomas committed
495

thomas's avatar
thomas committed
496
497
protected:

thomas's avatar
thomas committed
498
	flext_base();
thomas's avatar
thomas committed
499
	virtual ~flext_base();
thomas's avatar
thomas committed
500

thomas's avatar
thomas committed
501
502
// inlets and outlets
		
thomas's avatar
thomas committed
503
	/*! \brief Set up inlets and outlets
thomas's avatar
thomas committed
504
		\ingroup FLEXT_C_INOUT 
thomas's avatar
thomas committed
505
506
507
508
		\return True on successful creation of all inlets and outlets
	*/
	virtual bool Init();

thomas's avatar
thomas committed
509
	//! \brief This represents either an inlet or outlet
thomas's avatar
thomas committed
510
511
512
	struct xlet {	
		enum type {
			tp_none = 0,
thomas's avatar
thomas committed
513
			tp_float,tp_int,tp_sym,tp_list,tp_any,
thomas's avatar
thomas committed
514
515
			tp_LIST,tp_ANY, // use AtomList and AtomAnything
			tp_sig
thomas's avatar
thomas committed
516
517
		};

thomas's avatar
thomas committed
518
		xlet(type t,const char *desc = NULL);
thomas's avatar
thomas committed
519
520
		~xlet();
		
thomas's avatar
thomas committed
521
		char *desc;
thomas's avatar
thomas committed
522
523
524
		type tp;
		xlet *nxt;
	};
thomas's avatar
thomas committed
525

thomas's avatar
thomas committed
526
	/*!	\defgroup FLEXT_C_ATTR Attribute handling methods
thomas's avatar
thomas committed
527
528
529
		@{ 
	*/

thomas's avatar
thomas committed
530
531
	void AddAttrib(const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(attr,a_float,(methfun)get,(methfun)set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(attr,a_int,(methfun)get,(methfun)set); }
thomas's avatar
thomas committed
532
	void AddAttrib(const char *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
thomas's avatar
thomas committed
533
	void AddAttrib(const char *attr,bool (*get)(flext_base *,t_symbol *&),bool (*set)(flext_base *,t_symbol *&)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
thomas's avatar
thomas committed
534
	void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(attr,a_LIST,(methfun)get,(methfun)set); }
thomas's avatar
thomas committed
535
	void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(attr,a_ANY,(methfun)get,(methfun)set); }
thomas's avatar
thomas committed
536

thomas's avatar
thomas committed
537
//!		@} FLEXT_C_ATTR
thomas's avatar
thomas committed
538

thomas's avatar
thomas committed
539
540
541
542
	/*!	\addtogroup FLEXT_C_INOUT 
		@{ 
	*/

thomas's avatar
thomas committed
543
	//! \brief get a code for a list of inlets or outlets
thomas's avatar
thomas committed
544
545
	unsigned long XletCode(xlet::type tp = xlet::tp_none,...); // end list with 0 (= tp_none) !!

thomas's avatar
thomas committed
546
547
548
549
550
551
	/*! \brief Add some inlets by a special code representing the types
		\remark use XletCode function to get code value
	*/
	void AddInlets(unsigned long code); 

	//! \brief Add one or more inlet(s)
thomas's avatar
thomas committed
552
	void AddInlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,inlist); }
thomas's avatar
thomas committed
553
554
555
556
557
558
559

	/*! \brief Add some inlets by a special code representing the types
		\remark use XletCode function to get code value
	*/
	void AddOutlets(unsigned long code); 

	//! \brief Add one or more outlet(s)
thomas's avatar
thomas committed
560
561
	void AddOutlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,outlist); }

thomas's avatar
thomas committed
562
	//! \brief Set the description of an indexed inlet
thomas's avatar
thomas committed
563
	void DescInlet(int ix,const char *desc) { DescXlet(ix,desc,inlist); }
thomas's avatar
thomas committed
564
565

	//! \brief Set the description of an indexed outlet
thomas's avatar
thomas committed
566
567
	void DescOutlet(int ix,const char *desc) { DescXlet(ix,desc,outlist); }

thomas's avatar
thomas committed
568
//!		@} FLEXT_C_INOUT
thomas's avatar
thomas committed
569

thomas's avatar
thomas committed
570
571
// method handling

thomas's avatar
thomas committed
572
	//! \brief This represents an item of the method list
thomas's avatar
thomas committed
573
574
	class methitem { 
	public:
thomas's avatar
thomas committed
575
		methitem(int inlet,const t_symbol *t);
thomas's avatar
thomas committed
576
577
578
579
		~methitem();

		void SetArgs(methfun fun,int argc,metharg *args);

thomas's avatar
thomas committed
580
		const t_symbol *tag;
thomas's avatar
thomas committed
581
582
583
584
585
586
587
588
		int inlet;
		int argc;
		metharg *args;
		methfun fun;
		
		methitem *nxt;
	};
	
thomas's avatar
thomas committed
589
	//! \brief This represents an item of the attribute list
thomas's avatar
thomas committed
590
591
592
593
594
595
596
597
598
599
600
601
	class attritem { 
	public:
		attritem(const t_symbol *tag,const t_symbol *gtag,metharg tp,methfun gfun,methfun sfun);
		~attritem();

		const t_symbol *tag,*gtag;
		metharg argtp;
		methfun	gfun,sfun;

		attritem *nxt;
	};

thomas's avatar
thomas committed
602
603
//!		@} FLEXT_CLASS

thomas's avatar
thomas committed
604
605
606
607
608
private:

	static void Setup(t_class *c);

	xlet *inlist,*outlist;
thomas's avatar
thomas committed
609
	const t_symbol *curtag;
thomas's avatar
thomas committed
610
	int incnt,outcnt,insigs,outsigs;
thomas's avatar
thomas committed
611
	outlet **outlets,*outattr;
thomas's avatar
thomas committed
612
613
	bool distmsgs;

thomas's avatar
thomas committed
614
615
	void AddXlet(xlet::type tp,int mult,const char *desc,xlet *&root);	
	void DescXlet(int ix,const char *desc,xlet *&root);	
thomas's avatar
thomas committed
616

thomas's avatar
thomas committed
617
618
619
620
	union t_any {
		float ft;
		int it;
		t_symbol *st;
thomas's avatar
thomas committed
621
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
622
		t_gpointer *pt;
thomas's avatar
thomas committed
623
#endif
thomas's avatar
thomas committed
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
		void *vt;
	};

	typedef bool (*methfun_V)(flext_base *c,int argc,t_atom *argv);
	typedef bool (*methfun_A)(flext_base *c,const t_symbol *s,int argc,t_atom *argv);
	typedef bool (*methfun_0)(flext_base *c);
	typedef bool (*methfun_1)(flext_base *c,t_any &);
	typedef bool (*methfun_2)(flext_base *c,t_any &,t_any &);
	typedef bool (*methfun_3)(flext_base *c,t_any &,t_any &,t_any &);
	typedef bool (*methfun_4)(flext_base *c,t_any &,t_any &,t_any &,t_any &);
	typedef bool (*methfun_5)(flext_base *c,t_any &,t_any &,t_any &,t_any &,t_any &);
	
	methitem *methhead;
	void AddMethItem(methitem *m);

	attritem *attrhead;
	int attrcnt;
	void AddAttrItem(attritem *m);

	void AddAttrib(const char *attr,metharg tp,methfun gfun,methfun sfun);

thomas's avatar
thomas committed
645
	static int CheckAttrib(int argc,const t_atom *argv);
thomas's avatar
thomas committed
646
647
	bool InitAttrib(int argc,const t_atom *argv);

thomas's avatar
thomas committed
648
649
650
651
652
653
654
	bool ListAttrib();
	bool GetAttrib(const t_symbol *s,int argc,const t_atom *argv);
	bool SetAttrib(const t_symbol *s,int argc,const t_atom *argv);

	static bool cb_ListAttrib(flext_base *c) { return c->ListAttrib(); }
	static bool cb_GetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->GetAttrib(s,argc,argv); }
	static bool cb_SetAttrib(flext_base *c,const t_symbol *s,int argc,const t_atom *argv) { return c->SetAttrib(s,argc,argv); }
thomas's avatar
thomas committed
655

thomas's avatar
thomas committed
656
657
658
#ifdef FLEXT_THREADS
	bool shouldexit;
	int thrcount;
thomas's avatar
thomas committed
659
660
	
	pthread_t thrid;  // the thread that created the object (the system thread)
thomas's avatar
thomas committed
661
662
663
664
665
	ThrMutex qmutex;

	thr_entry *thrhead,*thrtail;
	ThrMutex tlmutex;
#endif
thomas's avatar
thomas committed
666
667
668

	class qmsg;
	qmsg *qhead,*qtail;
thomas's avatar
thomas committed
669
	t_qelem *qclk;
thomas's avatar
thomas committed
670
#if FLEXT_SYS == FLEXT_SYS_MAX
thomas's avatar
thomas committed
671
	t_clock *yclk;
thomas's avatar
thomas committed
672
	static void YTick(flext_base *th);
thomas's avatar
thomas committed
673
#endif
thomas's avatar
thomas committed
674
675
676

	static void QTick(flext_base *th);
	void Queue(qmsg *m);
thomas's avatar
thomas committed
677

thomas's avatar
thomas committed
678
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
679
680
681
	// proxy object (for additional inlets) stuff
	struct px_object;
	friend struct px_object;
thomas's avatar
thomas committed
682
#elif FLEXT_SYS == FLEXT_SYS_MAX
thomas's avatar
thomas committed
683
684
	typedef object px_object;
	static void cb_px_float(t_class *c,float f);
thomas's avatar
thomas committed
685
	static void cb_px_int(t_class *c,int v);
thomas's avatar
thomas committed
686
687
688
689
690
691
692
693
694
695
696
	static void cb_px_bang(t_class *c);

	static void cb_px_in1(t_class *c,int v);
	static void cb_px_in2(t_class *c,int v);
	static void cb_px_in3(t_class *c,int v);
	static void cb_px_in4(t_class *c,int v);
	static void cb_px_in5(t_class *c,int v);
	static void cb_px_in6(t_class *c,int v);
	static void cb_px_in7(t_class *c,int v);
	static void cb_px_in8(t_class *c,int v);
	static void cb_px_in9(t_class *c,int v);
thomas's avatar
thomas committed
697
698
#else
#error
thomas's avatar
thomas committed
699
#endif
thomas's avatar
thomas committed
700
	static void cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv);
thomas's avatar
thomas committed
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

	static void cb_px_ft1(t_class *c,float f);
	static void cb_px_ft2(t_class *c,float f);
	static void cb_px_ft3(t_class *c,float f);
	static void cb_px_ft4(t_class *c,float f);
	static void cb_px_ft5(t_class *c,float f);
	static void cb_px_ft6(t_class *c,float f);
	static void cb_px_ft7(t_class *c,float f);
	static void cb_px_ft8(t_class *c,float f);
	static void cb_px_ft9(t_class *c,float f);

	px_object **inlets;

	// callback functions

	static void cb_help(t_class *c);

	static void cb_loadbang(t_class *c);
thomas's avatar
thomas committed
719
#if FLEXT_SYS == FLEXT_SYS_MAX
thomas's avatar
thomas committed
720
721
722
723
724
	static void cb_assist(t_class *c,void *b,long msg,long arg,char *s);
#endif
};

#endif