Jamoma API  0.6.0.a19
TTClassWrapperMax.cpp
1 /*
2  * TTClassWrapperMax
3  * An automated class wrapper to make Jamoma objects available as objects for Max/MSP
4  * Copyright � 2008 by Timothy Place
5  *
6  * License: This code is licensed under the terms of the "New BSD License"
7  * http://creativecommons.org/licenses/BSD/
8  */
9 
10 #include "TTClassWrapperMax.h"
11 #include "ext_hashtab.h"
12 #include "TTCallback.h"
13 #ifdef MAC_VERSION
14 #include <dlfcn.h>
15 #endif
16 
17 extern "C" void wrappedClass_receiveNotificationForOutlet(WrappedInstancePtr self, TTValue& arg);
18 
19 
20 /** A hash of all wrapped clases, keyed on the Max class name. */
21 static t_hashtab* wrappedMaxClasses = NULL;
22 
23 
24 t_object* wrappedClass_new(t_symbol* name, long argc, t_atom* argv)
25 {
26  WrappedClass* wrappedMaxClass = NULL;
27  WrappedInstancePtr x = NULL;
28  TTValue sr(sys_getsr());
29  TTValue v, none;
30  long attrstart = attr_args_offset(argc, argv); // support normal arguments
31  TTErr err = kTTErrNone;
32 
33  // Find the WrappedClass
34  hashtab_lookup(wrappedMaxClasses, name, (t_object**)&wrappedMaxClass);
35 
36  // If the WrappedClass has a validity check defined, then call the validity check function.
37  // If it returns an error, then we won't instantiate the object.
38  if (wrappedMaxClass) {
39  if (wrappedMaxClass->validityCheck)
40  err = wrappedMaxClass->validityCheck(wrappedMaxClass->validityCheckArgument);
41  else
42  err = kTTErrNone;
43  }
44  else
45  err = kTTErrGeneric;
46 
47  if (!err)
48  x = (WrappedInstancePtr)object_alloc(wrappedMaxClass->maxClass);
49  if (x) {
50  x->wrappedClassDefinition = wrappedMaxClass;
51  x->maxNumChannels = 2; // An initial argument to this object will set the maximum number of channels
52  if (attrstart && argv)
53  x->maxNumChannels = atom_getlong(argv);
54 
55  ttEnvironment->setAttributeValue(kTTSym_sampleRate, sr);
56 
57  if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("numChannelsUseFixedRatioInputsToOutputs"), v)) {
58  TTUInt16 inputs;
59  TTUInt16 outputs;
60 
61  inputs = v[0];
62  outputs = v[1];
63  x->numInputs = x->maxNumChannels * inputs;
64  x->numOutputs = x->maxNumChannels * outputs;
65  }
66  else if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("fixedNumChannels"), v)) {
67  TTUInt16 numChannels;
68 
69  numChannels = v[0];
70  x->numInputs = numChannels;
71  x->numOutputs = numChannels;
72  }
73  else if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("fixedNumOutputChannels"), v)) {
74  TTUInt16 numChannels;
75 
76  numChannels = v[0];
77  x->numInputs = x->maxNumChannels;
78  x->numOutputs = numChannels;
79  }
80  else {
81  x->numInputs = x->maxNumChannels;
82  x->numOutputs = x->maxNumChannels;
83  }
84 
85  if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("additionalSignalInputSetsAttribute"), v)) {
86  x->numControlSignals = v.size();
87  x->controlSignalNames = new TTSymbol[x->numControlSignals];
88  for (TTUInt16 i=0; i<x->numControlSignals; i++) {
89  x->numInputs++;
90  x->controlSignalNames[i] = v[i];
91  }
92  }
93 
94  x->wrappedObject = new TTAudioObject(wrappedMaxClass->ttblueClassName, x->maxNumChannels);
95  x->audioIn = new TTAudio(x->numInputs);
96  x->audioOut = new TTAudio(x->numOutputs);
97  attr_args_process(x,argc,argv); // handle attribute args
98  object_obex_store((void *)x, _sym_dumpout, (object *)outlet_new(x,NULL)); // dumpout
99 
100 
101  dsp_setup((t_pxobject *)x, x->numInputs); // inlets
102 
103  //if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("numControlOutlets"), v))
104  // v.get(0, numControlOutlets);
105  if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("controlOutletFromNotification"), v)) {
106  TTUInt16 outletIndex = 0;
107  TTSymbol notificationName;
108 
109  outletIndex = v[0];
110  notificationName = v[1];
111 
112  // TODO: to support more than one notification->outlet we need see how many args are actually passed-in
113  // and then we need to track them in a hashtab or something...
114 
115  x->controlOutlet = outlet_new((t_pxobject*)x, NULL);
116 
117  x->controlCallback = new TTObject("callback");
118  x->controlCallback->set("function", TTPtr(&wrappedClass_receiveNotificationForOutlet));
119  x->controlCallback->set("baton", TTPtr(x));
120 
121  // dynamically add a message to the callback object so that it can handle the 'objectFreeing' notification
122  x->controlCallback->instance()->registerMessage(notificationName, (TTMethod)&TTCallback::notify, kTTMessagePassValue);
123 
124  // tell the source that is passed in that we want to watch it
125  x->wrappedObject->registerObserverForNotifications(*x->controlCallback);
126 
127  }
128 
129  for (short i=0; i < x->numOutputs; i++)
130  outlet_new((t_pxobject *)x, "signal"); // outlets
131 
132 
133  x->obj.z_misc = Z_NO_INPLACE;
134  }
135  return (t_object*)x;
136 }
137 
138 
139 void wrappedClass_free(WrappedInstancePtr x)
140 {
141  dsp_free((t_pxobject *)x);
142  delete x->wrappedObject;
143  delete x->audioIn;
144  delete x->audioOut;
145  delete[] x->controlSignalNames;
146 }
147 
148 
149 void wrappedClass_receiveNotificationForOutlet(WrappedInstancePtr self, TTValue& arg)
150 {
151  TTString string = arg[0];
152  t_symbol* s = gensym((char*)string.c_str());
153 
154  outlet_anything(self->controlOutlet, s, 0, NULL);
155 }
156 
157 
158 t_max_err wrappedClass_attrGet(TTPtr self, t_object* attr, long* argc, t_atom** argv)
159 {
160  t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname);
161  TTValue v;
162  long i;
164  TTPtr rawpointer;
165  t_max_err err;
166 
167  err = hashtab_lookup(x->wrappedClassDefinition->maxNamesToTTNames, attrName, (t_object**)&rawpointer);
168  if (err)
169  return err;
170 
171  TTSymbol ttAttrName(rawpointer);
172 
173  x->wrappedObject->get(ttAttrName, v);
174 
175  *argc = v.size();
176  if (!(*argv)) // otherwise use memory passed in
177  *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * v.size());
178 
179  for (i=0; i < (TTInt32) v.size(); i++) {
180  if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64) {
181  TTFloat64 value;
182  value = v[i];
183  atom_setfloat(*argv+i, value);
184  }
185  else if (v[i].type() == kTypeSymbol) {
186  TTSymbol value;
187  value = v[i];
188  atom_setsym(*argv+i, gensym((char*)value.c_str()));
189  }
190  else { // assume int
191  TTInt32 value;
192  value = v[i];
193  atom_setlong(*argv+i, value);
194  }
195  }
196  return MAX_ERR_NONE;
197 }
198 
199 
200 t_max_err wrappedClass_attrSet(TTPtr self, t_object* attr, long argc, t_atom* argv)
201 {
203 
204  if (argc && argv) {
205  t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname);
206  TTValue v;
207  long i;
208  t_max_err err;
209  TTPtr ptr = NULL;
210 
211  err = hashtab_lookup(x->wrappedClassDefinition->maxNamesToTTNames, attrName, (t_object**)&ptr);
212  if (err)
213  return err;
214 
215  TTSymbol ttAttrName(ptr);
216 
217  v.resize(argc);
218  for (i=0; i<argc; i++) {
219  if (atom_gettype(argv+i) == A_LONG)
220  v[i] = (TTInt32)atom_getlong(argv+i);
221  else if (atom_gettype(argv+i) == A_FLOAT)
222  v[i] = atom_getfloat(argv+i);
223  else if (atom_gettype(argv+i) == A_SYM)
224  v[i] = TT(atom_getsym(argv+i)->s_name);
225  else
226  object_error((t_object*)x, "bad type for attribute setter");
227  }
228  x->wrappedObject->set(ttAttrName, v);
229  return MAX_ERR_NONE;
230  }
231  return MAX_ERR_GENERIC;
232 }
233 
234 
235 void wrappedClass_anything(TTPtr self, t_symbol* s, long argc, t_atom* argv)
236 {
238  TTSymbol ttName;
239  t_max_err err;
240  TTValue v_in;
241  TTValue v_out;
242 
243  err = hashtab_lookup(x->wrappedClassDefinition->maxNamesToTTNames, s, (t_object**)&ttName);
244  if (err) {
245  object_post((t_object*)x, "no method found for %s", s->s_name);
246  return;
247  }
248 
249  if (argc && argv) {
250  v_in.resize(argc);
251  for (long i=0; i<argc; i++) {
252  if (atom_gettype(argv+i) == A_LONG)
253  v_in[i] = (TTInt32)atom_getlong(argv+i);
254  else if (atom_gettype(argv+i) == A_FLOAT)
255  v_in[i] = atom_getfloat(argv+i);
256  else if (atom_gettype(argv+i) == A_SYM)
257  v_in[i] = TT(atom_getsym(argv+i)->s_name);
258  else
259  object_error((t_object*)x, "bad type for message arg");
260  }
261  }
262  x->wrappedObject->send(ttName, v_in, v_out);
263 
264  // process the returned value for the dumpout outlet
265  {
266  long ac = v_out.size();
267 
268  if (ac) {
269  t_atom* av = (t_atom*)malloc(sizeof(t_atom) * ac);
270 
271  for (long i=0; i<ac; i++) {
272  if (v_out[0].type() == kTypeSymbol) {
273  TTSymbol ttSym;
274  ttSym = v_out[i];
275  atom_setsym(av+i, gensym((char*)ttSym.c_str()));
276  }
277  else if (v_out[0].type() == kTypeFloat32 || v_out[0].type() == kTypeFloat64) {
278  TTFloat64 f = 0.0;
279  f = v_out[i];
280  atom_setfloat(av+i, f);
281  }
282  else {
283  TTInt32 l = 0;
284  l = v_out[i];
285  atom_setfloat(av+i, l);
286  }
287  }
288  object_obex_dumpout(self, s, ac, av);
289  free(av);
290  }
291  }
292 }
293 
294 
295 // Method for Assistance Messages
296 void wrappedClass_assist(WrappedInstancePtr self, void *b, long msg, long arg, char *dst)
297 {
298  if (msg==1) { // Inlets
299  if (arg==0)
300  strcpy(dst, "signal input, control messages"); //leftmost inlet
301  else {
302  if (arg > self->numInputs-self->numControlSignals-1)
303  //strcpy(dst, "control signal input");
304  snprintf(dst, 256, "control signal for \"%s\"", self->controlSignalNames[arg - self->numInputs+1].c_str());
305  else
306  strcpy(dst, "signal input");
307  }
308  }
309  else if (msg==2) { // Outlets
310  if (arg < self->numOutputs)
311  strcpy(dst, "signal output");
312  else
313  strcpy(dst, "dumpout"); //rightmost outlet
314  }
315 }
316 
317 
318 void wrappedClass_perform64(WrappedInstancePtr self, t_object* dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
319 {
320  TTUInt16 i;
321  //TTUInt16 numChannels = numouts;
322 
323  self->numChannels = numouts; // <-- this is kinda lame, but for the time being I think we can get away with this assumption...
324 
325  for (i=0; i < self->numControlSignals; i++) {
326  int signal_index = self->numInputs - self->numControlSignals + i;
327 
328  if (self->signals_connected[signal_index])
329  self->wrappedObject->set(self->controlSignalNames[i], *ins[signal_index]);
330  }
331 
332  self->audioIn->setNumChannels(self->numInputs-self->numControlSignals);
333  self->audioOut->setNumChannels(self->numOutputs);
334  self->audioOut->allocWithVectorSize(sampleframes);
335 
336  for (i=0; i < self->numInputs-self->numControlSignals; i++)
337  self->audioIn->setVector(i, self->vs, ins[i]);
338 
339  self->wrappedObject->process(self->audioIn, self->audioOut);
340 
341  for (i=0; i < self->numOutputs; i++)
342  self->audioOut->getVectorCopy(i, self->vs, outs[i]);
343 
344 }
345 
346 
347 void wrappedClass_dsp64(WrappedInstancePtr self, t_object* dsp64, short *count, double samplerate, long maxvectorsize, long flags)
348 {
349  for (int i=0; i < (self->numInputs + self->numOutputs); i++)
350  self->signals_connected[i] = count[i];
351 
352  ttEnvironment->setAttributeValue(kTTSym_sampleRate, samplerate);
353  self->wrappedObject->set(TT("sampleRate"), samplerate);
354 
355  self->vs = maxvectorsize;
356 
357  self->audioIn->setVectorSizeWithInt(self->vs);
358  self->audioOut->setVectorSizeWithInt(self->vs);
359 
360  object_method(dsp64, gensym("dsp_add64"), self, wrappedClass_perform64, 0, NULL);
361 }
362 
363 
364 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c)
365 {
366  return wrapTTClassAsMaxClass(ttblueClassName, maxClassName, c, (WrappedClassOptionsPtr)NULL);
367 }
368 
369 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c, WrappedClassOptionsPtr options)
370 {
371  TTObject o(ttblueClassName, 1); // Create a temporary instance of the class so that we can query it.
372  TTValue v;
373  WrappedClass* wrappedMaxClass = NULL;
374  TTSymbol name;
375  TTCString nameCString = NULL;
376  t_symbol* nameMaxSymbol = NULL;
377  TTUInt32 nameSize = 0;
378 
379  common_symbols_init();
380  TTDSPInit();
381 
382  if (!wrappedMaxClasses)
383  wrappedMaxClasses = hashtab_new(0);
384 
385  wrappedMaxClass = new WrappedClass;
386  wrappedMaxClass->maxClassName = gensym((char*)maxClassName);
387  wrappedMaxClass->maxClass = class_new( (char*)maxClassName,
388  (method)wrappedClass_new,
389  (method)wrappedClass_free,
390  sizeof(WrappedInstance),
391  (method)0L,
392  A_GIMME,
393  0);
394  wrappedMaxClass->ttblueClassName = ttblueClassName;
395  wrappedMaxClass->validityCheck = NULL;
396  wrappedMaxClass->validityCheckArgument = NULL;
397  wrappedMaxClass->options = options;
398  wrappedMaxClass->maxNamesToTTNames = hashtab_new(0);
399 
400  if (!o.valid()) {
401  error("Jamoma ClassWrapper failed to load %s", ttblueClassName.c_str());
402  return kTTErrAllocFailed;
403  }
404 
405  o.messages(v);
406  for (TTUInt16 i=0; i<v.size(); i++) {
407  name = v[i];
408  //nameSize = name->getString().length(); // to -- this crash on Windows...
409  nameSize = strlen(name.c_str());
410  nameCString = new char[nameSize+1];
411  strncpy_zero(nameCString, name.c_str(), nameSize+1);
412 
413  nameMaxSymbol = gensym(nameCString);
414  hashtab_store(wrappedMaxClass->maxNamesToTTNames, nameMaxSymbol, (t_object*)name.rawpointer());
415  class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_anything, nameCString, A_GIMME, 0);
416 
417  delete nameCString;
418  nameCString = NULL;
419  }
420 
421  o.attributes(v);
422  for (TTUInt16 i=0; i<v.size(); i++) {
423  TTAttributePtr attr = NULL;
424  t_symbol* maxType = _sym_long;
425 
426  name = v[i];
427  //nameSize = name->getString().length(); // to -- this crash on Windows...
428  nameSize = strlen(name.c_str());
429  nameCString = new char[nameSize+1];
430  strncpy_zero(nameCString, name.c_str(), nameSize+1);
431  nameMaxSymbol = gensym(nameCString);
432 
433  if (name == TT("maxNumChannels"))
434  continue; // don't expose these attributes to Max users
435  if (name == TT("bypass")) {
436  if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("generator"), v))
437  continue; // generators don't have inputs, and so don't really provide a bypass
438  }
439 
440  o.instance()->findAttribute(name, &attr);
441 
442  if (attr->type == kTypeFloat32)
443  maxType = _sym_float32;
444  else if (attr->type == kTypeFloat64)
445  maxType = _sym_float64;
446  else if (attr->type == kTypeSymbol || attr->type == kTypeString)
447  maxType = _sym_symbol;
448 
449  hashtab_store(wrappedMaxClass->maxNamesToTTNames, nameMaxSymbol, (t_object*)name.rawpointer());
450  class_addattr(wrappedMaxClass->maxClass, attr_offset_new(nameCString, maxType, 0, (method)wrappedClass_attrGet, (method)wrappedClass_attrSet, 0));
451 
452  // Add display styles for the Max 5 inspector
453  if (attr->type == kTypeBoolean)
454  CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)name.c_str(), 0, (char*)"onoff");
455  if (name == TT("fontFace"))
456  CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)"fontFace", 0, (char*)"font");
457 
458  delete nameCString;
459  nameCString = NULL;
460  }
461 
462  class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_dsp64, "dsp64", A_CANT, 0L);
463  class_addmethod(wrappedMaxClass->maxClass, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
464  class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_assist, "assist", A_CANT, 0L);
465  class_addmethod(wrappedMaxClass->maxClass, (method)stdinletinfo, "inletinfo", A_CANT, 0);
466 
467  class_dspinit(wrappedMaxClass->maxClass);
468  class_register(_sym_box, wrappedMaxClass->maxClass);
469  if (c)
470  *c = wrappedMaxClass;
471 
472  hashtab_store(wrappedMaxClasses, wrappedMaxClass->maxClassName, (t_object*)wrappedMaxClass);
473  return kTTErrNone;
474 }
475 
476 
477 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c, TTValidityCheckFunction validityCheck)
478 {
479  TTErr err = wrapTTClassAsMaxClass(ttblueClassName, maxClassName, c);
480 
481  if (!err) {
482  (*c)->validityCheck = validityCheck;
483  (*c)->validityCheckArgument = (*c)->maxClass;
484  }
485  return err;
486 }
487 
488 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c, TTValidityCheckFunction validityCheck, WrappedClassOptionsPtr options)
489 {
490  TTErr err = wrapTTClassAsMaxClass(ttblueClassName, maxClassName, c, options);
491 
492  if (!err) {
493  (*c)->validityCheck = validityCheck;
494  (*c)->validityCheckArgument = (*c)->maxClass;
495  }
496  return err;
497 }
498 
499 
500 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c, TTValidityCheckFunction validityCheck, TTPtr validityCheckArgument)
501 {
502  TTErr err = wrapTTClassAsMaxClass(ttblueClassName, maxClassName, c);
503 
504  if (!err) {
505  (*c)->validityCheck = validityCheck;
506  (*c)->validityCheckArgument = validityCheckArgument;
507  }
508  return err;
509 }
510 
511 TTErr wrapTTClassAsMaxClass(TTSymbol ttblueClassName, const char* maxClassName, WrappedClassPtr* c, TTValidityCheckFunction validityCheck, TTPtr validityCheckArgument, WrappedClassOptionsPtr options)
512 {
513  TTErr err = wrapTTClassAsMaxClass(ttblueClassName, maxClassName, c, options);
514 
515  if (!err) {
516  (*c)->validityCheck = validityCheck;
517  (*c)->validityCheckArgument = validityCheckArgument;
518  }
519  return err;
520 }
521 
522 
523 
524 TTErr TTValueFromAtoms(TTValue& v, long ac, t_atom* av)
525 {
526  v.clear();
527 
528  // For now we assume floats for speed (e.g. in the performance sensitive j.unit object)
529  for (int i=0; i<ac; i++)
530  v.append((TTFloat64)atom_getfloat(av+i));
531  return kTTErrNone;
532 }
533 
534 TTErr TTAtomsFromValue(const TTValue& v, long* ac, t_atom** av)
535 {
536  int size = v.size();
537 
538  if (*ac && *av)
539  ; // memory was passed-in from the calling function -- use it
540  else {
541  *ac = size;
542  *av = new t_atom[size];// (t_atom*)sysmem_newptr(sizeof(t_atom) * size);
543  }
544 
545  for (int i=0; i<size; i++) {
546  atom_setfloat((*av)+i, v[i]);
547  }
548  return kTTErrNone;
549 }
550 
551 
552 #include "jit.common.h"
553 
554 /*
555  We cannot count on Jitter matrices being tightly packed.
556  There are alignment issues (rows are aligned to 16-byte boundaries)
557  but there are additional issues, such as when accessing 1-plane of a 4-plane matrix, etc.
558  Jitter is really expecting that any matrix will be broken down into vectors for processing.
559  Jamoma does not make this assumption.
560 
561  Unfortunately, the only way to reliably get what we need into a tightly-packed Jamoma matrix
562  is to do a copy -- and not just a copy but a row-by-row iterative copy.
563 
564  For these reasons, the 'copy' argument is optional, and it defaults to true.
565 
566  NOTE: this function does not do the copying itself!
567  this function references a matrix such that it is setup to serve as a copy.
568 
569  There is also the scenario where the output matrix from the Jamoma object is a different size
570  than the input matrix, and the Jamoma object cannot change the size of a Jitter matrix.
571 */
572 
573 long TTMatrixReferenceJitterMatrix(TTMatrix aMatrix, TTPtr aJitterMatrix, TTBoolean copy)
574 {
575  t_jit_matrix_info jitterMatrixInfo;
576  TTBytePtr jitterMatrixData;
577  long jitterMatrixLock = (long)jit_object_method(aJitterMatrix, _sym_lock, 1);
578  long jitterDimensionCount;
579  TTValue dimensions;
580 
581  jit_object_method(aJitterMatrix, _sym_getinfo, &jitterMatrixInfo);
582  jit_object_method(aJitterMatrix, _sym_getdata, &jitterMatrixData);
583 
584  if (!copy)
585  aMatrix.referenceExternalData(jitterMatrixData);
586 
587  if (jitterMatrixInfo.type == _sym_char)
588  aMatrix.set(kTTSym_type, kTTSym_uint8);
589  else if (jitterMatrixInfo.type == _sym_long)
590  aMatrix.set(kTTSym_type, kTTSym_int32);
591  else if (jitterMatrixInfo.type == _sym_float32)
592  aMatrix.set(kTTSym_type, kTTSym_float32);
593  else if (jitterMatrixInfo.type == _sym_float64)
594  aMatrix.set(kTTSym_type, kTTSym_float64);
595 
596  aMatrix.set(kTTSym_elementCount, (int)jitterMatrixInfo.planecount);
597 
598  jitterDimensionCount = jitterMatrixInfo.dimcount;
599  dimensions.resize(jitterDimensionCount);
600 
601  for (int d=0; d < jitterDimensionCount; d++) {
602  // The first 2 dimensions (rows and columns) are reversed in Jitter as compared to Jamoma
603  if (d == 1)
604  dimensions[0] = (int)jitterMatrixInfo.dim[d];
605  else if (d==0 && jitterDimensionCount>1)
606  dimensions[1] = (int)jitterMatrixInfo.dim[d];
607  else
608  dimensions[d] = (int)jitterMatrixInfo.dim[d];
609  }
610 
611  aMatrix.set(kTTSym_dimensions, dimensions);
612 
613  return jitterMatrixLock;
614 }
615 
616 
617 // Assumes jitter matrix is locked, matrix dimensions agree , and we're ready to go
618 TTErr TTMatrixCopyDataFromJitterMatrix(TTMatrix aMatrix, TTPtr aJitterMatrix)
619 {
620  t_jit_matrix_info jitterMatrixInfo;
621  TTBytePtr jitterMatrixData;
622  TTValue dimensions;
623  int dimcount;
624  TTBytePtr data = aMatrix.getLockedPointer();
625 
626  jit_object_method(aJitterMatrix, _sym_getinfo, &jitterMatrixInfo);
627  jit_object_method(aJitterMatrix, _sym_getdata, &jitterMatrixData);
628 
629  dimcount = jitterMatrixInfo.dimcount;
630 
631  if (dimcount == 1) {
632  memcpy(data, jitterMatrixData, jitterMatrixInfo.dimstride[0] * jitterMatrixInfo.dim[0]);
633  }
634  else if (dimcount == 2) {
635  for (int i=0; i<jitterMatrixInfo.dim[1]; i++) { // step through the jitter matrix by row
636  memcpy(data+(i*jitterMatrixInfo.dim[0] * aMatrix.getComponentStride()),
637  jitterMatrixData+(i*jitterMatrixInfo.dimstride[1]),
638  jitterMatrixInfo.dimstride[0] * jitterMatrixInfo.dim[0]);
639  }
640  }
641  else {
642  // not supporting other dimcounts yet...
643  aMatrix.releaseLockedPointer();
644  return kTTErrInvalidType;
645  }
646  aMatrix.releaseLockedPointer();
647  return kTTErrNone;
648 }
649 
650 
651 // Assumes jitter matrix is locked, matrix dimensions agree , and we're ready to go
652 TTErr TTMatrixCopyDataToJitterMatrix(TTMatrix aMatrix, TTPtr aJitterMatrix)
653 {
654  t_jit_matrix_info jitterMatrixInfo;
655  TTBytePtr jitterMatrixData;
656  TTValue dimensions;
657  int dimcount;
658  TTBytePtr data = aMatrix.getLockedPointer();
659 
660  jit_object_method(aJitterMatrix, _sym_getinfo, &jitterMatrixInfo);
661  jit_object_method(aJitterMatrix, _sym_getdata, &jitterMatrixData);
662 
663  dimcount = jitterMatrixInfo.dimcount;
664 
665  // TODO: need to actually resize the Jitter matrix?
666 
667  if (dimcount == 1) {
668  memcpy(jitterMatrixData, data, jitterMatrixInfo.dimstride[0] * jitterMatrixInfo.dim[0]);
669  }
670  else if (dimcount == 2) {
671  for (int i=0; i<jitterMatrixInfo.dim[1]; i++) { // step through the jitter matrix by row
672  memcpy(jitterMatrixData+(i*jitterMatrixInfo.dimstride[1]),
673  data+(i*jitterMatrixInfo.dim[0] * aMatrix.getComponentStride()),
674  jitterMatrixInfo.dimstride[0] * jitterMatrixInfo.dim[0]);
675  }
676  }
677  else {
678  // not supporting other dimcounts yet...
679  aMatrix.releaseLockedPointer();
680  return kTTErrInvalidType;
681  }
682  aMatrix.releaseLockedPointer();
683  return kTTErrNone;
684 }
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTByte * getLockedPointer()
Return a pointer to the matrix data, and lock the matrix so that others cannot access the data...
Definition: TTMatrix.cpp:30
Couldn't get memory.
Definition: TTBase.h:345
void releaseLockedPointer()
Release a locked pointer obtained using getLockedPointer().
Definition: TTMatrix.cpp:36
TTDataType type
The data type of the attribute value.
Definition: TTAttribute.h:84
TTFOUNDATION_EXPORT TTEnvironment * ttEnvironment
The environment object has one instance, which is global in scope.
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
Bad DataType for the context.
Definition: TTBase.h:347
TTUInt32 getComponentStride() const
Return number of bytes from one the beginning one matrix component to the next.
Definition: TTMatrix.cpp:54
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
Wrap audio objects for convenience.
TTErr(TTObjectBase::* TTMethod)(const TTSymbol methodName, const TTValue &anInputValue, TTValue &anOutputValue)
A type that can be used to store a pointer to a message for an object.
Definition: TTObjectBase.h:46
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
Symbol type.
Definition: TTBase.h:282
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
#define TT
This macro is defined as a shortcut for doing a lookup in the symbol table.
Definition: TTSymbol.h:155
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
WrappedInstance * WrappedInstancePtr
Pointer to a wrapped instance of our object.
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
This class is used to create a backward communication channel to notify a client that something chang...
TTPtr rawpointer() const
Get the value of the raw pointer into the symbol table.
Definition: TTSymbol.h:134
TTErr(* TTValidityCheckFunction)(const TTPtr data)
A type that can be used to store a pointer to a validity checking function.
Definition: MaxAudioGraph.h:36
64-bit floating point
Definition: TTBase.h:272
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
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
TTByte * TTBytePtr
Data is a pointer to some bytes.
Definition: TTBase.h:169
void TTDSP_EXPORT TTDSPInit(const char *pathToBinaries=NULL)
Initialise the Jamoma DSP library, as well as Jamoma Foundation foundation if needed.
Definition: TTDSP.cpp:30
Wrap TTMatrixBase instances.
Definition: TTMatrix.h:27
32-bit floating point
Definition: TTBase.h:271
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
Set this flag if the method you are binding to this message is prototyped with a single TTValue& argu...
Definition: TTObjectBase.h:87
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
No Error.
Definition: TTBase.h:343
void referenceExternalData(TTPtr aDataPointer)
You must proceed to set the various attributes, dimensions, etc.
Definition: TTMatrix.cpp:24
TTErr notify(const TTValue &anInputValue, TTValue &anUnusedOutputValue)
Message called because we are registered as an observer to some other object, and then calls our exte...
Definition: TTCallback.cpp:69
The TTString class is used to represent a string.
Definition: TTString.h:34
String type.
Definition: TTBase.h:285
void resize(size_type n)
Change the number of elements.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
Wrap TTAudioSignal instances for convenience.
Definition: TTAudioObject.h:25