flclass.h 49.1 KB
Newer Older
Thomas Grill's avatar
Thomas Grill committed
1 2
/*
flext - C++ layer for Max and Pure Data externals
thomas's avatar
thomas committed
3

4
Copyright (c) 2001-2017 Thomas Grill (gr@grrrr.org)
thomas's avatar
thomas committed
5
For information on usage and redistribution, and for a DISCLAIMER OF ALL
Thomas Grill's avatar
Thomas Grill committed
6
WARRANTIES, see the file, "license.txt," in this distribution.
thomas's avatar
thomas committed
7 8 9
*/

/*! \file flclass.h
thomas's avatar
thomas committed
10
	\brief User accessible flext base classes
thomas's avatar
thomas committed
11 12 13 14 15 16
    
*/

#ifndef __FLCLASS_H
#define __FLCLASS_H

thomas's avatar
thomas committed
17
// include the header file declaring the base classes
thomas's avatar
thomas committed
18
#include "flbase.h"
thomas's avatar
thomas committed
19
#include "flsupport.h"
thomas's avatar
thomas committed
20
#include "flmap.h"
thomas's avatar
thomas committed
21
#include "flinternal.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

34 35
#include "flpushns.h"

thomas's avatar
thomas committed
36 37
// === flext_base ==================================================

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

40
    This is the base class from which typical external objects derive.
thomas's avatar
thomas committed
41
    DSP objects should use the flext_dsp class which inherits from flext_base and
42
    provides the necessary functionality.
thomas's avatar
thomas committed
43 44 45 46 47 48 49

    For a valid external object class you would also need FLEXT_HEADER, also if it's only
    a base class without instantiated objects again.
    To make an instance of an object class you would typically use FLEXT_NEW or 
    its companions.

    See the flext_obj class for additional information.
thomas's avatar
thomas committed
50 51
*/

thomas's avatar
thomas committed
52

53
FLEXT_TEMPLATE class FLEXT_SHARE FLEXT_CLASSDEF(flext_base);
54

55 56 57
typedef class FLEXT_SHARE FLEXT_TEMPINST(FLEXT_CLASSDEF(flext_base)) flext_base;

FLEXT_TEMPLATE
58
class FLEXT_SHARE FLEXT_CLASSDEF(flext_base): 
thomas's avatar
thomas committed
59 60
	public flext_obj
{
61
	FLEXT_HEADER_S(FLEXT_CLASSDEF(flext_base),flext_obj,Setup)
thomas's avatar
thomas committed
62
	
63
	friend class FLEXT_SHARE FLEXT_CLASSDEF(flext_obj);
thomas's avatar
thomas committed
64

thomas's avatar
thomas committed
65 66 67 68
public:

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

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

		@{ 
	*/

thomas's avatar
thomas committed
74
	//! called on patcher load (not on mere object creation!)
75
	virtual void CbLoadbang();
thomas's avatar
thomas committed
76
	virtual void m_loadbang();
thomas's avatar
thomas committed
77

78
	//! called on (double-)click into object box
79
	virtual void CbClick();
thomas's avatar
thomas committed
80 81 82 83 84

	/*!	\brief Called for every incoming message.
		All method handling is done in there
		\return True if a handler was found and called
	*/
85
	virtual bool CbMethodHandler(int inlet,const t_symbol *s,int argc,const t_atom *argv);
thomas's avatar
thomas committed
86

87
	/*! \brief Called for every unhandled message (by CbMethodHandler)
thomas's avatar
thomas committed
88
	*/
89
	virtual bool CbMethodResort(int inlet,const t_symbol *s,int argc,const t_atom *argv);
thomas's avatar
thomas committed
90
	virtual bool m_method_(int inlet,const t_symbol *s,int argc,const t_atom *argv);
thomas's avatar
thomas committed
91

92 93
	virtual bool CbIdle();

thomas's avatar
thomas committed
94
//!		@} FLEXT_C_VIRTUAL
thomas's avatar
thomas committed
95

thomas's avatar
thomas committed
96

thomas's avatar
thomas committed
97 98
// --- inlet/outlet stuff -----------------------------------------	

thomas's avatar
thomas committed
99 100 101
	/*!	\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
102 103
		@{ 
	*/
thomas's avatar
thomas committed
104

thomas's avatar
thomas committed
105
	/*!	\defgroup FLEXT_C_IO_ADD Announce in-/outlet functions
thomas's avatar
thomas committed
106 107 108
		@{ 
	*/

thomas's avatar
thomas committed
109 110
	// argument m specifies multiple inlet/outlet count
	
thomas's avatar
thomas committed
111
//	void AddInDef() { AddInlet(xlet_def,1); }
thomas's avatar
thomas committed
112

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

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

thomas's avatar
thomas committed
170 171 172 173 174 175
	//!	@} FLEXT_C_IO_ADD 

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

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

thomas's avatar
thomas committed
185

thomas's avatar
thomas committed
186
	//! Retrieve currently processed message tag (NULL if no message processing)
thomas's avatar
thomas committed
187
	static const t_symbol *thisTag() { return curtag; }
thomas's avatar
thomas committed
188

thomas's avatar
thomas committed
189 190
	class outlet;

thomas's avatar
thomas committed
191
	//! Get pointer to outlet (not in the constructor!)
thomas's avatar
thomas committed
192
	outlet *GetOut(int ix) const { return outlets[ix]; }
193

thomas's avatar
thomas committed
194
	int GetOutAttr() const { return HasAttributes()?CntOut():0; }
thomas's avatar
thomas committed
195

thomas's avatar
thomas committed
196 197 198 199 200 201
	//! @} FLEXT_C_IO_MISC

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

thomas's avatar
thomas committed
202
	// output messages 
thomas's avatar
thomas committed
203

thomas's avatar
thomas committed
204
	//! Output bang (index n starts with 0)
thomas's avatar
thomas committed
205
	void ToOutBang(int n) const;
thomas's avatar
thomas committed
206

thomas's avatar
thomas committed
207
	//! Output float (index n starts with 0)
thomas's avatar
thomas committed
208
	void ToOutFloat(int n,float f) const;
thomas's avatar
thomas committed
209

thomas's avatar
thomas committed
210
	//! Output integer (index n starts with 0)
thomas's avatar
thomas committed
211
	void ToOutInt(int n,int f) const;
thomas's avatar
thomas committed
212
	
thomas's avatar
thomas committed
213 214
	//! Output boolean (index n starts with 0)
    void ToOutBool(int n,bool f) const { ToOutInt(n,f?1:0); }
215 216 217 218

	//! Output double (index n starts with 0)
	void ToOutDouble(int n,double d) const { t_atom dbl[2]; ToOutList(n,2,SetDouble(dbl,d)); }

thomas's avatar
thomas committed
219
	//! Output symbol (index n starts with 0)
thomas's avatar
thomas committed
220
	void ToOutSymbol(int n,const t_symbol *s) const;
thomas's avatar
thomas committed
221
	//! Output string aka symbol (index n starts with 0)
thomas's avatar
thomas committed
222
	void ToOutString(int n,const char *s) const { ToOutSymbol(n,MakeSymbol(s)); }
thomas's avatar
thomas committed
223

thomas's avatar
thomas committed
224 225 226
	//! Output atom (index n starts with 0)
	void ToOutAtom(int n,const t_atom &at) const; 

thomas's avatar
thomas committed
227
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
228
	void ToOutList(int n,int argc,const t_atom *argv) const;
thomas's avatar
thomas committed
229
	//! Output list (index n starts with 0)
thomas's avatar
thomas committed
230
	void ToOutList(int n,const AtomList &list) const { ToOutList(n,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
231
	
thomas's avatar
thomas committed
232
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
233
	void ToOutAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const;
thomas's avatar
thomas committed
234
	//! Output anything (index n starts with 0)
thomas's avatar
thomas committed
235
	void ToOutAnything(int n,const AtomAnything &any) const { ToOutAnything(n,any.Header(),any.Count(),any.Atoms()); }
236 237
	//! Output anything (index n starts with 0)
	void ToOutAnything(int n,const t_symbol *s,const AtomList &list) const { ToOutAnything(n,s,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
238
	
thomas's avatar
thomas committed
239 240 241 242 243 244
	//! @} FLEXT_C_IO_OUT

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

245
	//! Output low priority bang (index n starts with 0)
thomas's avatar
thomas committed
246
	void ToQueueBang(int n) const;
thomas's avatar
thomas committed
247

248
	//! Output low priority float (index n starts with 0)
thomas's avatar
thomas committed
249
	void ToQueueFloat(int n,float f) const;
thomas's avatar
thomas committed
250

251
	//! Output low priority integer (index n starts with 0)
thomas's avatar
thomas committed
252
	void ToQueueInt(int n,int f) const;
thomas's avatar
thomas committed
253

254
	//! Output low priority boolean (index n starts with 0)
thomas's avatar
thomas committed
255 256
	void ToQueueBool(int n,bool f) const { ToQueueInt(n,f?1:0); }

257 258 259
	//! Output double (index n starts with 0)
	void ToQueueDouble(int n,double d) const { t_atom dbl[2]; ToQueueList(n,2,SetDouble(dbl,d)); }

260
	//! Output low priority symbol (index n starts with 0)
thomas's avatar
thomas committed
261
	void ToQueueSymbol(int n,const t_symbol *s) const;
262
	//! Output low priority string aka symbol (to appointed outlet)
thomas's avatar
thomas committed
263
	void ToQueueString(int n,const char *s) const { ToQueueSymbol(n,MakeSymbol(s)); }
thomas's avatar
thomas committed
264

265
	//! Output low priority atom (index n starts with 0)
thomas's avatar
thomas committed
266 267
	void ToQueueAtom(int n,const t_atom &at) const; 

268
	//! Output low priority list (index n starts with 0)
thomas's avatar
thomas committed
269
	void ToQueueList(int n,int argc,const t_atom *argv) const; 
270
	//! Output low priority list (index n starts with 0)
thomas's avatar
thomas committed
271
	void ToQueueList(int n,const AtomList &list) const  { ToQueueList(n,list.Count(),list.Atoms()); }
thomas's avatar
thomas committed
272

273
	//! Output low priority anything (index n starts with 0)
thomas's avatar
thomas committed
274
	void ToQueueAnything(int n,const t_symbol *s,int argc,const t_atom *argv)  const;
275
	//! Output low priority anything (index n starts with 0)
thomas's avatar
thomas committed
276
	void ToQueueAnything(int n,const AtomAnything &any) const  { ToQueueAnything(n,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
277

278 279
    //!	@} FLEXT_C_IO_QUEUE

thomas's avatar
thomas committed
280

281 282 283 284 285
	/*!	\defgroup FLEXT_C_IO_SELF Output of data to inlets/outlets of this object
		@{ 
	*/

    //! Send bang to self (inlet n)
286
    void ToSelfBang(int n) const { ToQueueBang(-1-n); }
thomas's avatar
thomas committed
287 288

	//! Send float to self (inlet n)
289
    void ToSelfFloat(int n,float f) const { ToQueueFloat(-1-n,f); }
thomas's avatar
thomas committed
290 291

	//! Send integer to self (inlet n)
292
    void ToSelfInt(int n,int f) const { ToQueueInt(-1-n,f); }
thomas's avatar
thomas committed
293

thomas's avatar
thomas committed
294 295 296
	//! Send boolean to self (inlet n)
	void ToSelfBool(int n,bool f) const { ToSelfInt(n,f?1:0); }

297 298 299
	//! Send double to self (index n starts with 0)
	void ToSelfDouble(int n,double d) const { t_atom dbl[2]; ToSelfList(n,2,SetDouble(dbl,d)); }

thomas's avatar
thomas committed
300
	//! Send symbol to self (inlet n)
301
    void ToSelfSymbol(int n,const t_symbol *s) const { ToQueueSymbol(-1-n,s); }
thomas's avatar
thomas committed
302 303 304
	//! Send string aka symbol to self (inlet 0)
	void ToSelfString(int n,const char *s) const { ToSelfSymbol(n,MakeSymbol(s)); }

thomas's avatar
thomas committed
305 306 307
	//! Output atom (index n starts with 0)
    void ToSelfAtom(int n,const t_atom &at) const { ToQueueAtom(-1-n,at); }

thomas's avatar
thomas committed
308
	//! Send list to self (inlet n)
309
    void ToSelfList(int n,int argc,const t_atom *argv) const { ToQueueList(-1-n,argc,argv); }
thomas's avatar
thomas committed
310 311 312 313
	//! Send list to self (inlet n)
	void ToSelfList(int n,const AtomList &list) const  { ToSelfList(n,list.Count(),list.Atoms()); }

	//! Send anything to self (inlet n)
314
    void ToSelfAnything(int n,const t_symbol *s,int argc,const t_atom *argv) const { ToQueueAnything(-1-n,s,argc,argv); }
thomas's avatar
thomas committed
315 316
	//! Send anything to self (inlet n)
	void ToSelfAnything(int n,const AtomAnything &any) const { ToSelfAnything(n,any.Header(),any.Count(),any.Atoms()); }
thomas's avatar
thomas committed
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
    //!	@} FLEXT_C_IO_SELF


	/*!	\defgroup FLEXT_C_IO_MESSAGEBUNDLE Output of data via message bundles

        These are used to assure the sending of several messages from a second thread to the same logical time

		@{ 
	*/

	//! Output bang (index n starts with 0)
	void MsgAddBang(MsgBundle *mb,int n) const;

	//! Output float (index n starts with 0)
	void MsgAddFloat(MsgBundle *mb,int n,float f) const;

	//! Output integer (index n starts with 0)
	void MsgAddInt(MsgBundle *mb,int n,int f) const;

	//! Output boolean (index n starts with 0)
	void MsgAddBool(MsgBundle *mb,int n,bool f) const { MsgAddInt(mb,n,f?1:0); }

340 341 342
	//! Output double (index n starts with 0)
	void MsgAddDouble(MsgBundle *mb,int n,double d) const { t_atom dbl[2]; MsgAddList(mb,n,2,SetDouble(dbl,d)); }

343 344 345 346 347 348 349 350 351
	//! Output symbol (index n starts with 0)
	void MsgAddSymbol(MsgBundle *mb,int n,const t_symbol *s) const;
	//! Output string aka symbol (to appointed outlet)
	void MsgAddString(MsgBundle *mb,int n,const char *s) const { MsgAddSymbol(mb,n,MakeSymbol(s)); }

	//! Output atom (index n starts with 0)
	void MsgAddAtom(MsgBundle *mb,int n,const t_atom &at) const;

	//! Output list (index n starts with 0)
352 353
	void MsgAddList(MsgBundle *mb,int n,int argc,const t_atom *argv) const;

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	//! Output list (index n starts with 0)
	void MsgAddList(MsgBundle *mb,int n,const AtomList &list) const { MsgAddList(mb,n,list.Count(),list.Atoms()); }

	//! Output anything (index n starts with 0)
	void MsgAddAnything(MsgBundle *mb,int n,const t_symbol *s,int argc,const t_atom *argv) const;
	//! Output anything (index n starts with 0)
	void MsgAddAnything(MsgBundle *mb,int n,const AtomAnything &any) const { MsgAddAnything(mb,n,any.Header(),any.Count(),any.Atoms()); }

    void MsgSelfBang(MsgBundle *mb,int n) const { MsgAddBang(mb,-1-n); }

	//! Send float to self (inlet n)
    void MsgSelfFloat(MsgBundle *mb,int n,float f) const { MsgAddFloat(mb,-1-n,f); }

	//! Send integer to self (inlet n)
    void MsgSelfInt(MsgBundle *mb,int n,int f) const { MsgAddInt(mb,-1-n,f); }

	//! Send boolean to self (inlet n)
	void MsgSelfBool(MsgBundle *mb,int n,bool f) const { MsgSelfInt(mb,n,f?1:0); }

373 374 375
	//! Output double (index n starts with 0)
	void MsgSelfDouble(MsgBundle *mb,int n,double d) const { t_atom dbl[2]; MsgSelfList(mb,n,2,SetDouble(dbl,d)); }

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
	//! Send symbol to self (inlet n)
    void MsgSelfSymbol(MsgBundle *mb,int n,const t_symbol *s) const { MsgAddSymbol(mb,-1-n,s); }
	//! Send string aka symbol to self (inlet 0)
	void MsgSelfString(MsgBundle *mb,int n,const char *s) const { MsgSelfSymbol(mb,n,MakeSymbol(s)); }

	//! Output atom (index n starts with 0)
    void MsgSelfAtom(MsgBundle *mb,int n,const t_atom &at) const { MsgAddAtom(mb,-1-n,at); }

	//! Send list to self (inlet n)
    void MsgSelfList(MsgBundle *mb,int n,int argc,const t_atom *argv) const { MsgAddList(mb,-1-n,argc,argv); }
	//! Send list to self (inlet n)
	void MsgSelfList(MsgBundle *mb,int n,const AtomList &list) const { MsgSelfList(mb,n,list.Count(),list.Atoms()); }

	//! Send anything to self (inlet n)
    void MsgSelfAnything(MsgBundle *mb,int n,const t_symbol *s,int argc,const t_atom *argv) const { MsgAddAnything(mb,-1-n,s,argc,argv); }
	//! Send anything to self (inlet n)
	void MsgSelfAnything(MsgBundle *mb,int n,const AtomAnything &any) const { MsgSelfAnything(mb,n,any.Header(),any.Count(),any.Atoms()); }

    //! @} FLEXT_C_IO_MESSAGEBUNDLE
thomas's avatar
thomas committed
395 396

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

thomas's avatar
thomas committed
398

thomas's avatar
thomas committed
399 400 401 402
// --- message handling -------------------------------------------

	enum metharg {
		a_null = 0,
thomas's avatar
thomas committed
403
		a_float,a_int,a_bool,
thomas's avatar
thomas committed
404
		a_symbol,a_pointer,
thomas's avatar
thomas committed
405 406
		a_list,a_any, // (t_symbol *) / int / t_atom *
		a_LIST,a_ANY // AtomList, AtomAnything
thomas's avatar
thomas committed
407 408
	};

thomas's avatar
thomas committed
409
	typedef bool (*methfun)(flext_base *c);
thomas's avatar
thomas committed
410

thomas's avatar
thomas committed
411
	/*!	\defgroup FLEXT_C_ADDMETHOD Method handling (object scope)
thomas's avatar
thomas committed
412 413 414 415
		\internal
		@{ 
	*/

416
    void AddMethodDef(int inlet,const t_symbol *tag = NULL) { ThMeths()->Add(new MethItem,tag,inlet); }
thomas's avatar
thomas committed
417 418
    void AddMethodDef(int inlet,const char *tag = NULL) { AddMethodDef(inlet,MakeSymbol(tag)); }

thomas's avatar
thomas committed
419
	void AddMethod(int inlet,bool (*m)(flext_base *)) { AddMethod(ThMeths(),inlet,sym_bang,(methfun)m,a_null); }
thomas's avatar
thomas committed
420 421 422 423 424 425 426 427 428 429 430
	void AddMethod(int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ThMeths(),inlet,sym_list,(methfun)m,a_list,a_null); }
	void AddMethod(int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,sym_list,(methfun)m,a_list,a_null); }
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_null); }  // pure method
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ThMeths(),inlet,sym_anything,(methfun)m,a_any,a_null); } // anything
	void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,sym_anything,(methfun)m,a_any,a_null); } // anything
	void AddMethod(int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ThMeths(),inlet,sym_symbol,(methfun)m,a_symbol,a_null); } // single symbol
	void AddMethod(int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ThMeths(),inlet,sym_symbol,(methfun)m,a_symbol,a_null); } // single symbol
	void AddMethod(int inlet,bool (*m)(flext_base *,float &)) { AddMethod(ThMeths(),inlet,sym_float,(methfun)m,a_float,a_null); }  // single float
	void AddMethod(int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(ThMeths(),inlet,sym_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(ThMeths(),inlet,sym_list,(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats
thomas's avatar
thomas committed
431
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
432
	void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,sym_float,(methfun)m,a_int,a_null); }  // single float
thomas's avatar
thomas committed
433
#else
434
	void AddMethod(int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,sym_int,(methfun)m,a_int,a_null); }  // single float
thomas's avatar
thomas committed
435
#endif
thomas's avatar
thomas committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
	void AddMethod(int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(ThMeths(),inlet,sym_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(ThMeths(),inlet,sym_list,(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,float &)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_float,a_null); }  // method+float
	void AddMethod(int inlet,const t_symbol *tag,bool (*m)(flext_base *,int &)) { AddMethod(ThMeths(),inlet,tag,(methfun)m,a_int,a_null); } // method+int
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(inlet,MakeSymbol(tag),m); }
	void AddMethod(int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(inlet,MakeSymbol(tag),m); }
thomas's avatar
thomas committed
454

thomas's avatar
thomas committed
455
	// ¥schedule call of the CbIdle method during the next idle cycle
456 457
	void AddIdle();

thomas's avatar
thomas committed
458
	//! Set Max/MSP style of distributing list elements over (message) inlets
thomas's avatar
thomas committed
459 460 461 462
	static void SetDist(t_classid c,bool d = true);
    //! Query whether lists are distributed
	bool DoDist() const;

thomas's avatar
thomas committed
463 464 465 466 467 468 469 470

//!		@} FLEXT_C_ADDMETHOD

	/*!	\defgroup FLEXT_C_CADDMETHOD Method handling (class scope)
		\internal
		@{ 
	*/

thomas's avatar
thomas committed
471
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *)) { AddMethod(ClMeths(c),inlet,sym_bang,(methfun)m,a_null); }
thomas's avatar
thomas committed
472 473 474 475 476 477 478 479 480 481 482
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_list,a_null); }
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_list,a_null); }
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_null); }  // pure method
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,sym_anything,(methfun)m,a_any,a_null); } // anything
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,sym_anything,(methfun)m,a_any,a_null); } // anything
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ClMeths(c),inlet,sym_symbol,(methfun)m,a_symbol,a_null); } // single symbol
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ClMeths(c),inlet,sym_symbol,(methfun)m,a_symbol,a_null); } // single symbol
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,float &)) { AddMethod(ClMeths(c),inlet,sym_float,(methfun)m,a_float,a_null); }  // single float
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,float &,float &)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_float,a_float,a_null); } // list of 2 floats
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,float &,float &,float &)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_float,a_float,a_float,a_null); } // list of 3 floats
thomas's avatar
thomas committed
483
#if FLEXT_SYS == FLEXT_SYS_PD
thomas's avatar
thomas committed
484
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,sym_float,(methfun)m,a_int,a_null); }  // single integer
thomas's avatar
thomas committed
485
#else
486
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,sym_int,(methfun)m,a_int,a_null); }  // single integer
thomas's avatar
thomas committed
487
#endif
thomas's avatar
thomas committed
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int &,int &)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_int,a_int,a_null); } // list of 2 floats
	static void AddMethod(t_classid c,int inlet,bool (*m)(flext_base *,int &,int &,int &)) { AddMethod(ClMeths(c),inlet,sym_list,(methfun)m,a_int,a_int,a_int,a_null); } // list of 3 floats
    static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_list,a_null); } // method+gimme
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_any,a_null); } // method+gimme 
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_symbol,a_null); } // method+symbol
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,float &)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_float,a_null); }  // method+float
	static void AddMethod(t_classid c,int inlet,const t_symbol *tag,bool (*m)(flext_base *,int &)) { AddMethod(ClMeths(c),inlet,tag,(methfun)m,a_int,a_null); } // method+int
    static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,int,t_atom *)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,int,const t_atom *)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *,int,t_atom *)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *,int,const t_atom *)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,t_symbol *&)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,const t_symbol *&)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,float &)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
	static void AddMethod(t_classid c,int inlet,const char *tag,bool (*m)(flext_base *,int &)) { AddMethod(c,inlet,MakeSymbol(tag),m); }
thomas's avatar
thomas committed
506

thomas's avatar
thomas committed
507
	// ¥schedule call of the given idlefun during the next idle cycle
508 509
	static void AddIdle(bool (*idlefun)(int argc,const t_atom *argv),int argc,const t_atom *argv);

thomas's avatar
thomas committed
510
//!		@} FLEXT_C_CADDMETHOD
thomas's avatar
thomas committed
511

thomas's avatar
thomas committed
512
// --- bind/unbind ---------------------------------------
thomas's avatar
thomas committed
513

thomas's avatar
thomas committed
514 515 516 517 518
	/*!	\defgroup FLEXT_C_BIND Methods for binding a flext class to a symbol

		@{ 
	*/

thomas's avatar
thomas committed
519
	//! Bind object to a symbol
520
	bool Bind(const t_symbol *sym);
thomas's avatar
thomas committed
521
	//! Unbind object from a symbol
522
	bool Unbind(const t_symbol *sym);
thomas's avatar
thomas committed
523

thomas's avatar
thomas committed
524
	//! Bind object to a symbol (as string)
525
	bool Bind(const char *sym) { return Bind(MakeSymbol(sym)); }  
thomas's avatar
thomas committed
526
	//! Unbind object from a symbol (as string)
527
	bool Unbind(const char *sym) { return Unbind(MakeSymbol(sym)); }  
thomas's avatar
thomas committed
528

529 530 531 532 533 534 535 536
    /*! \brief Bind a method to a symbol
        \param sym Symbol to bind to
        \param meth Function to bind
        \param data User data that is passed to the function
        \return true on success
    */
	bool BindMethod(const t_symbol *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data),void *data = NULL);
    /*! \brief Unbind a method from a symbol
537 538
        \param sym Symbol to unbind from (if NULL... unbind all functions)
        \param meth Method to unbind (if NULL ... unbind all functions bound to symbol)
539 540 541
        \param data returns data pointer specified with BindMethod
        \return true on success
    */
542
	bool UnbindMethod(const t_symbol *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data) = NULL,void **data = NULL);
thomas's avatar
thomas committed
543 544 545 546 547 548 549
    /*! \brief Get data of bound method of a symbol
        \param sym Symbol to bind to
        \param meth Function to bind
        \param data Reference to returned user data
        \return true on success (symbol/method combination was found)
    */
	bool GetBoundMethod(const t_symbol *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data),void *&data);
550

551
    //! \brief Bind a method to a symbol (as string)
552
    bool BindMethod(const char *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data),void *data = NULL) { return BindMethod(MakeSymbol(sym),meth,data); }
553 554
    //! \brief Unbind a method from a symbol (as string)
    bool UnbindMethod(const char *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data) = NULL,void **data = NULL) { return UnbindMethod(MakeSymbol(sym),meth,data); }
thomas's avatar
thomas committed
555 556
    //! \brief Get data of bound method of a symbol (as string)
    bool GetBoundMethod(const char *sym,bool (*meth)(flext_base *obj,t_symbol *sym,int argc,t_atom *argv,void *data),void *&data) { return GetBoundMethod(MakeSymbol(sym),meth,data); }
thomas's avatar
thomas committed
557

thomas's avatar
thomas committed
558 559 560 561 562
	/*! Unbind all symbol bindings
		\note Memory associated to data pointers passed by BindMethod will not be freed!
	*/
	bool UnbindAll();

thomas's avatar
thomas committed
563 564
//!		@} FLEXT_C_BIND

thomas's avatar
thomas committed
565
	// --- thread stuff -----------------------------------------------
thomas's avatar
thomas committed
566

thomas's avatar
thomas committed
567
#ifdef FLEXT_THREADS
thomas's avatar
thomas committed
568
	/*!	\defgroup FLEXT_C_THREAD Thread handling 
thomas's avatar
thomas committed
569 570 571 572

		@{ 
	*/

thomas's avatar
thomas committed
573
	//! Start a thread for this object
574
	bool StartThread(void (*meth)(thr_params *p),thr_params *p,const char * = NULL) { p->cl = this; return flext::LaunchThread(meth,p); }
thomas's avatar
thomas committed
575 576

	//! Terminate all threads of this object
thomas's avatar
thomas committed
577
	bool StopThreads();
thomas's avatar
thomas committed
578 579
#endif // FLEXT_THREADS

thomas's avatar
thomas committed
580
//!		@}  FLEXT_C_THREAD
thomas's avatar
thomas committed
581

thomas's avatar
thomas committed
582 583
// xxx internal stuff xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

thomas's avatar
thomas committed
584 585 586 587 588 589 590 591 592
public: // needed by VC++ 6

    enum xlettype {
	    xlet_none = 0,
	    xlet_float,xlet_int,xlet_sym,xlet_list,xlet_any,
	    xlet_LIST,xlet_ANY, // use AtomList and AtomAnything
	    xlet_sig
    };

thomas's avatar
thomas committed
593 594
protected:

595
	FLEXT_CLASSDEF(flext_base)();
thomas's avatar
thomas committed
596

thomas's avatar
thomas committed
597
	/*! \brief Set up inlets and outlets, method and attribute lists
thomas's avatar
thomas committed
598
	*/
thomas's avatar
thomas committed
599 600
	virtual bool Init();
	
601 602 603 604
	/*! \brief Deallocate all kinds of stuff
	*/
	virtual void Exit();
	
thomas's avatar
thomas committed
605

thomas's avatar
thomas committed
606
	/*!	\defgroup FLEXT_C_ATTR Attribute handling methods (object scope)
thomas's avatar
thomas committed
607 608 609
		@{ 
	*/

thomas's avatar
thomas committed
610 611 612 613 614 615 616 617 618 619 620 621 622 623
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(attr,a_float,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(attr,a_int,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,bool &),bool (*set)(flext_base *,bool &)) { AddAttrib(attr,a_bool,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,t_symptr &),bool (*set)(flext_base *,t_symptr &)) { AddAttrib(attr,a_symbol,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(attr,a_LIST,(methfun)get,(methfun)set); }
	void AddAttrib(const t_symbol *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(attr,a_ANY,(methfun)get,(methfun)set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,bool &),bool (*set)(flext_base *,bool &)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,t_symptr &),bool (*set)(flext_base *,t_symptr &)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(MakeSymbol(attr),get,set); }
	void AddAttrib(const char *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(MakeSymbol(attr),get,set); }
thomas's avatar
thomas committed
624

thomas's avatar
thomas committed
625 626 627 628 629 630
//!		@} FLEXT_C_ATTR

	/*!	\defgroup FLEXT_C_CATTR Attribute handling methods (class scope)
		@{ 
	*/

thomas's avatar
thomas committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(c,attr,a_float,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(c,attr,a_int,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,bool &),bool (*set)(flext_base *,bool &)) { AddAttrib(c,attr,a_bool,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(c,attr,a_symbol,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,t_symptr &),bool (*set)(flext_base *,t_symptr &)) { AddAttrib(c,attr,a_symbol,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(c,attr,a_LIST,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const t_symbol *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(c,attr,a_ANY,(methfun)get,(methfun)set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,float &),bool (*set)(flext_base *,float &)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,int &),bool (*set)(flext_base *,int &)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,bool &),bool (*set)(flext_base *,bool &)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,const t_symbol *&),bool (*set)(flext_base *,const t_symbol *&)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,t_symptr &),bool (*set)(flext_base *,t_symptr &)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,AtomList *&),bool (*set)(flext_base *,AtomList *&)) { AddAttrib(c,MakeSymbol(attr),get,set); }
	static void AddAttrib(t_classid c,const char *attr,bool (*get)(flext_base *,AtomAnything *&),bool (*set)(flext_base *,AtomAnything *&)) { AddAttrib(c,MakeSymbol(attr),get,set); }
thomas's avatar
thomas committed
645

thomas's avatar
thomas committed
646
//!		@} FLEXT_C_CATTR
thomas's avatar
thomas committed
647

thomas's avatar
thomas committed
648 649 650 651 652
	//! Dump an attribute to the attribute outlet
	bool DumpAttrib(const t_symbol *attr) const;
    //! Dump an attribute to the attribute outlet
	bool DumpAttrib(const char *attr) const { return DumpAttrib(MakeSymbol(attr)); }

thomas's avatar
thomas committed
653 654 655 656 657 658 659
    // check for attribute symbol @
	static int CheckAttrib(int argc,const t_atom *argv);
    // check for attribute symbol @
    static int CheckAttrib(const AtomList &args,int offset = 0) { return CheckAttrib(args.Count()-offset,args.Atoms()+offset)+offset; }

	//! List attributes
	bool ListAttrib() const;
thomas's avatar
thomas committed
660
	//! List attributes
661
	void ListAttrib(AtomList &a) const;
thomas's avatar
thomas committed
662 663 664
	//! Get an attribute value
	bool GetAttrib(const t_symbol *s,AtomList &a) const;
	//! Set an attribute value
thomas's avatar
thomas committed
665 666
	bool SetAttrib(const t_symbol *s,int argc,const t_atom *argv);
	//! Set an attribute value
thomas's avatar
thomas committed
667 668
	bool SetAttrib(const t_symbol *s,const AtomList &a) { return SetAttrib(s,a.Count(),a.Atoms()); }

thomas's avatar
thomas committed
669 670 671 672 673 674 675 676 677 678 679
	// get and set the attribute
	bool BangAttrib(const t_symbol *a);
	// get and set the attribute
	bool BangAttrib(const char *a) { return BangAttrib(MakeSymbol(a)); }
	// get and set all (both get- and settables)
	bool BangAttribAll();
	// show/hide the attribute
	bool ShowAttrib(const t_symbol *a,bool show) const;
	// show/hide the attribute
	bool ShowAttrib(const char *a,bool show) { return ShowAttrib(MakeSymbol(a),show); }

thomas's avatar
thomas committed
680
	//! List methods
681
	void ListMethods(AtomList &a,int inlet = 0) const;
thomas's avatar
thomas committed
682 683

/*!		\addtogroup FLEXT_C_INOUT 
thomas's avatar
thomas committed
684
		@{ 
thomas's avatar
thomas committed
685
*/
thomas's avatar
thomas committed
686

thomas's avatar
thomas committed
687
	//! \brief get a code for a list of inlets or outlets
thomas's avatar
thomas committed
688
	unsigned long XletCode(xlettype tp = xlet_none,...); // end list with 0 (= tp_none) !!
thomas's avatar
thomas committed
689

thomas's avatar
thomas committed
690 691 692 693 694 695
	/*! \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
696
	void AddInlet(xlettype tp,int mult = 1,const char *desc = NULL);
thomas's avatar
thomas committed
697 698 699 700 701 702 703

	/*! \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
704
	void AddOutlet(xlettype tp,int mult = 1,const char *desc = NULL);
thomas's avatar
thomas committed
705

thomas's avatar
thomas committed
706
	//! \brief Set the description of an indexed inlet
thomas's avatar
thomas committed
707
	void DescInlet(int ix,const char *desc);
thomas's avatar
thomas committed
708 709

	//! \brief Set the description of an indexed outlet
thomas's avatar
thomas committed
710
	void DescOutlet(int ix,const char *desc);
thomas's avatar
thomas committed
711

thomas's avatar
thomas committed
712
//!		@} FLEXT_C_INOUT
thomas's avatar
thomas committed
713

thomas's avatar
thomas committed
714

thomas's avatar
thomas committed
715 716
// method handling

thomas's avatar
thomas committed
717 718
	public:

thomas's avatar
thomas committed
719
	class AttrItem;
thomas's avatar
thomas committed
720

thomas's avatar
thomas committed
721
    class Item
thomas's avatar
thomas committed
722
    {
thomas's avatar
thomas committed
723
	public:
724 725
        Item(AttrItem *a): attr(a),nxt(NULL) {}
        virtual ~Item();
thomas's avatar
thomas committed
726
		
thomas's avatar
thomas committed
727 728
		bool IsAttr() const { return attr != NULL; }

thomas's avatar
thomas committed
729
		AttrItem *attr;
730
		Item *nxt;
thomas's avatar
thomas committed
731 732
	};

733 734