Jamoma API  0.6.0.a19
Max/source/j.out/j.out.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup implementationMaxExternals
4  *
5  * @brief j.out & j.out~ & j.out= - Manage control and audio outputs for a Jamoma model
6  *
7  * @details
8  *
9  * @authors Timothy Place, ThŽo de la Hogue, Trond Lossius
10  *
11  * @copyright © 2008 by Timothy Place and 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 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; ///< Output instance symbol
26 
27 } t_extra;
28 #define EXTRA ((t_extra*)x->extra)
29 
30 
31 // Definitions
32 
33 /** Wrap the j.out class as a Max object.
34  @param c The class to be wrapped
35  @see WrappedOutputClass_new, WrappedOutputClass_free
36  */
37 void WrapTTOutputClass(WrappedClassPtr c);
38 
39 /** Wrapper for the j.out 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 WrappedOutputClass_free, out_subscribe
44  */
45 void WrappedOutputClass_new(TTPtr self, long argc, t_atom* argv);
46 
47 /** Wrapper for the j.out deconstructor class, called when an instance is destroyed.
48  @param self Pointer to this object.
49  @see WrappedOutputClass_new
50  */
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 out_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst);
61 
62 /** Associate j.out(~) with NodeLib. This is a prerequisit for communication with other Jamoma object in the module and beyond. */
63 void out_subscribe(TTPtr self);
64 
65 //TODO : void out_register_preview(t_out *x, void *preview_object) { x->preview_object = preview_object; }
66 
67 #ifdef J_OUT_TILDE
68 
69 /** j.out~ 64-bit MSP perform method (for Max 6). Only defined for j.out~. */
70 void out_perform64(TTPtr self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam);
71 
72 /** j.out~ 64-bit DSP method (for Max 6). Only defined for j.out~. */
73 void out_dsp64(TTPtr self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags);
74 
75 #endif
76 
77 #ifdef J_OUT_MULTI
78 
79 /** reset audiogrpaph setup of the wrapped object
80  @param self Pointer to this object.
81  */
82 void out_reset(TTPtr self);
83 
84 /** reset audiogrpaph setup of the wrapped object
85  @param self Pointer to this object.
86  */
87 void out_setup(TTPtr self);
88 
89 /** reset audiogrpaph setup of the wrapped audiograph object
90  @param self Pointer to this audiograph object.
91  @param audioSourceObject The audiograph object to connect with.
92  @param sourceOutletNumber The number of channel the source audiograph object have.
93  */
94 void out_connect(TTPtr self, TTAudioGraphObjectBasePtr audioSourceObject, long sourceOutletNumber);
95 #endif
96 
97 #ifndef J_OUT_TILDE
98 #ifndef J_OUT_MULTI
99 
100 /** bang handler for j.out
101  @param self Pointer to this object.
102  @see out_int, out_float, out_list, WrappedOutputClass_anything
103  */
104 void out_bang(TTPtr self);
105 
106 /** int handler for j.out
107  @param self Pointer to this object.
108  @param value The value sent to this object.
109  @see out_bang, out_float, out_list, WrappedOutputClass_anything
110  */
111 void out_int(TTPtr self, long value);
112 
113 /** float handler for j.out
114  @param self Pointer to this object.
115  @param value The value sent to this object.
116  @see out_bang, out_int, out_list, WrappedOutputClass_anything
117  */
118 void out_float(TTPtr self, double value);
119 
120 /** list handler for j.out
121  @param self Pointer to this object.
122  @param msg The message sent to this object.
123  @param argc The number of arguments passed to the object.
124  @param argv Pointer to an array of atoms passed to the object.
125  @see out_bang, out_int, out_float, WrappedOutputClass_anything
126  */
127 void out_list(TTPtr self, t_symbol* msg, long argc, t_atom* argv);
128 
129 /** anything else handler for j.out
130  @param self Pointer to this object.
131  @param msg The message sent to this object.
132  @param argc The number of arguments passed to the object.
133  @param argv Pointer to an array of atoms passed to the object.
134  @see out_bang, out_int, out_float, out_list
135  */
136 void WrappedOutputClass_anything(TTPtr self, t_symbol* msg, long argc, t_atom* argv);
137 
138 /** Method used to pass message to the module outlet
139  @param self Pointer to this object.
140  @param msg The message sent to this object.
141  @param argc The number of arguments passed to the object.
142  @param argv Pointer to an array of atoms passed to the object.
143  */
144 void out_return_signal(TTPtr self, t_symbol* msg, long argc, t_atom* argv);
145 
146 #endif
147 #endif
148 
149 #pragma mark -
150 #pragma mark main
151 
152 int C74_EXPORT main(void)
153 {
154  ModularSpec *spec = new ModularSpec;
155  spec->_wrap = &WrapTTOutputClass;
156  spec->_new = &WrappedOutputClass_new;
157  spec->_free = &WrappedOutputClass_free;
158 
159 #ifdef J_OUT_TILDE
160  spec->_any = NULL;
161  return wrapTTModularClassAsMaxClass(kTTSym_OutputAudio, "j.out~", NULL, spec);
162 #endif
163 
164 #ifdef J_OUT_MULTI
165  spec->_any = NULL;
166  return wrapTTModularClassAsMaxClass(kTTSym_OutputAudio, "j.out=", NULL, spec);
167 #endif
168 
169 #ifndef J_OUT_TILDE
170 #ifndef J_OUT_MULTI
171  spec->_any = &WrappedOutputClass_anything;
172  return wrapTTModularClassAsMaxClass(kTTSym_Output, "j.out", NULL, spec);
173 #endif
174 #endif
175 }
176 
177 void WrapTTOutputClass(WrappedClassPtr c)
178 {
179  class_addmethod(c->maxClass, (method)out_assist, "assist", A_CANT, 0L);
180 
181 #ifdef J_OUT_TILDE
182  class_addmethod(c->maxClass, (method)out_dsp64, "dsp64", A_CANT, 0);
183 #endif
184 
185 #ifdef J_OUT_MULTI
186  class_addmethod(c->maxClass, (method)out_reset, "audio.reset", A_CANT, 0);
187  class_addmethod(c->maxClass, (method)out_setup, "audio.setup", A_CANT, 0);
188  class_addmethod(c->maxClass, (method)out_connect, "audio.connect", A_OBJ, A_LONG, 0);
189 #endif
190 
191 #ifndef J_OUT_TILDE
192 #ifndef J_OUT_MULTI
193  class_addmethod(c->maxClass, (method)out_return_signal, "return_signal", A_CANT, 0);
194 
195  class_addmethod(c->maxClass, (method)out_bang, "bang", 0L);
196  class_addmethod(c->maxClass, (method)out_int, "int", A_LONG, 0L);
197  class_addmethod(c->maxClass, (method)out_float, "float", A_FLOAT, 0L);
198  class_addmethod(c->maxClass, (method)out_list, "list", A_GIMME, 0L);
199 #endif
200 #endif
201 
202  // no class_dspinit : it is done in wrapTTModularClassAsMaxClass for AUDIO_EXTERNAL
203 
204 }
205 
206 #pragma mark -
207 #pragma mark Object life
208 
209 void WrappedOutputClass_new(TTPtr self, long argc, t_atom* argv)
210 {
212  long attrstart = attr_args_offset(argc, argv); // support normal arguments
213  TTString sInstance;
214  TTValue v;
215 
216  // Prepare extra data
217  x->extra = (t_extra*)malloc(sizeof(t_extra));
218 
219  // Get input instance symbol
220  if (attrstart && argv) {
221 
222  jamoma_ttvalue_from_Atom(v, _sym_nothing, attrstart, argv);
223 
224  v.toString();
225  sInstance = TTString(v[0]);
226  EXTRA->instance = TTSymbol(sInstance.data());
227  }
228  else
229  EXTRA->instance = kTTSymEmpty;
230 
231  // Create Input Object and one outlet
232  x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr));
233 
234 #ifdef J_OUT_TILDE
235  jamoma_output_create_audio((t_object*)x, x->wrappedObject);
236 
237  dsp_setup((t_pxobject *)x, 1);
238  x->obj.z_misc = Z_NO_INPLACE | Z_PUT_FIRST;
239 
240  outlet_new((t_pxobject *)x, "signal");
241 
242 #endif
243 
244 #ifdef J_OUT_MULTI
245  jamoma_output_create_audio((t_object*)x, x->wrappedObject);
246 
247  x->outlets[0] = outlet_new(x, 0L);
248 #endif
249 
250 #ifndef J_OUT_TILDE
251 #ifndef J_OUT_MULTI
252  jamoma_output_create((t_object*)x, x->wrappedObject);
253 
254  x->outlets[0] = outlet_new(x, 0L);
255 #endif
256 #endif
257 
258  // handle attribute args
259  attr_args_process(x, argc, argv);
260 
261  // The following must be deferred because we have to interrogate our box,
262  // and our box is not yet valid until we have finished instantiating the object.
263  // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6)
264  defer_low((t_object*)x, (method)out_subscribe, NULL, 0, NULL);
265 }
266 
268 {
270 
271 #ifdef J_OUT_TILDE
272  dsp_free((t_pxobject *)x); // Always call dsp_free first in this routine
273 #endif
274 
275  //x->wrappedObject.set("inputAddress", kTTAdrsEmpty);
276 }
277 
278 #pragma mark -
279 #pragma mark NodeLib association
280 
282 {
284  TTAddress signalAddress;
285  TTAddress outputAddress;
286  TTAddress inputAddress;
287  TTValue v, args;
288  TTNodePtr returnedNode = NULL;
289  TTNodePtr returnedContextNode = NULL;
290  TTAddress returnedAddress, parentAddress;
291  TTString formatDescription, sInstance;
292  t_object *modelOrView = NULL;
293 
294 #ifdef J_OUT_TILDE
295  signalAddress = TTAddress("audio");
296 #endif
297 
298 #ifdef J_OUT_MULTI
299  signalAddress = TTAddress("audio");
300 #endif
301 
302 #ifndef J_OUT_TILDE
303 #ifndef J_OUT_MULTI
304  signalAddress = TTAddress("data");
305 #endif
306 #endif
307 
308  // edit "signal/out.instance" address
309  outputAddress = signalAddress.appendAddress(TTAddress("out")).appendInstance(EXTRA->instance);
310 
311  // if the subscription is successful
312  if (!jamoma_subscriber_create((t_object*)x, x->wrappedObject, outputAddress, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) {
313 
314  // get patcher
315  x->patcherPtr = jamoma_patcher_get((t_object*)x);
316 
317  // update instance symbol in case of duplicate instance
318  EXTRA->instance = returnedAddress.getInstance();
319 
320  // observe /parent/in address in order to link/unlink with an Input object below
321  returnedNode->getParent()->getAddress(parentAddress);
322  inputAddress = parentAddress.appendAddress(TTAddress("in")).appendInstance(EXTRA->instance);
323  x->wrappedObject.set("inputAddress", inputAddress);
324 
325  // get model or view object
327 
328  // notify the model there is something new concerning signal processing
329  if (modelOrView)
330  object_method_typed(modelOrView, gensym("output_created"), 0, NULL, NULL);
331  }
332 }
333 
334 #pragma mark -
335 #pragma mark Methods bound to input/inlets
336 
337 // Method for Assistance Messages
338 void out_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
339 {
340  if (msg==1) // Inlets
341  strcpy(dst, "(signal) connect to the algorithm");
342  else if (msg==2) { // Outlets
343  if (arg == 0)
344  strcpy(dst, "(signal) output of the model");
345  else
346  strcpy(dst, "dumpout");
347  }
348 }
349 
350 #ifdef J_OUT_TILDE
351 #pragma mark -
352 #pragma mark Methods relating to audio processing
353 
354 // Perform Method 64 bit - just pass the whole vector straight through
355 // (the work is all done in the dsp 64 bit method)
356 void out_perform64(TTPtr self, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
357 {
360 
361  if (anOutput)
362  anOutput->process(ins[0], outs[0], sampleframes);
363 }
364 
365 
366 // DSP64 method
367 void out_dsp64(TTPtr self, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags)
368 {
371 
372  if (anOutput) {
373  anOutput->setupAudioSignals(maxvectorsize, samplerate);
374  object_method(dsp64, gensym("dsp_add64"), x, out_perform64, 0, NULL);
375  }
376 }
377 #endif
378 
379 #ifdef J_OUT_MULTI
380 #pragma mark -
381 #pragma mark Methods relating to audiograph processing
382 
383 void out_reset(TTPtr self)
384 {
387 
388  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTOutputAudio members
389  // fell free to change everything if needed !
390 
391  // clear the internal signal in used to get signal from inside the model
392  TTAudioGraphObjectBasePtr(anOutput->mSignalIn.instance())->resetAudio();
393 
394  // clear the internal signal out used to forward signal outside the model
395  TTAudioGraphObjectBasePtr(anOutput->mSignalOut.instance())->resetAudio();
396 }
397 
398 void out_setup(TTPtr self)
399 {
402 
403  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTOutputAudio members
404  // fell free to change everything if needed !
405 
406  t_atom a[2];
407 
408  // forward the internal signal out to connect it to any audiograph object below the j.out=
409  atom_setobj(a+0, (t_object*)anOutput->mSignalOut.instance());
410  atom_setlong(a+1, 0);
411  outlet_anything(x->outlets[signal_out], gensym("audio.connect"), 2, a);
412 }
413 
414 void out_connect(TTPtr self, TTAudioGraphObjectBasePtr audioSourceObject, long sourceOutletNumber)
415 {
418 
419  // NOTE FOR TIM : all the code below is a try and it's also a way to show you how to access to #TTOutputAudio members
420  // fell free to change everything if needed !
421 
422  // connect the source to the internal signal in
423  TTAudioGraphObjectBasePtr(anOutput->mSignalIn.instance())->connectAudio(audioSourceObject, sourceOutletNumber);
424 
425  // ??? : do we need to connect the internal signal in to the internal signal out
426  //TTAudioGraphObjectBasePtr(anOutput->mSignalOut.instance())->connectAudio(anOutput->mSignalIn, ?);
427 }
428 #endif
429 
430 #ifndef J_OUT_TILDE
431 #ifndef J_OUT_MULTI
432 #pragma mark -
433 #pragma mark Methods relating to any data processing
434 
435 void out_bang(TTPtr self)
436 {
437  out_list(self, _sym_bang, 0, NULL);
438 }
439 
440 void out_int(TTPtr self, long value)
441 {
442  t_atom a;
443 
444  atom_setlong(&a, value);
445  out_list(self, _sym_int, 1, &a);
446 }
447 
448 void out_float(TTPtr self, double value)
449 {
450  t_atom a;
451 
452  atom_setfloat(&a, value);
453  out_list(self, _sym_float, 1, &a);
454 }
455 
456 void out_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
457 {
459 
460  jamoma_output_send(x->wrappedObject, msg, argc, argv);
461 }
462 
463 void WrappedOutputClass_anything(TTPtr self, t_symbol* msg, long argc, t_atom* argv)
464 {
466 
467  jamoma_output_send(x->wrappedObject, msg, argc, argv);
468 }
469 
470 void out_return_signal(TTPtr self, t_symbol* msg, long argc, t_atom* argv)
471 {
473 
474  // avoid blank before data
475  if (msg == _sym_nothing)
476  outlet_atoms(x->outlets[signal_out], argc, argv);
477  else
478  outlet_anything(x->outlets[signal_out], msg, argc, argv);
479 }
480 #endif
481 #endif
void WrappedOutputClass_anything(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
anything else handler for j.out
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
Definition: TTAddress.h:167
int C74_EXPORT main(void)
Set up this class as a Max external the first time an object of this kind is instantiated.
TTObject subscriberObject
The instance of a TTSubscriber object used to register the wrapped object in the tree structure...
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 out_int(TTPtr self, long value)
int handler for j.out
TTString toString(TTBoolean quotes=YES) const
Return the content as a single string with spaces between elements.
Definition: TTValue.h:351
void out_subscribe(TTPtr self)
Associate j.out(~) with NodeLib.
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 WrappedOutputClass_free(TTPtr self)
Wrapper for the j.out deconstructor class, called when an instance is destroyed.
TTErr JAMOMA_EXPORT jamoma_output_send(TTObject &anOutput, t_symbol *msg, long argc, const t_atom *argv)
Send any signal to a TTOutput object.
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 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 out_assist(TTPtr self, TTPtr b, long msg, long arg, char *dst)
Assistance Method.
TTErr JAMOMA_EXPORT jamoma_output_create(t_object *x, TTObject &returnedOutput)
Create a TTOutput object for signal.
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
void WrappedOutputClass_new(TTPtr self, long argc, t_atom *argv)
Wrapper for the j.out constructor class, called when an instance is created.
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 WrapTTOutputClass(WrappedClassPtr c)
Wrap the j.out class as a Max object.
TTObject wrappedObject
The instance of the Jamoma object we are wrapping.
void out_list(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
list handler for j.out
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 out_bang(TTPtr self)
bang handler for j.out
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_output_create_audio(t_object *x, TTObject &returnedOutput)
Create an output object for audio signal.
Wraps Jamoma Core classes as objects for Max/MSP.
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
An audio output component for Jamoma models.
Definition: TTOutputAudio.h:23
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 out_return_signal(TTPtr self, t_symbol *msg, long argc, t_atom *argv)
Method used to pass message to the module outlet.
void JAMOMA_EXPORT jamoma_patcher_get_model_or_view(t_object *patcher, t_object **returnedModelOrView)
Get j.model or j.view of a patcher.
void out_float(TTPtr self, double value)
float handler for j.out