flclass.h 15.8 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
48
49
	public flext_obj
{
	FLEXT_HEADER_S(flext_base,flext_obj,Setup)
	
public:

thomas's avatar
thomas committed
50
51
52
53
54
	/*!	\defgroup FLEXT_C_BASE Flext basic class functionality

		@{ 
	*/

thomas's avatar
thomas committed
55
56
57
58
59
60
61
62
// ---  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
63
64
//!		@} 

thomas's avatar
thomas committed
65
66
67

// --- inheritable virtual methods --------------------------------

thomas's avatar
thomas committed
68
69
70
71
72
	/*!	\defgroup FLEXT_C_VIRTUAL Flext virtual base class functions

		@{ 
	*/

thomas's avatar
thomas committed
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	//! 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() {}

	//! quickhelp for inlets/outlets (gets calles in MaxMSP only)
	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
	*/
	virtual bool m_methodmain(int inlet,const t_symbol *s,int argc,t_atom *argv);

	//! called for every unhandled message (by m_methodmain)
thomas's avatar
thomas committed
89
	virtual bool m_method_(int inlet,const t_symbol *s,int argc,t_atom *argv);
thomas's avatar
thomas committed
90

thomas's avatar
thomas committed
91
//!		@} 
thomas's avatar
thomas committed
92

thomas's avatar
thomas committed
93

thomas's avatar
thomas committed
94
95
// --- inlet/outlet stuff -----------------------------------------	

thomas's avatar
thomas committed
96
97
98
99
100
101
102
	/*!	\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
103
104
105
106
	// argument m specifies multiple inlet/outlet count
	
//	void AddInDef() { AddInlet(xlet::tp_def,1); }

thomas's avatar
thomas committed
107
108
109
	/*! \brief Add inlet(s) for anythings
		That's the one to choose for the left-most (first) inlet unless it's a signal inlet.
	*/
thomas's avatar
thomas committed
110
	void AddInAnything(int m = 1) { AddInlet(xlet::tp_any,m); } // leftmost or via proxy
thomas's avatar
thomas committed
111
	void AddInAnything(const char *desc,int m = 1) { AddInlet(xlet::tp_any,m,desc); } // leftmost or via proxy
thomas's avatar
thomas committed
112
	//! Add inlet(s) for floats
thomas's avatar
thomas committed
113
	void AddInFloat(int m = 1) { AddInlet(xlet::tp_float,m); }
thomas's avatar
thomas committed
114
	void AddInFloat(const char *desc,int m = 1) { AddInlet(xlet::tp_float,m,desc); }
thomas's avatar
thomas committed
115
	//! Add inlet(s) for ints
thomas's avatar
thomas committed
116
	void AddInInt(int m = 1) { AddInlet(xlet::tp_int,m); }
thomas's avatar
thomas committed
117
	void AddInInt(const char *desc,int m = 1) { AddInlet(xlet::tp_int,m,desc); }
thomas's avatar
thomas committed
118
	//! Add inlet(s) for symbols
thomas's avatar
thomas committed
119
	void AddInSymbol(int m = 1) { AddInlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
120
	void AddInSymbol(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
121
	//! Add inlet(s) for bang
thomas's avatar
thomas committed
122
	void AddInBang(int m = 1) { AddInlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
123
	void AddInBang(const char *desc,int m = 1) { AddInlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
124
	//! Add inlet(s) for lists
thomas's avatar
thomas committed
125
	void AddInList(int m = 1) { AddInlet(xlet::tp_list,m); }  // via proxy
thomas's avatar
thomas committed
126
	void AddInList(const char *desc,int m = 1) { AddInlet(xlet::tp_list,m,desc); }  // via proxy
thomas's avatar
thomas committed
127
	
thomas's avatar
thomas committed
128
	//! Add outlet(s) for anythings
thomas's avatar
thomas committed
129
	void AddOutAnything(int m = 1) { AddOutlet(xlet::tp_any,m); }
thomas's avatar
thomas committed
130
	void AddOutAnything(const char *desc,int m = 1) { AddOutlet(xlet::tp_any,m,desc); }
thomas's avatar
thomas committed
131
	//! Add outlet(s) for floats
thomas's avatar
thomas committed
132
	void AddOutFloat(int m = 1) { AddOutlet(xlet::tp_float,m); }
thomas's avatar
thomas committed
133
	void AddOutFloat(const char *desc,int m = 1) { AddOutlet(xlet::tp_float,m,desc); }
thomas's avatar
thomas committed
134
	//! Add outlet(s) for ints
thomas's avatar
thomas committed
135
	void AddOutInt(int m = 1) { AddOutlet(xlet::tp_int,m); }
thomas's avatar
thomas committed
136
	void AddOutInt(const char *desc,int m = 1) { AddOutlet(xlet::tp_int,m,desc); }
thomas's avatar
thomas committed
137
	//! Add outlet(s) for symbols
thomas's avatar
thomas committed
138
	void AddOutSymbol(int m = 1) { AddOutlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
139
	void AddOutSymbol(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
140
	//! Add outlet(s) for bangs
thomas's avatar
thomas committed
141
	void AddOutBang(int m = 1) { AddOutlet(xlet::tp_sym,m); }
thomas's avatar
thomas committed
142
	void AddOutBang(const char *desc,int m = 1) { AddOutlet(xlet::tp_sym,m,desc); }
thomas's avatar
thomas committed
143
	//! Add outlet(s) for lists
thomas's avatar
thomas committed
144
	void AddOutList(int m = 1) { AddOutlet(xlet::tp_list,m); }
thomas's avatar
thomas committed
145
	void AddOutList(const char *desc,int m = 1) { AddOutlet(xlet::tp_list,m,desc); }
thomas's avatar
thomas committed
146
	
thomas's avatar
thomas committed
147
	/*! \brief Set up inlets and outlets
thomas's avatar
thomas committed
148
149
150
151
152
		\remark Must be called ONCE to actually set up the defined inlets/outlets.
		\return True on successful creation of all inlets and outlets
	*/
	bool SetupInOut(); 

thomas's avatar
thomas committed
153
	//! Get number of inlets
thomas's avatar
thomas committed
154
	int CntIn() const { return incnt; }
thomas's avatar
thomas committed
155
	//! Get number of outlets
thomas's avatar
thomas committed
156
	int CntOut() const { return outcnt; }
thomas's avatar
thomas committed
157
	//! Get number of signal inlets
thomas's avatar
thomas committed
158
	int CntInSig() const { return insigs; }
thomas's avatar
thomas committed
159
	//! Get number of signal outlets
thomas's avatar
thomas committed
160
161
162
163
	int CntOutSig() const { return outsigs; }


	class outlet;
thomas's avatar
thomas committed
164
165
//	class AtomList;
//	class AtomAnything;
thomas's avatar
thomas committed
166

thomas's avatar
thomas committed
167
	//! Get pointer to outlet (_after_ calling setup_inout()!)
thomas's avatar
thomas committed
168
169
	outlet *GetOut(int ix) { return (outlets && ix < outcnt)?outlets[ix]:NULL; }

thomas's avatar
thomas committed
170
	// output messages 
thomas's avatar
thomas committed
171
172

	void ToOutBang(outlet *o); 
thomas's avatar
thomas committed
173
	//! Output bang (index n starts with 0)
thomas's avatar
thomas committed
174
175
176
	void ToOutBang(int n) { outlet *o = GetOut(n); if(o) ToOutBang(o); }

	void ToOutFloat(outlet *o,float f); 
thomas's avatar
thomas committed
177
	//! Output float (index n starts with 0)
thomas's avatar
thomas committed
178
179
	void ToOutFloat(int n,float f) { outlet *o = GetOut(n); if(o) ToOutFloat(o,f); }

thomas's avatar
thomas committed
180
	void ToOutInt(outlet *o,int f); 
thomas's avatar
thomas committed
181
	//! Output int (index n starts with 0)
thomas's avatar
thomas committed
182
	void ToOutInt(int n,int f) { outlet *o = GetOut(n); if(o) ToOutInt(o,f); }
thomas's avatar
thomas committed
183
184
	
	void ToOutSymbol(outlet *o,const t_symbol *s); 
thomas's avatar
thomas committed
185
	//! Output symbol (index n starts with 0)
thomas's avatar
thomas committed
186
187
188
	void ToOutSymbol(int n,const t_symbol *s) { outlet *o = GetOut(n); if(o) ToOutSymbol(o,s); }

	void ToOutString(outlet *o,const char *s) { ToOutSymbol(o,gensym(const_cast<char *>(s))); }
thomas's avatar
thomas committed
189
	//! Output string (index n starts with 0)
thomas's avatar
thomas committed
190
	void ToOutString(int n,const char *s) { outlet *o = GetOut(n); if(o) ToOutString(o,s); }
thomas's avatar
thomas committed
191

thomas's avatar
thomas committed
192
	void ToOutList(outlet *o,int argc,const t_atom *argv); 
thomas's avatar
thomas committed
193
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
194
195
196
	void ToOutList(int n,int argc,const t_atom *argv)  { outlet *o = GetOut(n); if(o) ToOutList(o,argc,argv); }
	//! Output list (index n starts with 0)
	void ToOutList(int n,const AtomList &list)  { ToOutList(n,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
197
	
thomas's avatar
thomas committed
198
199
200
	void ToOutAnything(outlet *o,const t_symbol *s,int argc,const t_atom *argv); 
	//! Output anything (index n starts with 0)
	void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv)  { outlet *o = GetOut(n); if(o) ToOutAnything(o,const_cast<t_symbol *>(s),argc,argv); }
thomas's avatar
thomas committed
201
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
202
	void ToOutAnything(int n,const AtomAnything &any)  { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
203
204
205
	
//!		@} 

thomas's avatar
thomas committed
206

thomas's avatar
thomas committed
207
208
209
210
211
212
213
214
215
// --- message handling -------------------------------------------

	enum metharg {
		a_null = 0,
		a_float,a_int, 
		a_symbol,a_pointer,
		a_gimme,a_xgimme
	};

thomas's avatar
thomas committed
216
	typedef bool (*methfun)(t_class *c);
thomas's avatar
thomas committed
217

thomas's avatar
thomas committed
218
219
220
221
222
223
	/*!	\defgroup FLEXT_C_ADDMETHOD Flext method handling
		\internal

		@{ 
	*/

thomas's avatar
thomas committed
224
225
226
227
	void AddMethodDef(int inlet); // call virtual function for inlet
	void AddMethodDef(int inlet,const char *tag); // call virtual function for tag && inlet
	void AddMethod(int inlet,const char *tag,methfun fun,metharg tp,...); 

thomas's avatar
thomas committed
228
229
230
231
232
233
234
	void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,"list",(methfun)m,a_gimme,a_null); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,tag,(methfun)m,a_null); }  // pure method
	void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,t_atom *)) { AddMethod(inlet,"anything",(methfun)m,a_xgimme,a_null); } // anything
	void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,"symbol",(methfun)m,a_symbol,a_null); } // single symbol
	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
235
#ifdef PD
thomas's avatar
thomas committed
236
	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
237
#else
thomas's avatar
thomas committed
238
	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
239
#endif
thomas's avatar
thomas committed
240
241
242
243
244
245
246
	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
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_gimme,a_null); } // method+gimme
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,t_atom *)) { AddMethod(inlet,tag,(methfun)m,a_xgimme,a_null); } // method+gimme 
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
	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
247
248
249
250

	//! Set MaxMSP style of distributing list elements over (message) inlets
	void SetDist(bool d = true) { distmsgs = d; }

thomas's avatar
thomas committed
251
252
//!		@} 

thomas's avatar
thomas committed
253
// --- bind/unbind ---------------------------------------
thomas's avatar
thomas committed
254
255

#ifdef PD
thomas's avatar
thomas committed
256
257
258
259
	//! 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
260
#else
thomas's avatar
thomas committed
261
262
263
264
	//! 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
265
#endif
thomas's avatar
thomas committed
266
267
268
269
	//! 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
270

thomas's avatar
thomas committed
271
/*
thomas's avatar
thomas committed
272
273
	// Low level

thomas's avatar
thomas committed
274
275
276
277
278
279
	//! 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
280
*/
thomas's avatar
thomas committed
281

thomas's avatar
thomas committed
282
// --- thread stuff -----------------------------------------------
thomas's avatar
thomas committed
283

thomas's avatar
thomas committed
284
#ifdef FLEXT_THREADS
thomas's avatar
thomas committed
285
286
287
288
289
290
291
292
	/*!	\defgroup FLEXT_C_THREAD Flext thread handling 

		@{ 
	*/

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

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

thomas's avatar
thomas committed
298
299
300
	/*! \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
301
	static void ThrYield() { sched_yield(); }
thomas's avatar
thomas committed
302

thomas's avatar
thomas committed
303
304
305
306
307
308
309
	typedef pthread_t thrid_t;

	/*! \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
310
	*/
thomas's avatar
thomas committed
311
312
313
314
315
	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
316

thomas's avatar
thomas committed
317
318
	/*! \brief Get current thread id
	*/
thomas's avatar
thomas committed
319
320
	static thrid_t GetThreadId();

thomas's avatar
thomas committed
321

thomas's avatar
thomas committed
322
323
#endif // FLEXT_THREADS

thomas's avatar
thomas committed
324
325
//!		@} 

thomas's avatar
thomas committed
326
327


thomas's avatar
thomas committed
328

thomas's avatar
thomas committed
329
330
// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

thomas's avatar
thomas committed
331
332
// --- thread stuff -----------------------------------------------

thomas's avatar
thomas committed
333
#ifdef FLEXT_THREADS
thomas's avatar
thomas committed
334
335
	class thr_params;
	static bool StartThread(void *(*)(thr_params *p),thr_params *p,char *methname);
thomas's avatar
thomas committed
336
	bool PushThread();
thomas's avatar
thomas committed
337
	void PopThread();
thomas's avatar
thomas committed
338
#endif
thomas's avatar
thomas committed
339

thomas's avatar
thomas committed
340
341
protected:

thomas's avatar
thomas committed
342
343
	flext_base();
	virtual ~flext_base();
thomas's avatar
thomas committed
344

thomas's avatar
thomas committed
345
346
347
348
349
// inlets and outlets
		
	struct xlet {	
		enum type {
			tp_none = 0,
thomas's avatar
thomas committed
350
			tp_float,tp_int,tp_sym,tp_list,tp_sig,tp_any
thomas's avatar
thomas committed
351
352
		};

thomas's avatar
thomas committed
353
		xlet(type t,const char *desc = NULL);
thomas's avatar
thomas committed
354
355
		~xlet();
		
thomas's avatar
thomas committed
356
		char *desc;
thomas's avatar
thomas committed
357
358
359
		type tp;
		xlet *nxt;
	};
thomas's avatar
thomas committed
360

thomas's avatar
thomas committed
361
362
363
364
365
	/*!	\addtogroup FLEXT_C_INOUT 

		@{ 
	*/

thomas's avatar
thomas committed
366
367
368
	unsigned long XletCode(xlet::type tp = xlet::tp_none,...); // end list with 0 (= tp_none) !!

	void AddInlets(unsigned long code); // use XletCode to get code value
thomas's avatar
thomas committed
369
	void AddInlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,inlist); }
thomas's avatar
thomas committed
370
	void AddOutlets(unsigned long code); // use XletCode to get code value
thomas's avatar
thomas committed
371
372
373
374
375
	void AddOutlet(xlet::type tp,int mult = 1,const char *desc = NULL) { AddXlet(tp,mult,desc,outlist); }

	void DescInlet(int ix,const char *desc) { DescXlet(ix,desc,inlist); }
	void DescOutlet(int ix,const char *desc) { DescXlet(ix,desc,outlist); }

thomas's avatar
thomas committed
376
377
//!		@} 

thomas's avatar
thomas committed
378

thomas's avatar
thomas committed
379
380
381
382
383
384
385
386
387
#ifdef FLEXT_THREADS
	void QueueBang(outlet *o); 
	void QueueFloat(outlet *o,float f); 
	void QueueInt(outlet *o,int f); 
	void QueueSymbol(outlet *o,const t_symbol *s); 
	void QueueList(outlet *o,int argc,t_atom *argv); 
	void QueueAnything(outlet *o,const t_symbol *s,int argc,t_atom *argv); 
#endif

thomas's avatar
thomas committed
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
// method handling

	class methitem { 
	public:
		methitem(int inlet,t_symbol *t);
		~methitem();

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

		t_symbol *tag;
		int inlet;
		int argc;
		metharg *args;
		methfun fun;
		
		methitem *nxt;
	};
	
	void AddMethItem(methitem *m);
	
private:

	static void Setup(t_class *c);

	xlet *inlist,*outlist;
	int incnt,outcnt,insigs,outsigs;
	outlet **outlets;
	bool distmsgs;

thomas's avatar
thomas committed
417
418
	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
419
420
421

	methitem *mlst;

thomas's avatar
thomas committed
422
423
424
#ifdef FLEXT_THREADS
	bool shouldexit;
	int thrcount;
thomas's avatar
thomas committed
425
426
	
	pthread_t thrid;  // the thread that created the object (the system thread)
thomas's avatar
thomas committed
427
428
429

	class qmsg;
	qmsg *qhead,*qtail;
thomas's avatar
thomas committed
430
	t_qelem *qclk;
thomas's avatar
thomas committed
431
	ThrMutex qmutex;
thomas's avatar
thomas committed
432
433
#ifdef MAXMSP
	t_clock *yclk;
thomas's avatar
thomas committed
434
	static void YTick(flext_base *th);
thomas's avatar
thomas committed
435
#endif
thomas's avatar
thomas committed
436
437
438

	static void QTick(flext_base *th);
	void Queue(qmsg *m);
thomas's avatar
thomas committed
439
440
441
442

	class thr_entry;
	thr_entry *thrhead,*thrtail;
	ThrMutex tlmutex;
thomas's avatar
thomas committed
443
444
#endif

thomas's avatar
thomas committed
445
446
447
448
449
450
451
#ifdef PD
	// proxy object (for additional inlets) stuff
	struct px_object;
	friend struct px_object;
#elif defined(MAXMSP)
	typedef object px_object;
	static void cb_px_float(t_class *c,float f);
thomas's avatar
thomas committed
452
	static void cb_px_int(t_class *c,int v);
thomas's avatar
thomas committed
453
454
455
456
457
458
459
460
461
462
463
464
	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);
#endif
thomas's avatar
thomas committed
465
	static void cb_px_anything(t_class *c,const t_symbol *s,int argc,t_atom *argv);
thomas's avatar
thomas committed
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

	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);
#ifdef MAXMSP
	static void cb_assist(t_class *c,void *b,long msg,long arg,char *s);
#endif
};

#endif