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