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