Jamoma API  0.6.0.a19
Max/source/j.parameter/j.parameter.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.parameter / j.message / j.return : Jamoma model parameter definition
6  *
7  * @details
8  *
9  * @authors Timothy Place, Théo de la Hogue, Trond Lossius
10  *
11  * @copyright © 2011 by Timothy Place, Théo de la Hogue @n
12  * This code is licensed under the terms of the "New BSD License" @n
13  * http://creativecommons.org/licenses/BSD/
14  */
15 
16 
18 
19 #define data_out 0
20 #define dump_out 1
21 
22 // This is used to store extra data
23 typedef struct extra {
24 
25  TTValue* arrayArgs; // store arguments
26 
27 } t_extra;
28 #define EXTRA ((t_extra*)x->extra)
29 
30 
31 // Definitions
32 void WrapTTDataClass(WrappedClassPtr c);
33 void WrappedDataClass_new(TTPtr self, long argc, t_atom *argv);
34 void WrappedDataClass_free(TTPtr self);
35 
36 
37 /** Provide assistance on input and output while patching.
38  @param self The parameter instance.
39  @param b
40  @param msg Determines if assistance is requested for an input or output.
41  @param arg Determines what input/output assistance is requested for.
42  @param dst Destination address that assistance string is copied to.
43  */
44 void data_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst);
45 
46 void data_new_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
47 void data_subscribe(TTPtr self, t_symbol *address, long argc, t_atom *argv);
48 void data_address(TTPtr self, t_symbol *name);
49 
50 void data_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
51 
52 
53 void WrappedDataClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
54 
55 
56 /** Process an incoming 'bang' message.
57  @param self The parameter instance
58  */
59 void data_bang(TTPtr self);
60 
61 
62 /** Process an incoming integer value.
63  @param self The parameter instance.
64  @param value The integer value received.
65  */
66 void data_int(TTPtr self, long value);
67 
68 
69 /** Process an incoming float value.
70  @param self The parameter instance.
71  @param value The float value received.
72  */
73 void data_float(TTPtr self, double value);
74 
75 
76 /** Process an incoming message containing a list. When the object receives a bang, int, float or anything, it is fornatted as a list and frwarded to this method.
77  @param self The parameter instance.
78  @param msg The dec symbol pointer
79  @param argc t_atom array count (length)
80  @param argv Pointer to the atom array
81  */
82 void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
83 
84 
85 /** Increase parameter value in steps.
86  @details Optional arguments passed as pointer to array of atoms specify how many steps to increase value by, if parameter is to ramp to new value and ramp time.
87  @param self The parameter instance
88  @param msg The dec symbol pointer
89  @param argc t_atom array count (length)
90  @param argv Pointer to the atom array
91  @see param_inc
92  */
93 void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
94 
95 
96 /** Decrease parameter value in steps.
97  @details Optional arguments passed as pointer to array of atoms specify how many steps to increase value by, if parameter is to ramp to new value and ramp time.
98  @param self The parameter instance
99  @param msg The dec symbol pointer
100  @param argc t_atom array count (length)
101  @param argv Pointer to the atom array
102  @see param_inc
103  */
104 void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
105 
106 
107 
108 int C74_EXPORT main(void)
109 {
110  ModularSpec *spec = new ModularSpec;
111  spec->_wrap = &WrapTTDataClass;
112  spec->_new = &WrappedDataClass_new;
113  spec->_free = &WrappedDataClass_free;
114  spec->_any = &WrappedDataClass_anything;
115 
116 #ifdef JMOD_MESSAGE
117  return wrapTTModularClassAsMaxClass(kTTSym_Data, "j.message", NULL, spec);
118 #endif
119 
120 #ifdef JMOD_RETURN
121  return wrapTTModularClassAsMaxClass(kTTSym_Data, "j.return", NULL, spec);
122 #endif
123 
124 #ifndef JMOD_MESSAGE
125 #ifndef JMOD_RETURN
126  return wrapTTModularClassAsMaxClass(kTTSym_Data, "j.parameter", NULL, spec);
127 #endif
128 #endif
129 }
130 
131 
132 void WrapTTDataClass(WrappedClassPtr c)
133 {
134  class_addmethod(c->maxClass, (method)data_assist, "assist", A_CANT, 0L);
135 
136  class_addmethod(c->maxClass, (method)data_return_value, "return_value", A_CANT, 0);
137 
138  class_addmethod(c->maxClass, (method)data_bang, "bang", 0L);
139  class_addmethod(c->maxClass, (method)data_int, "int", A_LONG, 0);
140  class_addmethod(c->maxClass, (method)data_float, "float", A_FLOAT, 0);
141  class_addmethod(c->maxClass, (method)data_list, "list", A_GIMME, 0);
142 
143  class_addmethod(c->maxClass, (method)data_inc, "+", A_GIMME, 0);
144  class_addmethod(c->maxClass, (method)data_dec, "-", A_GIMME, 0);
145 
146  class_addmethod(c->maxClass, (method)data_address, "address", A_SYM,0);
147 }
148 
149 
150 void WrappedDataClass_new(TTPtr self, long argc, t_atom *argv)
151 {
153  t_symbol* relativeAddress;
154  long attrstart = attr_args_offset(argc, argv); // support normal arguments
155 
156  // check address argument
157  relativeAddress = _sym_nothing;
158  if (attrstart && argv)
159  if (atom_gettype(argv) == A_SYM)
160  relativeAddress = atom_getsym(argv);
161 
162  if (relativeAddress == _sym_nothing) {
163  object_error((t_object*)x, "needs a name as first argument");
164  return;
165  }
166 
167  // check for reserved address
168  if (relativeAddress == gensym("data/mute") ||
169  relativeAddress == gensym("data/bypass") ||
170  relativeAddress == gensym("data/freeze") ||
171  relativeAddress == gensym("data/preview") ||
172  relativeAddress == gensym("audio/mute") ||
173  relativeAddress == gensym("audio/bypass") ||
174  relativeAddress == gensym("audio/mix") ||
175  relativeAddress == gensym("audio/gain") ||
176  relativeAddress == gensym("model") ||
177  relativeAddress == gensym("preset") ) {
178 
179  object_error((t_object*)x, "%s address is reserved by j.model", relativeAddress->s_name);
180  return;
181  }
182 
183  x->useInternals = false;
184 
185  // Make outlets (before attr_args_process)
186  /////////////////////////////////////////////////////////////////////////////////
187 
188  // Don't create outlets during dynamic changes
189  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 2);
190  x->outlets[data_out] = outlet_new(x, NULL); // anything outlet to output data
191 
192  // Prepare extra data
193  x->extra = (t_extra*)malloc(sizeof(t_extra));
194 
195  EXTRA->arrayArgs = new TTValue();
196 
197  // Store arguments
198  if (argc > 1 && argv)
199  jamoma_ttvalue_from_Atom(*(EXTRA->arrayArgs), _sym_list, argc--, argv++);
200 
201  data_new_address(self, relativeAddress, argc--, argv++);
202 }
203 
204 
205 void WrappedDataClass_free(TTPtr self)
206 {
208  free(EXTRA);
209 }
210 
211 
212 void data_new_address(TTPtr self, t_symbol *relativeAddress, long argc, t_atom *argv)
213 {
215 
216  // create the data
217 #ifdef JMOD_MESSAGE
218  jamoma_data_create((t_object*)x, x->wrappedObject, kTTSym_message);
219 #endif
220 
221 #if JMOD_RETURN
222  jamoma_data_create((t_object*)x, x->wrappedObject, kTTSym_return);
223 #endif
224 
225 #ifndef JMOD_MESSAGE
226 #ifndef JMOD_RETURN
227  jamoma_data_create((t_object*)x, x->wrappedObject, kTTSym_parameter);
228 #endif
229 #endif
230 
231  if (argc && argv)
232  attr_args_process(x, argc, argv);
233 
234  // The following must be deferred because we have to interrogate our box,
235  // and our box is not yet valid until we have finished instantiating the object.
236  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
237  defer_low((t_object*)x, (method)data_subscribe, relativeAddress, argc, argv);
238 }
239 
240 
241 void data_subscribe(TTPtr self, t_symbol *relativeAddress, long argc, t_atom *argv)
242 {
244  TTAddress returnedAddress;
245  TTNodePtr returnedNode = NULL;
246  TTNodePtr returnedContextNode = NULL;
247 
248  // for relative address
249  if (TTAddress(relativeAddress->s_name).getType() == kAddressRelative) {
250 
251  jamoma_subscriber_create((t_object*)x, x->wrappedObject, TTAddress(jamoma_parse_dieze((t_object*)x, relativeAddress)->s_name), x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode);
252 
253 #ifndef JMOD_MESSAGE
254 #ifndef JMOD_RETURN
255  // if a j.parameter is registered under the root : reset to the default value our self
256  if (returnedContextNode == accessApplicationLocalDirectory->getRoot())
257  {
258  TTBoolean initialized;
259  x->wrappedObject.get("initialized", initialized);
260  if (!initialized)
261  x->wrappedObject.send(kTTSym_Init);
262  }
263 #endif
264 #endif
265  }
266  else
267  object_error((t_object*)x, "can't register because %s is not a relative address", relativeAddress->s_name);
268 }
269 
270 
271 void data_address(TTPtr self, t_symbol *address)
272 {
274  long argc = 0;
275  t_atom *argv = NULL;
276 
277  // unregister wrapped object (or internals)
278  wrappedModularClass_unregister(x);
279 
280  // use stored arguments
281  jamoma_ttvalue_to_Atom(*(EXTRA->arrayArgs), &argc, &argv);
282 
283  // rebuild wrapped object (or internals)
284  defer_low(self,(method)data_new_address, address, argc, argv);
285 }
286 
287 
288 // Method for Assistance Messages
289 void data_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
290 {
291  if (msg==1) // Inlet
292  strcpy(dst, "update value, ramp to new value, or set an attribute");
293  else { // Outlets
294  switch(arg) {
295  case data_out:
296  strcpy(dst, "current value when updated");
297  break;
298  case dump_out:
299  strcpy(dst, "dumpout");
300  break;
301  }
302  }
303 }
304 
305 
306 void data_bang(TTPtr self)
307 {
308  data_list(self, _sym_bang, 0, NULL);
309 }
310 
311 
312 void data_int(TTPtr self, long value)
313 {
314  t_atom a;
315 
316  atom_setlong(&a, value);
317  // Forwards to data_float
318  data_list(self, _sym_int, 1, &a);
319 }
320 
321 
322 void data_float(TTPtr self, double value)
323 {
324  t_atom a;
325 
326  atom_setfloat(&a, value);
327  data_list(self, _sym_float, 1, &a);
328 }
329 
330 
331 void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
332 {
334 
335  jamoma_data_command(x->wrappedObject, msg, argc, argv);
336 }
337 
338 
339 void WrappedDataClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
340 {
342 
343  jamoma_data_command(x->wrappedObject, msg, argc, argv);
344 }
345 
346 
347 void data_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
348 {
350 
351  // avoid blank before data
352  if (msg == _sym_nothing)
353  outlet_atoms(x->outlets[data_out], argc, argv);
354  else
355  outlet_anything(x->outlets[data_out], msg, argc, argv);
356 }
357 
358 
359 void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
360 {
362  TTValue v, none;
363 
364  jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
365  x->wrappedObject.send("Inc", v, none);
366 }
367 
368 
369 void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
370 {
372  TTValue v, none;
373 
374  jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
375  x->wrappedObject.send("Dec", v, none);
376 }
TTObject subscriberObject
The instance of a TTSubscriber object used to register the wrapped object in the tree structure...
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTHandle outlets
an array of outlet
TTErr wrapTTModularClassAsMaxClass(TTSymbol &ttblueClassName, const char *maxClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Max class.
t_symbol JAMOMA_EXPORT * jamoma_parse_dieze(t_object *x, t_symbol *address)
Parse #N inside address and replace them by parent patcher arguments if there are.
void data_int(TTPtr self, long value)
Process an incoming integer value.
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
Data structure for storing extra data.
void * extra
used to keep very specific things
this flag means that an address have no leading slash
Definition: TTAddressBase.h:64
TTErr JAMOMA_EXPORT jamoma_data_create(t_object *x, TTObject &returnedData, TTSymbol service)
Create a TTData object.
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Increase parameter value in steps.
void JAMOMA_EXPORT jamoma_ttvalue_to_Atom(const TTValue &v, long *argc, t_atom **argv)
Make an Atom array from a TTValue.
TTErr JAMOMA_EXPORT jamoma_data_command(TTObject &aData, t_symbol *msg, long argc, const t_atom *argv)
Set the TTData value attribute using the #TTData::Command method.
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Process an incoming message containing a list.
void JAMOMA_EXPORT jamoma_ttvalue_from_Atom(TTValue &v, t_symbol *msg, long argc, const t_atom *argv)
Make a TTValue from Atom array.
void data_bang(TTPtr self)
Process an incoming 'bang' message.
Data Structure for this object.
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
Wraps Jamoma Core classes as objects for Max/MSP.
TTBoolean useInternals
The hash table can be used as an array of wrappedObject.
void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Decrease parameter value in steps.
TTErr JAMOMA_EXPORT jamoma_subscriber_create(t_object *x, TTObject &anObject, TTAddress relativeAddress, TTObject &returnedSubscriber, TTSymbol &returnedAddress, TTNodePtr *returnedNode, TTNodePtr *returnedContextNode)
Create a #TTSubscriber object and register a TTObject into the tree or, if aTTObject is NULL...
void data_float(TTPtr self, double value)
Process an incoming float value.
void data_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
Provide assistance on input and output while patching.
WrappedModularInstance * WrappedModularInstancePtr
Pointer to a wrapped instance of our object.
#define accessApplicationLocalDirectory
Access to the local application directory.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34