Jamoma API  0.6.0.a19
PureData/source/j.in/j.in.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationPdExternals
4  *
5  * @brief j.in & j.in~ & j.in= - Manage control and audio inputs for a Jamoma model
6  *
7  * @details
8  *
9  * @authors Tim Place, Théo de la Hogue, Nils Peters, Trond Lossius, Antoine Villeret
10  *
11  * @copyright Copyright © 2006 by Tim Place @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 
18 
19 #define signal_out 0
20 #define dump_out 1
21 
22 // This is used to store extra data
23 typedef struct extra {
24 
25  TTSymbol instance; ///< Input instance symbol
26  t_object *modelOrView; ///< the j.model or j.view object of our patcher
27 
28 } t_extra;
29 #define EXTRA ((t_extra*)x->extra)
30 
31 
32 // Definitions
33 
34 /** Wrap the j.in class as a Max object.
35  @param c The class to be wrapped
36  @see WrappedInputClass_new, WrappedInputClass_free
37  */
38 void WrapTTInputClass(WrappedClassPtr c);
39 
40 /** Wrapper for the j.in constructor class, called when an instance is created.
41  @param self Pointer to this object.
42  @param argc The number of arguments passed to the object.
43  @param argv Pointer to an array of atoms passed to the object.
44  @see WrappedInputClass_free, in_subscribe
45  */
46 void WrappedInputClass_new(TTPtr self, long argc, t_atom *argv);
47 
48 /** Wrapper for the j.in deconstructor class, called when an instance is destroyed.
49  @param self Pointer to this object.
50  @see WrappedInputClass_new
51  */
52 void WrappedInputClass_free(TTPtr self);
53 
54 /** Assistance Method.
55  @param self Pointer to this object.
56  @param b Pointer to (exactly what?)
57  @param msg The message passed to the object.
58  @param arg
59  @param dst Pointer to the destination that assistance strings are passed to for display.
60  */
61 void in_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst);
62 
63 /** Associate j.in(~) with NodeLib. This is a prerequisit for communication with other Jamoma object in the module and beyond. */
64 void in_subscribe(TTPtr self);
65 
66 #ifdef J_IN_TILDE
67 /** j.in~ 64-bit MSP perform method (for Max 6). Only defineed for j.in~. */
68 void in_perform64(TTPtr self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
69 
70 /** j.in~ 64-bit DSP method (for Max 6). Only defineed for j.in~. */
71 void in_dsp64(TTPtr self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags);
72 #endif
73 
74 #ifdef J_IN_MULTI
75 /** reset audiogrpaph setup of the wrapped object
76  @param self Pointer to this object.
77  */
78 void in_reset(TTPtr self);
79 
80 /** reset audiogrpaph setup of the wrapped object
81  @param self Pointer to this object.
82  */
83 void in_setup(TTPtr self);
84 
85 /** reset audiogrpaph setup of the wrapped audiograph object
86  @param self Pointer to this audiograph object.
87  @param audioSourceObject The audiograph object to connect with.
88  @param sourceOutletNumber The number of channel the source audiograph object have.
89  */
90 void in_connect(TTPtr self, TTAudioGraphObjectBasePtr audioSourceObject, long sourceOutletNumber);
91 #endif
92 
93 #ifndef J_IN_TILDE
94 #ifndef J_IN_MULTI
95 /** bang handler for j.in
96  @param self Pointer to this object.
97  @see in_float, in_list, WrappedInputClass_anything
98  */
99 void in_bang(TTPtr self);
100 
101 /** float handler for j.in
102  @param self Pointer to this object.
103  @param value The value sent to this object.
104  @see in_bang, in_list, WrappedInputClass_anything
105  */
106 void in_float(TTPtr self, t_float value);
107 
108 /** list handler for j.in
109  @param self Pointer to this object.
110  @param msg The message sent to this object.
111  @param argc The number of arguments passed to the object.
112  @param argv Pointer to an array of atoms passed to the object.
113  @see in_bang, in_float, WrappedInputClass_anything
114  */
115 void in_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
116 
117 /** Method used to pass messages from the module outlet. */
118 void in_return_signal(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
119 #endif
120 #endif
121 
122 /** anything else handler for j.in
123  @param self Pointer to this object.
124  @param msg The message sent to this object.
125  @param argc The number of arguments passed to the object.
126  @param argv Pointer to an array of atoms passed to the object.
127  @see in_bang, in_float, in_list
128  */
129 void WrappedInputClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv);
130 
131 
132 #pragma mark -
133 #pragma mark main
134 
135 extern "C" void JAMOMA_EXPORT_MAXOBJ setup_j0x2ein(void)
136 {
137  ModularSpec *spec = new ModularSpec;
138  spec->_wrap = &WrapTTInputClass;
139  spec->_new = &WrappedInputClass_new;
140  spec->_free = &WrappedInputClass_free;
141  spec->_any = &WrappedInputClass_anything;
142 
143 #ifdef J_IN_TILDE
144  return (void)wrapTTModularClassAsPdClass(kTTSym_InputAudio, "j.in~", NULL, spec);
145 #endif
146 
147 #ifdef J_IN_MULTI
148  return (void)wrapTTModularClassAsPdClass(kTTSym_InputAudio, "j.in=", NULL, spec);
149 #endif
150 
151 #ifndef J_IN_TILDE
152 #ifndef J_IN_MULTI
153  return (void)wrapTTModularClassAsPdClass(kTTSym_Input, "j.in", NULL, spec);
154 #endif
155 #endif
156 
157 }
158 
159 void WrapTTInputClass(WrappedClassPtr c)
160 {
161  eclass_addmethod(c->pdClass, (method)in_assist, "assist", A_CANT, 0L);
162 
163 #ifdef J_IN_TILDE
164  eclass_addmethod(c->pdClass, (method)in_dsp64, "dsp64", A_CANT, 0);
165 #endif
166 
167 #ifdef J_IN_MULTI
168  eclass_addmethod(c->pdClass, (method)in_reset, "audio.reset", A_CANT, 0);
169  eclass_addmethod(c->pdClass, (method)in_setup, "audio.setup", A_CANT, 0);
170  eclass_addmethod(c->pdClass, (method)in_connect, "audio.connect", A_OBJ, A_LONG, 0);
171 #endif
172 
173 #ifndef J_IN_TILDE
174 #ifndef J_IN_MULTI
175  eclass_addmethod(c->pdClass, (method)in_return_signal, "return_signal", A_CANT, 0);
176 
177  eclass_addmethod(c->pdClass, (method)in_bang, "bang", A_NULL, 0L);
178  eclass_addmethod(c->pdClass, (method)in_float, "float", A_FLOAT, 0L);
179  eclass_addmethod(c->pdClass, (method)in_list, "list", A_GIMME, 0L);
180  // eclass_addmethod(c->pdClass, (method)NULL, "loadbang", A_NULL, 0L);
181 #endif
182 #endif
183 
184  // no class_dspinit : it is done in wrapTTModularClassAsMaxClass for AUDIO_EXTERNAL
185 }
186 
187 #pragma mark -
188 #pragma mark Object life
189 
190 void WrappedInputClass_new(TTPtr self, long argc, t_atom *argv)
191 {
193  long attrstart = attr_args_offset(argc, argv); // support normal arguments
194  TTString sInstance;
195  TTValue v;
196 
197  // Prepare extra data
198  x->extra = (t_extra*)malloc(sizeof(t_extra));
199 
200  // Get input instance symbol
201  if (attrstart && argv) {
202 
203  jamoma_ttvalue_from_Atom(v, _sym_nothing, attrstart, argv);
204 
205  v.toString();
206  sInstance = TTString(v[0]);
207  EXTRA->instance = TTSymbol(sInstance.data());
208  }
209  else
210  EXTRA->instance = kTTSymEmpty;
211 
212  // set no model or view by default
213  EXTRA->modelOrView = NULL;
214 
215  // Create Input Object and one outlet
216  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr));
217 
218 #ifdef J_IN_TILDE
219  jamoma_input_create_audio((t_object*)x, x->wrappedObject);
220 
221  dsp_setup((t_pxobject *)x, 1);
222  x->obj.z_misc = Z_NO_INPLACE | Z_PUT_FIRST;
223 
224  outlet_new((t_pxobject *)x, "signal");
225 
226 #endif
227 
228 #ifdef J_IN_MULTI
229 
230  jamoma_input_create_audio((t_object*)x, x->wrappedObject);
231 
232  x->outlets[0] = outlet_new(x, 0L);
233 #endif
234 
235 #ifndef J_IN_TILDE
236 #ifndef J_IN_MULTI
237  jamoma_input_create((t_object*)x, x->wrappedObject);
238 
239  x->outlets[0] = outlet_new((t_object*)x, 0L);
240 #endif
241 #endif
242 
243  // handle attribute args
244  attr_args_process(x, argc, argv);
245 
246  // The following must be deferred because we have to interrogate our box,
247  // and our box is not yet valid until we have finished instantiating the object.
248  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
249  // in_subscribe(x);
250 // defer_low((t_object*)x, (method)in_subscribe, NULL, 0, NULL);
251 }
252 
254 {
256 
257 #ifdef J_IN_TILDE
258  dsp_free((t_pxobject *)x); // Always call dsp_free first in this routine
259 #endif
260 
261  //x->wrappedObject.set("outputAddress", kTTAdrsEmpty);
262 }
263 
264 #pragma mark -
265 #pragma mark NodeLib association
266 
267 void in_subscribe(TTPtr self)
268 {
270  TTAddress signalAddress;
271  TTAddress inputAddress;
272  TTAddress outputAddress;
273  TTValue v, args;
274  TTNodePtr returnedNode = NULL;
275  TTNodePtr returnedContextNode = NULL;
276  TTAddress returnedAddress, parentAddress;
277  TTString formatDescription, sInstance;
278 
279 #ifdef J_IN_TILDE
280  signalAddress = TTAddress("audio");
281 #endif
282 
283 #ifdef J_IN_MULTI
284  signalAddress = TTAddress("audio");
285 #endif
286 
287 #ifndef J_IN_TILDE
288 #ifndef J_IN_MULTI
289  signalAddress = TTAddress("data");
290 #endif
291 #endif
292 
293  // edit "signal/in.instance" address
294  inputAddress = signalAddress.appendAddress(TTAddress("in")).appendInstance(EXTRA->instance);
295 
296  // if the subscription is successful
297  if (!jamoma_subscriber_create((t_eobj*)x, x->wrappedObject, inputAddress, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) {
298 
299  // get patcher
300  x->patcherPtr = ((t_eobj*)x)->o_canvas;
301 
302  // update instance symbol in case of duplicate instance
303  EXTRA->instance = returnedAddress.getInstance();
304 
305  // observe /parent/out address in order to link/unlink with an Input object below
306  returnedNode->getParent()->getAddress(parentAddress);
307  outputAddress = parentAddress.appendAddress(TTAddress("out")).appendInstance(EXTRA->instance);
308  x->wrappedObject.set(TTSymbol("outputAddress"), outputAddress);
309 
310  // get model or view object
311  if (!EXTRA->modelOrView)
312  jamoma_patcher_get_model_or_view(x->patcherPtr, &EXTRA->modelOrView);
313 
314  // notify the model there is something new concerning signal processing
315  if (EXTRA->modelOrView)
316  object_method_typed(EXTRA->modelOrView, gensym("input_created"), NULL, 0, NULL);
317  }
318 }
319 
320 #pragma mark -
321 #pragma mark Methods bound to input/inlets
322 
323 // Method for Assistance Messages
324 void in_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
325 {
326  if (msg==1) // Inlets
327  strcpy(dst, "(signal) input of the model");
328  else if (msg==2) { // Outlets
329  if (arg == 0)
330  strcpy(dst, "(signal) connect to the algorithm");
331  else
332  strcpy(dst, "dumpout");
333  }
334 }
335 
336 #ifdef J_IN_TILDE
337 #pragma mark -
338 #pragma mark Methods relating to audio processing
339 
340 // Perform Method 64 bit - just pass the whole vector straight through
341 // (the work is all done in the dsp 64 bit method)
342 void in_perform64(TTPtr self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
343 {
346 
347  if (anInput)
348  anInput->process(ins[0], outs[0], sampleframes);
349 }
350 
351 
352 // DSP64 method
353 void in_dsp64(TTPtr self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
354 {
357 
358  if (anInput) {
359  anInput->setupAudioSignals(maxvectorsize);
360  object_method(dsp64, gensym("dsp_add64"), x, in_perform64, 0, NULL);
361  }
362 }
363 #endif
364 
365 #ifdef J_IN_MULTI
366 #pragma mark -
367 #pragma mark Methods relating to audiograph processing
368 
369 void in_reset(TTPtr self)
370 {
373 
374  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTInputAudio members
375  // fell free to change everything if needed !
376 
377  // clear the internal signal in used to get signal from outside the model
378  TTAudioGraphObjectBasePtr(anInput->mSignalIn.instance())->resetAudio();
379 
380  /* ??? : do we clear each internal signal cached or do we supposed they are cleared by their owner ?
381  if (anInput->mSignalCache) {
382 
383  for (anInput->mSignalCache->begin(); anInput->mSignalCache->end(); anInput->mSignalCache->next()) {
384  TTAudioGraphObjectBasePtr sentSignal = TTAudioSignalPtr((TTObjectBasePtr)anInput->mSignalCache->current()[0]);
385 
386  if (sentSignal)
387  sentSignal->resetAudio();
388  }
389  }
390  */
391 
392  // clear the internal signal out used to forward signal into the model
393  TTAudioGraphObjectBasePtr(anInput->mSignalOut.instance())->resetAudio();
394 }
395 
396 void in_setup(TTPtr self)
397 {
400 
401  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTInputAudio members
402  // fell free to change everything if needed !
403 
404  t_atom a[2];
405 
406  // forward the internal signal out to connect it to any audiograph object below the j.in=
407  atom_setobj(a+0, (t_object*)anInput->mSignalOut.instance());
408  atom_setlong(a+1, 0);
409  outlet_anything(x->outlets[signal_out], gensym("audio.connect"), 2, a);
410 }
411 
412 void in_connect(TTPtr self, TTAudioGraphObjectBasePtr audioSourceObject, long sourceOutletNumber)
413 {
416 
417  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTInputAudio members
418  // fell free to change everything if needed !
419 
420  // connect the source to the internal signal in
421  TTAudioGraphObjectBasePtr(anInput->mSignalIn.instance())->connectAudio(audioSourceObject, sourceOutletNumber);
422 
423  /* ??? : do we need to connect each internal signal cache to the signal in
424  if (anInput->mSignalCache) {
425 
426  for (anInput->mSignalCache->begin(); anInput->mSignalCache->end(); anInput->mSignalCache->next()) {
427  TTAudioGraphObjectBasePtr sentSignal = TTAudioSignalPtr((TTObjectBasePtr)anInput->mSignalCache->current()[0]);
428 
429  if (sentSignal)
430  anInput->mSignalIn->connectAudio(sentSignal, ?);
431  }
432  }
433  */
434 
435  // ??? : do we need to connect the internal signal in to the internal signal out
436  //TTAudioGraphObjectBasePtr(anInput->mSignalOut)->connectAudio(anInput->mSignalIn, ?);
437 }
438 #endif
439 
440 #ifndef J_IN_TILDE
441 #ifndef J_IN_MULTI
442 #pragma mark -
443 #pragma mark Methods relating to any data processing
444 
445 void in_bang(TTPtr self)
446 {
447  in_list(self, _sym_bang, 0, NULL);
448 }
449 
450 void in_float(TTPtr self, t_float value)
451 {
452  t_atom a;
453 
454  atom_setfloat(&a, value);
455  in_list(self, _sym_float, 1, &a);
456 }
457 
458 void in_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
459 {
461 
462  jamoma_input_send(x->wrappedObject, msg, argc, argv);
463 }
464 
465 void in_return_signal(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
466 {
468 
469  // avoid blank before data
470  if (msg == _sym_nothing)
471  outlet_anything((t_outlet*)x->outlets[signal_out], NULL, argc, argv);
472  else
473  outlet_anything((t_outlet*)x->outlets[signal_out], msg, argc, argv);
474 }
475 #endif
476 #endif
477 
478 void WrappedInputClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
479 {
481 
482  // route any message to the model
483 // if (msg != _sym_nothing && msg != _sym_jit_matrix && msg != _sym_jit_gl_texture && msg != _sym_dictionary) {
484  if (msg != _sym_nothing ) {
485 
486  // get model or view object
487  if (!EXTRA->modelOrView)
488  jamoma_patcher_get_model_or_view(x->patcherPtr, &EXTRA->modelOrView);
489 
490  zgetfn((t_pd*)x,msg)((t_object*)EXTRA->modelOrView, argc, argv, NULL);
491 // object_method_typed(EXTRA->modelOrView, msg, argc, argv, NULL);
492  return;
493  }
494 
495  jamoma_input_send(x->wrappedObject, msg, argc, argv);
496 }
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
Definition: TTAddress.h:167
TTObject subscriberObject
The instance of a TTSubscriber object used to register the wrapped object in the tree structure...
void WrappedInputClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
anything else handler for j.in
TTSymbol & getInstance()
Get the instance part.
Definition: TTAddress.h:124
TTHandle outlets
an array of outlet
void process(TTSampleValue *anInputSampleVector, TTSampleValue *anOutputSampleVector, TTUInt16 aVectorSize)
Called by the perform method in j.in~ to pass the samples in from the outside world Will also be call...
void WrapTTInputClass(WrappedClassPtr c)
Wrap the j.in class as a Max object.
TTString toString(TTBoolean quotes=YES) const
Return the content as a single string with spaces between elements.
Definition: TTValue.h:351
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
void in_return_signal(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Method used to pass messages from the module outlet.
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
TTAddress appendInstance(const TTSymbol anInstance)
Return a new TTAddress with a instance part.
Definition: TTAddress.h:173
t_object * patcherPtr
the patcher in which the external is (ignoring subpatcher)
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
void in_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
list handler for j.in
void in_bang(TTPtr self)
bang handler for j.in
t_object obj
Max control object header.
TTErr set(const TTSymbol aName, T aValue)
Set an attribute value for an object.
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
void WrappedInputClass_free(TTPtr self)
Wrapper for the j.in deconstructor class, called when an instance is destroyed.
void in_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
Assistance Method.
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
void WrappedInputClass_new(TTPtr self, long argc, t_atom *argv)
Wrapper for the j.in constructor class, called when an instance is created.
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 in_subscribe(TTPtr self)
Associate j.in(~) with NodeLib.
Wraps Jamoma Core classes as objects for PureData.
TTErr getAddress(TTAddress &returnedAddress, TTAddress from=kTTAdrsEmpty)
Get the address of the node.
Definition: TTNode.cpp:478
Data Structure for this object.
The TTAudioGraphObjectBase wraps a TTDSP object such that it is possible to build a dynamic graph of ...
TTErr JAMOMA_EXPORT jamoma_input_send(TTObject &anInput, t_symbol *msg, long argc, const t_atom *argv)
Send any signal to a TTInput object.
void setupAudioSignals(TTUInt16 aVectorSize)
Used e.g.
Definition: TTInputAudio.h:46
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
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...
The TTString class is used to represent a string.
Definition: TTString.h:34
TTErr JAMOMA_EXPORT jamoma_input_create_audio(t_object *x, TTObject &returnedInput)
Create a #TTInput object for audio signal.
WrappedModularInstance * WrappedModularInstancePtr
Pointer to a wrapped instance of our object.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTNodePtr getParent()
Get a pointer to the parent node of the node.
Definition: TTNode.cpp:296
void in_float(TTPtr self, t_float value)
float handler for j.in
TTErr wrapTTModularClassAsPdClass(TTSymbol &ttblueClassName, const char *pdClassName, WrappedClassPtr *c, ModularSpec *specificities)
Wrap a Jamoma class as a Pd class.
TTErr JAMOMA_EXPORT jamoma_input_create(t_object *x, TTObject &returnedInput)
Create a #TTInput object for signal.
void JAMOMA_EXPORT jamoma_patcher_get_model_or_view(t_object *patcher, t_object **returnedModelOrView)
Get j.model or j.view of a patcher.
An audio input component for Jamoma models.
Definition: TTInputAudio.h:23