Jamoma API  0.6.0.a19
PureData/source/j.parameter/j.parameter.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
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, Antoine Villeret
10  *
11  * @copyright © 2011 by Timothy Place, Théo de la Hogue @n
12  * Copyright © 2015, Antoine Villeret@n
13  * This code is licensed under the terms of the "New BSD License" @n
14  * http://creativecommons.org/licenses/BSD/
15  */
16 
17 
19 
20 #define data_out 0
21 #define dump_out 1
22 
23 // This is used to store extra data
24 typedef struct extra {
25 
26  TTValue* arrayArgs; // store arguments
27  t_symbol* address;
28 
29 } t_extra;
30 #define EXTRA ((t_extra*)x->extra)
31 
32 
33 // Definitions
34 void WrapTTDataClass(WrappedClassPtr c);
35 void WrappedDataClass_new(TTPtr self, long argc, t_atom *argv);
36 void WrappedDataClass_free(TTPtr self);
37 
38 
39 /** Provide assistance on input and output while patching.
40  @param self The parameter instance.
41  @param b
42  @param msg Determines if assistance is requested for an input or output.
43  @param arg Determines what input/output assistance is requested for.
44  @param dst Destination address that assistance string is copied to.
45  */
46 void data_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst);
47 
48 void data_new_address(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
49 void data_subscribe(TTPtr self, t_symbol *address);
50 void data_address(TTPtr self, t_symbol *name);
51 
52 void data_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
53 
54 
55 void WrappedDataClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
56 
57 
58 /** Process an incoming 'bang' message.
59  @param self The parameter instance
60  */
61 void data_bang(TTPtr self);
62 
63 
64 /** Process an incoming float value.
65  @param self The parameter instance.
66  @param value The float value received.
67  */
68 void data_float(TTPtr self, t_float value);
69 
70 
71 /** 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.
72  @param self The parameter instance.
73  @param msg The dec symbol pointer
74  @param argc t_atom array count (length)
75  @param argv Pointer to the atom array
76  */
77 void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
78 
79 
80 /** Increase parameter value in steps.
81  @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.
82  @param self The parameter instance
83  @param msg The dec symbol pointer
84  @param argc t_atom array count (length)
85  @param argv Pointer to the atom array
86  @see param_inc
87  */
88 void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
89 
90 
91 /** Decrease parameter value in steps.
92  @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.
93  @param self The parameter instance
94  @param msg The dec symbol pointer
95  @param argc t_atom array count (length)
96  @param argv Pointer to the atom array
97  @see param_inc
98  */
99 void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
100 
101 
102 /** Loadbang method to register parameter *after* box creation */
103 void data_loadbang(TTPtr self);
104 
105 #if defined(JMOD_RETURN)
106 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2ereturn(void)
107 #elif defined(JMOD_MESSAGE)
108 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2emessage(void)
109 #else
110 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2eparameter(void)
111 #endif
112 {
113  ModularSpec *spec = new ModularSpec;
114  spec->_wrap = &WrapTTDataClass;
115  spec->_new = &WrappedDataClass_new;
116  spec->_free = &WrappedDataClass_free;
117  spec->_any = &WrappedDataClass_anything;
118  spec->_notify = NULL;
119 
120 #if defined(JMOD_MESSAGE)
121  return (void)wrapTTModularClassAsPdClass(kTTSym_Data, "j.message", NULL, spec);
122 #elif defined(JMOD_RETURN)
123  return (void)wrapTTModularClassAsPdClass(kTTSym_Data, "j.return", NULL, spec);
124 #else
125  return (void)wrapTTModularClassAsPdClass(kTTSym_Data, "j.parameter", NULL, spec);
126 #endif
127 }
128 
129 
130 void WrapTTDataClass(WrappedClassPtr c)
131 {
132  eclass_addmethod(c->pdClass, (method)data_assist, "assist", A_CANT, 0L);
133 
134  eclass_addmethod(c->pdClass, (method)data_return_value, "return_value", A_CANT, 0L);
135 
136  eclass_addmethod(c->pdClass, (method)data_bang, "bang", A_NULL, 0L);
137  eclass_addmethod(c->pdClass, (method)data_float, "float", A_FLOAT, 0);
138  eclass_addmethod(c->pdClass, (method)data_list, "list", A_GIMME, 0);
139 
140  eclass_addmethod(c->pdClass, (method)data_inc, "+", A_GIMME, 0);
141  eclass_addmethod(c->pdClass, (method)data_dec, "-", A_GIMME, 0);
142 
143  eclass_addmethod(c->pdClass, (method)data_address, "address", A_SYM,0);
144  eclass_addmethod(c->pdClass, (method)data_loadbang, "loadbang", A_NULL,0);
145 }
146 
147 
148 void WrappedDataClass_new(TTPtr self, long argc, t_atom *argv)
149 {
151  t_symbol* relativeAddress;
152  long attrstart = attr_args_offset(argc, argv); // support normal arguments
153 
154  // check address argument
155  relativeAddress = _sym_nothing;
156 
157  // Prepare extra data
158  x->extra = (t_extra*)malloc(sizeof(t_extra));
159  EXTRA->address = _sym_nothing;
160  EXTRA->arrayArgs = new TTValue();
161 
162  if (attrstart && argv)
163  if (atom_gettype(argv) == A_SYM)
164  relativeAddress = atom_getsym(argv);
165 
166  if (relativeAddress == _sym_nothing) {
167  pd_error((t_object*)x, "needs a name as first argument");
168  return;
169  }
170 
171  // check for reserved address
172  if (relativeAddress == gensym("data/mute") ||
173  relativeAddress == gensym("data/bypass") ||
174  relativeAddress == gensym("data/freeze") ||
175  relativeAddress == gensym("data/preview") ||
176  relativeAddress == gensym("audio/mute") ||
177  relativeAddress == gensym("audio/bypass") ||
178  relativeAddress == gensym("audio/mix") ||
179  relativeAddress == gensym("audio/gain") ||
180  relativeAddress == gensym("model") ||
181  relativeAddress == gensym("preset") ) {
182 
183  pd_error((t_object*)x, "%s address is reserved by j.model", relativeAddress->s_name);
184  return;
185  }
186 
187  x->useInternals = false;
188 
189  // Make outlets (before attr_args_process)
190  /////////////////////////////////////////////////////////////////////////////////
191 
192  // Don't create outlets during dynamic changes
193  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr));
194  x->outlets[data_out] = outlet_new((t_object*)x, NULL); // anything outlet to output data
195 
196  // Store arguments
197  if (argc > 1 && argv)
198  jamoma_ttvalue_from_Atom(*(EXTRA->arrayArgs), _sym_list, argc--, argv++);
199 
200  EXTRA->address = relativeAddress;
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, (t_method)data_subscribe, relativeAddress, argc, argv);
238  data_subscribe((t_object*)x, relativeAddress);
239 }
240 
241 
242 void data_subscribe(TTPtr self, t_symbol *relativeAddress)
243 {
245  TTAddress returnedAddress;
246  TTNodePtr returnedNode = NULL;
247  TTNodePtr returnedContextNode = NULL;
248 
249  // for relative address
250  if (TTAddress(relativeAddress->s_name).getType() == kAddressRelative) {
251 
252  if(!jamoma_subscriber_create((t_eobj*)x, x->wrappedObject, relativeAddress->s_name, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode))
253  pd_error((t_object*)x, "error when registering %s", relativeAddress->s_name);
254 
255 #ifndef JMOD_MESSAGE
256 #ifndef JMOD_RETURN
257  /* TODO this crashes Pd
258  // if a j.parameter is registered under the root : reset to the default value our self
259  if (returnedContextNode == accessApplicationLocalDirectory->getRoot())
260  {
261  TTBoolean initialized;
262  x->wrappedObject.get("initialized", initialized);
263  if (!initialized)
264  x->wrappedObject.send(kTTSym_Init);
265  }
266  */
267 #endif
268 #endif
269  }
270  else
271  pd_error((t_object*)x, "can't register because %s is not a relative address", relativeAddress->s_name);
272 }
273 
274 
275 void data_address(TTPtr self, t_symbol *address)
276 {
278  long argc = 0;
279  t_atom *argv = NULL;
280 
281  // unregister wrapped object (or internals)
282  wrappedModularClass_unregister(x);
283 
284  // use stored arguments
285  jamoma_ttvalue_to_Atom(*(EXTRA->arrayArgs), &argc, &argv);
286 
287  // rebuild wrapped object (or internals)
288  // defer_low(self,(t_method)data_new_address, address, argc, argv);
289  data_new_address(self, address, argc, argv);
290 }
291 
292 
293 // Method for Assistance Messages
294 void data_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
295 {
296  if (msg==1) // Inlet
297  strcpy(dst, "input");
298  else { // Outlets
299  switch(arg) {
300  case data_out:
301  strcpy(dst, "direct: values");
302  break;
303  case dump_out:
304  strcpy(dst, "dumpout");
305  break;
306  }
307  }
308 }
309 
310 
311 void data_bang(TTPtr self)
312 {
313  data_list(self, _sym_bang, 0, NULL);
314 }
315 
316 void data_float(TTPtr self, t_float value)
317 {
318  t_atom a;
319 
320  atom_setfloat(&a, value);
321  data_list(self, _sym_float, 1, &a);
322 }
323 
324 
325 void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
326 {
328 
329  jamoma_data_command(x->wrappedObject, msg, argc, argv);
330 }
331 
332 
333 void WrappedDataClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
334 {
336 
337  jamoma_data_command(x->wrappedObject, msg, argc, argv);
338 }
339 
340 
341 void data_return_value(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
342 {
344 
345  // avoid blank before data
346  if ( msg == _sym_nothing)
347  outlet_anything((t_outlet*)x->outlets[data_out], NULL, argc, argv);
348  else
349  outlet_anything((t_outlet*)x->outlets[data_out], msg, argc, argv);
350 }
351 
352 
353 void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
354 {
356  TTValue v, none;
357 
358  jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
359  x->wrappedObject.send("Inc", v, none);
360 }
361 
362 
363 void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
364 {
366  TTValue v, none;
367 
368  jamoma_ttvalue_from_Atom(v, _sym_nothing, argc, argv);
369  x->wrappedObject.send("Dec", v, none);
370 }
371 
373 {
375  data_subscribe((t_object*)x, EXTRA->address);
376 }
TTObject subscriberObject
The instance of a TTSubscriber object used to register the wrapped object in the tree structure...
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTHandle outlets
an array of outlet
void data_float(TTPtr self, t_float 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.
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
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 data_bang(TTPtr self)
Process an incoming 'bang' message.
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
void JAMOMA_EXPORT jamoma_ttvalue_to_Atom(const TTValue &v, long *argc, t_atom **argv)
Make an Atom array from a TTValue.
void data_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Process an incoming message containing a list.
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.
void data_inc(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Increase parameter value in steps.
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
void JAMOMA_EXPORT jamoma_ttvalue_from_Atom(TTValue &v, t_symbol *msg, long argc, const t_atom *argv)
Make a TTValue from Atom array.
Wraps Jamoma Core classes as objects for PureData.
Data Structure for this object.
void data_loadbang(TTPtr self)
Loadbang method to register parameter after box creation.
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
void data_dec(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Decrease parameter value in steps.
TTBoolean useInternals
The hash table can be used as an array of wrappedObject.
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...
WrappedModularInstance * WrappedModularInstancePtr
Pointer to a wrapped instance of our object.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr wrapTTModularClassAsPdClass(TTSymbol &ttblueClassName, const char *pdClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Pd class.