Jamoma API  0.6.0.a19
TTData.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A Data Object
6  *
7  * @details
8  *
9  * @authors Théo de la Hogue
10  *
11  * @copyright © 2010, 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 
17 #include "TTData.h"
18 
19 #define thisTTClass TTData
20 #define thisTTClassName "Data"
21 #define thisTTClassTags "data"
22 
23 TTObjectBasePtr TTData::instantiate (TTSymbol name, TTValue arguments)
24 {
25  return new TTData(arguments);
26 }
27 
28 
29 extern "C" void TTData::registerClass()
30 {
31  TTClassRegister(TTSymbol("Data"), thisTTClassTags, TTData::instantiate);
32 }
33 
34 
35 TTData::TTData(const TTValue& arguments) :
36 TTCallback(arguments),
37 mValue(TTValue(0.0)),
38 mValueDefault(TTValue(0.0)),
39 mValueStepsize(TTValue(0.1)), // this default value is expected in #TTData::setType method
40 mType(kTTSym_generic),
41 mTags(TTValue(kTTSym_none)),
42 mPriority(0),
43 mDescription(kTTSym_none),
44 mRepetitionsFilter(NO),
45 mActive(YES),
46 mInitialized(NO),
47 mRangeBounds(0.0, 1.0), // this default value is expected in #TTData::setType method
48 mRangeClipmode(kTTSym_none),
49 mDynamicInstances(NO),
50 mInstanceBounds(0, -1),
51 mRampDrive(kTTSym_none),
52 mRampDriveDefault(TTSymbol("system")),
53 #ifndef TT_NO_DSP
54 mRampFunction(kTTSym_none), // this default value is expected in #TTData::setType method
55 #endif
56 mRampStatus(NO),
57 mDataspace(kTTSym_none),
58 mDataspaceUnit(kTTSym_none),
59 mService(kTTSymEmpty)
60 {
61  if (arguments.size() == 1)
62  mService = arguments[0];
63 
64  registerAttribute(kTTSym_value, kTypeNone, NULL, (TTGetterMethod)&TTData::getValue, (TTSetterMethod)&TTData::setGenericValue);
65  addAttributeWithGetterAndSetter(ValueDefault, kTypeNone);
66  addAttributeWithGetterAndSetter(ValueStepsize, kTypeNone);
67 
71  addAttributeWithSetter(Description, kTypeSymbol);
72  addAttributeWithSetter(RepetitionsFilter, kTypeBoolean);
73 
75 
76  addAttribute(Initialized, kTypeBoolean);
77  addAttributeProperty(Initialized, readOnly, YES);
78  addAttributeProperty(Initialized, hidden, YES);
79 
81  addAttributeWithSetter(RangeClipmode, kTypeSymbol);
82 
83  // this is a temporary solution for Blue Yéti
84  addAttribute(DynamicInstances, kTypeBoolean);
85  addAttributeProperty(DynamicInstances, hidden, YES);
86  addAttributeWithSetter(InstanceBounds, kTypeLocalValue);
87  addAttributeProperty(InstanceBounds, hidden, YES);
88 
90  addAttribute(RampDriveDefault, kTypeSymbol);
91  addAttributeProperty(RampDriveDefault, hidden, YES);
92 #ifndef TT_NO_DSP
93  addAttributeWithSetter(RampFunction, kTypeSymbol);
94 #endif
95 
96  addAttribute(RampFunctionParameters, kTypeLocalValue);
97  addAttributeProperty(RampFunctionParameters, readOnly, YES);
98 
99  addAttribute(RampStatus, kTypeBoolean);
100  addAttributeProperty(RampStatus, readOnly, YES);
101  addAttributeProperty(RampStatus, hidden, YES); // hidden for Max
102 
104  addAttributeWithSetter(DataspaceUnit, kTypeSymbol);
105 
106  addAttribute(Service, kTypeSymbol);
107  //addAttributeProperty(Service, hidden, YES); // we don't hide this attribute to mirror it (even if we want to hide it for Max)
108 
109  registerMessage(kTTSym_Init, (TTMethod)&TTData::GenericInit, kTTMessagePassNone);
112 
113  addMessageWithArguments(Command);
114  addMessageProperty(Command, hidden, YES);
115 
116  addMessageWithArguments(RampSet);
117  addMessageProperty(RampSet, hidden, YES);
118  addMessageWithArguments(RampTarget);
119  addMessageProperty(RampTarget, hidden, YES);
120  addMessageWithArguments(RampGo);
121  addMessageProperty(RampGo, hidden, YES);
122  addMessageWithArguments(RampSlide);
123  addMessageProperty(RampSlide, hidden, YES);
124 
125  // needed to be handled by a TTTextHandler
126  addMessageWithArguments(WriteAsText);
127  addMessageProperty(WriteAsText, hidden, YES);
128 
129  mIsSending = NO;
130  mIsOverridingDataspaceUnit = NO;
131 
132  commandMethod = (TTMethodValue)&TTData::GenericCommand;
133 
134  // cache some message and attribute for observer notification
135  this->findAttribute(kTTSym_value, &valueAttribute);
136  this->findAttribute(kTTSym_initialized, &initializedAttribute);
137 
138  // set no time for external ramp drive
139  externalRampTime = 0;
140 }
141 
142 
143 TTData::~TTData()
144 {
145  ;
146 }
147 
148 
149 TTErr TTData::Inc(const TTValue& inputValue, TTValue& outputValue)
150 {
151  TTUInt32 i;
152  TTFloat64 inc, ramptime, v, vStepsize;
153  TTSymbol ramp;
154  TTValue command, none;
155 
156  if (mType == kTTSym_string)
157  return kTTErrGeneric;
158 
159  vStepsize = mValueStepsize[0];
160 
161  switch (inputValue.size()) {
162 
163  // 1 incrementation step
164  case 1 :
165  {
166  if (inputValue[0].type() == kTypeFloat64 || inputValue[0].type() == kTypeInt32) {
167  inc = inputValue[0];
168 
169  for (i = 0; i < mValue.size(); i++) {
170  v = mValue[i];
171  command.append(v + inc * vStepsize);
172  }
173  }
174  break;
175  }
176 
177  // 1 incrementation step + ramp ramptime
178  case 3 :
179  {
180  if (inputValue[0].type() == kTypeFloat64 || inputValue[0].type() == kTypeInt32) {
181  inc = inputValue[0];
182 
183  for (i = 0; i < mValue.size(); i++) {
184  v = mValue[i];
185  command.append(v + inc * vStepsize);
186  }
187 
188  if (inputValue[1].type() == kTypeSymbol) {
189  ramp = inputValue[1];
190  if (ramp == kTTSym_ramp) {
191  command.append(ramp);
192  if (inputValue[2].type() == kTypeFloat64 || inputValue[2].type() == kTypeInt32) {
193  ramptime = inputValue[2];
194  command.append(ramptime);
195  }
196  }
197  }
198  break;
199  }
200  }
201 
202  // no value or wrong value
203  default :
204  {
205  for (i = 0; i < mValue.size(); i++) {
206  v = mValue[i];
207  command.append(v + vStepsize);
208  }
209 
210  break;
211  }
212  }
213 
214  this->sendMessage(kTTSym_Command, command, none);
215 
216  return kTTErrNone;
217 }
218 
219 
220 TTErr TTData::Dec(const TTValue& inputValue, TTValue& outputValue)
221 {
222  TTUInt32 i;
223  TTFloat64 dec, ramptime, v, vStepsize;
224  TTSymbol ramp;
225  TTValue command, none;
226 
227  if (mType == kTTSym_string)
228  return kTTErrGeneric;
229 
230  vStepsize = mValueStepsize[0];
231 
232  switch (inputValue.size()) {
233 
234  // 1 decrementation step
235  case 1 :
236  {
237  if (inputValue[0].type() == kTypeFloat64 || inputValue[0].type() == kTypeInt32) {
238  dec = inputValue[0];
239 
240  for (i = 0; i < mValue.size(); i++) {
241  v = mValue[i];
242  command.append(v - dec * vStepsize);
243  }
244  }
245  break;
246  }
247 
248  // 1 decrementation step + ramp ramptime
249  case 3 :
250  {
251  if (inputValue[0].type() == kTypeFloat64 || inputValue[0].type() == kTypeInt32) {
252  dec = inputValue[0];
253 
254  for (i = 0; i < mValue.size(); i++) {
255  v = mValue[i];
256  command.append(v - dec * vStepsize);
257  }
258 
259  if (inputValue[1].type() == kTypeSymbol) {
260  ramp = inputValue[1];
261  if (ramp == kTTSym_ramp) {
262  command.append(ramp);
263  if (inputValue[2].type() == kTypeFloat64 || inputValue[2].type() == kTypeInt32) {
264  ramptime = inputValue[2];
265  command.append(ramptime);
266  }
267  }
268  }
269  break;
270  }
271  }
272 
273  // no value or wrong value
274  default :
275  {
276  for (i = 0; i < mValue.size(); i++) {
277  v = mValue[i];
278  command.append(v - vStepsize);
279  }
280 
281  break;
282  }
283  }
284 
285  this->sendMessage(kTTSym_Command, command, none);
286 
287  return kTTErrNone;
288 }
289 
290 
291 TTErr TTData::getValue(TTValue& value)
292 {
293  // can't get the value before the data has been initialized
294  if (mInitialized) {
295 
296  value = mValue;
297  return kTTErrNone;
298  }
299  else
300  return kTTErrGeneric;
301 }
302 
303 
304 TTErr TTData::getValueDefault(TTValue& value)
305 {
306  value = mValueDefault;
307  return kTTErrNone;
308 }
309 
310 
311 TTErr TTData::setValueDefault(const TTValue& value)
312 {
313  TTValue n = value; // use new value to protect the attribute
314  mValueDefault = value;
315  this->notifyObservers(kTTSym_valueDefault, n);
316  return kTTErrNone;
317 }
318 
319 
320 TTErr TTData::getValueStepsize(TTValue& value)
321 {
322  value = mValueStepsize;
323  return kTTErrNone;
324 }
325 
326 
327 TTErr TTData::setValueStepsize(const TTValue& value)
328 {
329  TTValue n = value; // use new value to protect the attribute
330  mValueStepsize = value;
331  this->notifyObservers(kTTSym_valueStepsize, n);
332  return kTTErrNone;
333 }
334 
335 TTErr TTData::setTags(const TTValue& value)
336 {
337  TTValue n = value; // use new value to protect the attribute
338  mTags = value;
339  this->notifyObservers(kTTSym_tags, n);
340  return kTTErrNone;
341 }
342 
343 TTErr TTData::setRepetitionsFilter(const TTValue& value)
344 {
345  TTValue n = value; // use new value to protect the attribute
346  mRepetitionsFilter = value;
347  this->notifyObservers(kTTSym_repetitionsFilter, n);
348  return kTTErrNone;
349 }
350 
351 
352 TTErr TTData::setActive(const TTValue& value)
353 {
354  TTValue n = value; // use new value to protect the attribute
355  mActive = value;
356  this->notifyObservers(kTTSym_active, n);
357  return kTTErrNone;
358 }
359 
360 
361 TTErr TTData::setRangeBounds(const TTValue& value)
362 {
363  TTValue n; // use new value to protect the attribute
364  mRangeBounds = value;
365 
366  if (mType == kTTSym_integer)
367  mRangeBounds.truncate();
368 
369  n = mRangeBounds;
370 
371  this->notifyObservers(kTTSym_rangeBounds, n);
372  return kTTErrNone;
373 }
374 
375 
376 TTErr TTData::setRangeClipmode(const TTValue& value)
377 {
378  TTValue n = value; // use new value to protect the attribute
379  mRangeClipmode = value;
380  this->notifyObservers(kTTSym_rangeClipmode, n);
381  return kTTErrNone;
382 }
383 
384 
385 TTErr TTData::setInstanceBounds(const TTValue& value)
386 {
387  TTValue n; // use new value to protect the attribute
388  TTInt16 vmin, vmax;
389  vmin = value[0];
390  vmax = value[1];
391  mInstanceBounds[0] = vmin;
392  mInstanceBounds[1] = vmax;
393 
394  return kTTErrNone;
395 }
396 
397 
398 TTErr TTData::setRampDrive(const TTValue& value)
399 {
400  TTValue n = value; // use new value to protect the attribute
401  mRampDrive = value;
402 
403  rampSetup();
404 
405  this->notifyObservers(kTTSym_rampDrive, n);
406  return kTTErrNone;
407 }
408 
409 
410 #ifndef TT_NO_DSP
411 TTErr TTData::setRampFunction(const TTValue& value)
412 {
413  TTValue n = value; // use new value to protect the attribute
414  mRampFunction = value;
415 
416  if (mRampFunction != kTTSym_none && mRamper.valid()) {
417 
418  // set the function of the ramper
419  mRamper.set(kTTSym_function, mRampFunction);
420 
421  TTUInt32 i, n;
422  TTValue names;
423  TTSymbol aName;
424 
425  // Remove former datas
426  n = mRampFunctionParameters.size();
427  for (i = 0; i < n; i++) {
428  aName = mRampFunctionParameters[i];
429  this->removeAttribute(aName);
430  }
431  mRampFunctionParameters.clear();
432 
433  // cache the function's attribute names
434  TTRampPtr(mRamper.instance())->mFunctionUnit.attributes(names);
435  n = names.size();
436 
437  if (n) {
438  for (i = 0; i < n; i++) {
439 
440  aName = names[i];
441 
442  if (aName == kTTSym_bypass || aName == kTTSym_mute || aName == kTTSym_maxNumChannels || aName == kTTSym_sampleRate)
443  continue; // don't publish these datas
444 
445  // extend attribute with the same name
446  this->extendAttribute(aName, TTRampPtr(mRamper.instance())->mFunctionUnit.instance(), aName);
447 
448  mRampFunctionParameters.append(aName);
449  }
450  }
451 
452  if (mRampFunctionParameters.size() == 0)
453  mRampFunctionParameters.append(kTTSym_none);
454  }
455 
456  this->notifyObservers(kTTSym_rampFunction, n);
457  return kTTErrNone;
458 }
459 #endif
460 
461 
462 TTErr TTData::setDataspace(const TTValue& value)
463 {
464  TTErr err;
465  TTValue v;
466  TTValue n = value; // use new value to protect the attribute
467 
468  mDataspace = value;
469 
470  if (!mDataspaceConverter.valid()) {
471  mDataspaceConverter = TTObject("dataspace");
472  mDataspaceInverseConverter = TTObject("dataspace");
473  }
474 
475  err = mDataspaceConverter.set("dataspace", mDataspace);
476  mDataspaceInverseConverter.set("dataspace", mDataspace);
477 
478  if (err) {
479 
480  mDataspace = kTTSym_none;
481  return err;
482  }
483 
484  // If there is already a unit defined, then we try to use that
485  err = mDataspaceConverter.set("outputUnit", mDataspaceUnit);
486  mDataspaceInverseConverter.set("inputUnit", mDataspaceUnit);
487 
488  // Otherwise we use the default (neutral) unit.
489  if (err) {
490  mDataspaceConverter.get("outputUnit", v);
491  mDataspaceUnit = v[0];
492  mDataspaceConverter.set("outputUnit", mDataspaceUnit);
493  mDataspaceInverseConverter.set("inputUnit", mDataspaceUnit);
494  }
495 
496  this->notifyObservers(kTTSym_dataspace, n);
497  return kTTErrNone;
498 }
499 
500 
501 TTErr TTData::setDataspaceUnit(const TTValue& value)
502 {
503  TTValue n = value; // use new value to protect the attribute
504  mDataspaceUnit = value;
505 
506  if (mDataspaceConverter.valid()) {
507 
508  mDataspaceConverter.set("outputUnit", mDataspaceUnit);
509  mDataspaceInverseConverter.set("inputUnit", mDataspaceUnit);
510 
511  this->notifyObservers(kTTSym_dataspaceUnit, n);
512  return kTTErrNone;
513  }
514 
515  return kTTErrGeneric;
516 }
517 
518 
519 TTErr TTData::setDescription(const TTValue& value)
520 {
521  TTValue n = value; // use new value to protect the attribute
522  mDescription = value;
523 
524  this->notifyObservers(kTTSym_description, n);
525  return kTTErrNone;
526 }
527 
528 TTErr TTData::setPriority(const TTValue& value)
529 {
530  TTValue n = value; // use new value to protect the attribute
531  mPriority = value;
532 
533  this->notifyObservers(kTTSym_priority, n);
534  return kTTErrNone;
535 }
536 
537 
538 TTErr TTData::RampSet(const TTValue& inputValue, TTValue& outputValue)
539 {
540  return mRamper.send("Set", inputValue, outputValue);
541 }
542 
543 
544 TTErr TTData::RampTarget(const TTValue& inputValue, TTValue& outputValue)
545 {
546  return mRamper.send("Target", inputValue, outputValue);
547 }
548 
549 
550 TTErr TTData::RampGo(const TTValue& inputValue, TTValue& outputValue)
551 {
552  return mRamper.send(kTTSym_Go, inputValue, outputValue);
553 }
554 
555 
556 TTErr TTData::RampSlide(const TTValue& inputValue, TTValue& outputValue)
557 {
558  return mRamper.send("Slide", inputValue, outputValue);
559 }
560 
561 
562 TTErr TTData::rampSetup()
563 {
564  TTValue args;
565 
566  // 1. destroy the old ramp object
567  if (mRamper.valid()) {
568  mRamper = TTObject();
569  externalRampTime = 0;
570  }
571 
572  // 2. create the new ramp object
573  // For some types ramping doesn't make sense, so they will be set to none
574  if (mType == kTTSym_none || mType == kTTSym_string || mType == kTTSym_generic)
575  mRampDrive = kTTSym_none;
576 
577  else {
578 
579  // don't create ramper for external ramp drive
580  if (mRampDrive == kTTSym_external || mRampDrive == kTTSym_none)
581  return kTTErrNone;
582 
584  args.append((TTPtr)this); // we have to store this as a pointer
585 
586  mRamper = TTObject("Ramp", args);
587  mRamper.set("drive", mRampDrive);
588  }
589 
590 #ifndef TT_NO_DSP
591  // 3. reset the ramp function
592  return setRampFunction(mRampFunction);
593 #else
594  return kTTErrNone;
595 #endif
596 }
597 
598 
599 TTErr TTData::convertUnit(const TTValue& inputValue, TTValue& outputValue)
600 {
601  return mDataspaceConverter.send("convert", inputValue, outputValue);
602 }
603 
604 
605 TTErr TTData::inverseConvertUnit(const TTValue& inputValue, TTValue& outputValue)
606 {
607  return mDataspaceInverseConverter.send("convert", inputValue, outputValue);
608 }
609 
610 
611 TTErr TTData::notifyObservers(TTSymbol attrName, const TTValue& value)
612 {
613  TTAttributePtr anAttribute = NULL;
614  TTErr err;
615 
616  err = this->findAttribute(attrName, &anAttribute);
617 
618  if (!err)
619  anAttribute->sendNotification(kTTSym_notify, value); // we use kTTSym_notify because we know that observers are TTCallback
620 
621  return kTTErrNone;
622 }
623 
624 
625 TTErr TTData::WriteAsText(const TTValue& inputValue, TTValue& outputValue)
626 {
627  TTObject o = inputValue[0];
628  TTTextHandlerPtr aTextHandler = (TTTextHandlerPtr)o.instance();
629  if (!aTextHandler)
630  return kTTErrGeneric;
631 
632  TTString *buffer;
633  TTValue toString;
634  TTString line;
635 
636  buffer = aTextHandler->mWriter;
637 
638  // Type
639  *buffer += "\t\t\t<td class =\"instructionType\">";
640  *buffer += this->mType.c_str();
641  *buffer += "</td>";
642 
643  // range/bounds
644  toString = this->mRangeBounds;
645  toString.toString();
646  line = TTString(toString[0]);
647 
648  if ( (this->mType == kTTSym_integer) || (this->mType == kTTSym_boolean) || (this->mType == kTTSym_decimal) || (this->mType == kTTSym_generic) ) {
649  *buffer +="\t\t\t<td class =\"instructionRangeBounds\">";
650  *buffer +=line.data();
651  *buffer += "</td>";
652  }
653  else
654  *buffer += "\t\t\t<td class = \"instructionRangeBounds\"> N/A </td>";
655 
656  // clipmode
657  *buffer += "\t\t\t<td class =\"instructionRangeClipmode\">";
658  *buffer += this->mRangeClipmode.c_str();
659  *buffer += "</td>";
660 
661  // ramp/drive
662  *buffer += "\t\t\t<td class =\"instructionRampDrive\">";
663  *buffer += this->mRampDrive.c_str();
664  *buffer += "</td>";
665 #ifndef TT_NO_DSP
666  // ramp/function
667  *buffer += "\t\t\t<td class =\"instructionRampFunction\">";
668  *buffer += this->mRampFunction.c_str();
669  *buffer += "</td>";
670 #endif
671  // dataspace
672  *buffer += "\t\t\t<td class =\"instructionDataspace\">";
673  *buffer += this->mDataspace.c_str();
674  *buffer += "</td>";
675 
676  // dataspace/unit
677  *buffer += "\t\t\t<td class =\"instructionDataspaceUnit\">";
678  *buffer += this->mDataspaceUnit.c_str();
679  *buffer += "</td>";
680 
681  // repetitions/filter
682  toString = this->mRepetitionsFilter;
683  toString.toString();
684  line = TTString(toString[0]);
685  *buffer += "\t\t\t<td class =\"instructionRepetitionsFilter\">";
686  *buffer += line.data();
687  *buffer += "</td>";
688 
689  // description
690  *buffer += "\t\t\t<td class =\"instructionDescription\">";
691  *buffer += this->mDescription.c_str();
692  *buffer += "</td>";
693  return kTTErrNone;
694 }
695 
696 
697 #if 0
698 #pragma mark -
699 #pragma mark Some Methods
700 #endif
701 
702 
703 TTDictionaryBasePtr TTDataParseCommand(const TTValue& commandValue, TTBoolean parseUnitAndRamp)
704 {
705  TTDictionaryBasePtr command = new TTDictionaryBase();
706 
707  // don't parse the value, just store it into a dictionary
708  // this is useful when unit or ramp doesn't mean anything (e.g. generic case)
709  if (!parseUnitAndRamp) {
710 
711  command->setValue(commandValue);
712  command->setSchema(kTTSym_command);
713  return command;
714  }
715 
716  TTUInt32 time;
717  TTUInt32 commandSize;
718  TTSymbol unit, ramp;
719  TTValue aValue, c;
720  TTBoolean hasRamp = false;
721  TTBoolean hasUnit = false;
722 
723  // Parse the command to handle unit and ramp
724  ///////////////////////////////////////////////////
725  commandSize = commandValue.size();
726  switch(commandSize) {
727 
728  // no value
729  case 0 :
730  {
731  // nothing to do
732  break;
733  }
734 
735  // 1 value
736  case 1 :
737  {
738  // nothing to do
739  break;
740  }
741 
742  // 2 values || 1 value + unit
743  case 2 :
744  {
745  // Is the second element is a unit symbol ?
746  if (commandValue[0].type() != kTypeSymbol && commandValue[1].type() == kTypeSymbol) {
747  hasUnit = true;
748  unit = commandValue[1];
749  }
750 
751  break;
752  }
753 
754  // 3 values || 2 values + unit || 1 value + ramp ramptime
755  case 3 :
756  {
757  // Is the second element is a ramp symbol ?
758  if (commandValue[1].type() == kTypeSymbol) {
759  ramp = commandValue[1];
760  if (ramp == kTTSym_ramp)
761  hasRamp = true;
762  }
763  // or is the last element is a unit symbol ?
764  else if (commandValue[0].type() != kTypeSymbol && commandValue[2].type() == kTypeSymbol) {
765  hasUnit = true;
766  unit = commandValue[2];
767  }
768 
769  break;
770  }
771 
772  // X values || X-1 values + unit || X-2 values + ramp ramptime || X-3 values + unit + ramp ramptime
773  default :
774  {
775  // Is the X-2 element is a ramp symbol ?
776  if (commandValue[commandSize - 2].type() == kTypeSymbol) {
777  ramp = commandValue[commandSize - 2];
778  if (ramp == kTTSym_ramp)
779  hasRamp = true;
780  }
781 
782  // Is the X-3 or last element a unit symbol ?
783  if (commandValue[0].type() != kTypeSymbol) {
784  if (hasRamp) {
785  if (commandValue[commandSize - 3].type() == kTypeSymbol) {
786  hasUnit = true;
787  unit = commandValue[commandSize - 3];
788  }
789  }
790  else if (commandValue[commandSize - 1].type() == kTypeSymbol) {
791 
792  // only if all values before are numerical
793  TTBoolean numerical = YES;
794  for (TTUInt32 i = 0; i < commandSize - 1; i++)
795  numerical &= commandValue[i].type() != kTypeSymbol;
796 
797  if (numerical) {
798  hasUnit = true;
799  unit = commandValue[commandSize - 1];
800  }
801  }
802  }
803 
804  break;
805  }
806  }
807 
808  // 3. Strip ramp or unit informations if needed
809  if (hasRamp && hasUnit) {
810  aValue = commandValue;
811  aValue.resize(commandSize - 3);
812  }
813  else if (hasRamp) {
814  aValue = commandValue;
815  aValue.resize(commandSize - 2);
816  }
817  else if (hasUnit) {
818  aValue = commandValue;
819  aValue.resize(commandSize - 1);
820  }
821  else
822  aValue = commandValue;
823 
824  // 4. Edit command
825  if (hasUnit)
826  command->append(kTTSym_unit, unit);
827 
828  if (hasRamp) {
829 
830  // any other case it is a ramp time
831  time = commandValue[commandSize - 1];
832  command->append(kTTSym_ramp, (int)time);
833  }
834 
835  command->setValue(aValue);
836  command->setSchema(kTTSym_command);
837 
838  // We return a dictionary with one or more keys. It always has a value. If it is ramping, it also has a ramp key, and if it has a unit, it also has a unit key.
839 
840  return command;
841 }
842 
843 
844 void TTDataRampCallback(void *o, TTUInt32 n, TTFloat64 *rampedArray)
845 {
846  TTDataPtr aData = (TTDataPtr)o;
847  TTValue rampedValue;
848  TTBoolean isRunning;
849  TTUInt16 i;
850 
851  rampedValue.resize(n);
852  for (i = 0; i < n; i++)
853  rampedValue[i] = rampedArray[i];
854 
855  /*******************
856  TL: Commenting out as these processes need to be moved to the typed methods
857 
858  // TODO: This need to be moved to the typed method for @type integer
859  // Why is it truncated rather than rounded?
860  if (aData->mType == kTTSym_integer)
861  rampedValue.truncate();
862 
863  // TODO: This also need to be moved to the typed methods
864  if (aData->mRepetitionsFilter)
865  if (aData->mValue == rampedValue)
866  return;
867  *******************/
868 
869  // Set internal value - this calls the appropriate typed setter method in TTDataTypedMethods.cpp
870  aData->setAttributeValue(kTTSym_value, rampedValue);
871 
872  // Update the ramp status attribute
873  aData->mRamper.get(kTTSym_running, isRunning);
874  if (aData->mRampStatus != isRunning) {
875 
876  aData->mRampStatus = isRunning;
877 
878  // Stop the ramp
879  if (!aData->mRampStatus)
880  aData->mRamper.send(kTTSym_Stop);
881 
882  aData->notifyObservers(kTTSym_rampStatus, aData->mRampStatus);
883  }
884 }
TTErr sendMessage(const TTSymbol name)
TODO: Document this function.
TTErr setSchema(const TTSymbol schemaName)
TODO: Add documentation schemaName TODO: Add documentation.
TTErr(TTObjectBase::* TTSetterMethod)(const TTAttribute &attribute, const TTValue &value)
A type that can be used to store a pointer to a message for an object.
Definition: TTObjectBase.h:78
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
friend void TTMODULAR_EXPORT TTDataRampCallback(void *o, TTUInt32 n, TTFloat64 *v)
Definition: TTData.cpp:844
This class is used to be sensitive to any TTObject notifications and report them using a function wit...
Definition: TTCallback.h:28
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTString toString(TTBoolean quotes=YES) const
Return the content as a single string with spaces between elements.
Definition: TTValue.h:351
TTRamp generates a linear traversal from 0.0 to 1.0 over the course of a specified time period...
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
A type that contains a key and a value.
A Data Object.
TTErr removeAttribute(const TTSymbol name)
Remove an attribute.
TTErr setValue(const TTValue &newValue)
TODO: Add documentation.
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
TTErr sendNotification(const TTSymbol name, const TTValue &arguments)
Send a notification.
TTErr(TTObjectBase::* TTMethodValue)(const TTValue &anInputValue, TTValue &anOutputValue)
A type that can be used to call a message for an object that does not declare the name argument...
Definition: TTObjectBase.h:52
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
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 registerAttribute(const TTSymbol name, const TTDataType type, void *address)
Register an attribute.
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
This is a special type used by TTAttribute to indicate that a value is a TTValue and is locally maint...
Definition: TTBase.h:286
TTErr registerMessage(const TTSymbol name, TTMethod method)
Register a message with this object.
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
std::int16_t TTInt16
16 bit signed integer
Definition: TTBase.h:175
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
void TTDataRampCallback(void *o, TTUInt32 n, TTFloat64 *rampedArray)
Definition: TTData.cpp:844
64-bit floating point
Definition: TTBase.h:272
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
Definition: TTAttribute.h:68
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
TTErr extendAttribute(const TTSymbol name, const TTObjectBasePtr extendedObject, const TTSymbol extendedName)
Extend the attribute of an existing TTObjectBase to this TTObjectBase (using another attribute name) ...
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
const char * c_str() const
Return a pointer to the internal string as a C-string.
Definition: TTSymbol.h:77
TTData establishes a control point, which is to say a TTNode that is dramaticly expanded, for a model to get/set its state.
Definition: TTData.h:28
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
32-bit signed integer, range is -2,147,483,648 through 2,147,483,647.
Definition: TTBase.h:277
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
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
Definition: TTAttribute.h:47
TTDictionaryBasePtr TTDataParseCommand(const TTValue &commandValue, TTBoolean parseUnitAndRamp)
Format the command to update the value of TTData as a TTDictionary.
Definition: TTData.cpp:703
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
Set this flag if the method you are binding to this message is prototyped to accept no arguments...
Definition: TTObjectBase.h:86
The TTString class is used to represent a string.
Definition: TTString.h:34
void truncate()
Truncate float & double elements so that only whole number remains.
Definition: TTValue.h:334
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
TTErr(TTObjectBase::* TTGetterMethod)(const TTAttribute &attribute, TTValue &value)
A type that can be used to store a pointer to a message for an object.
Definition: TTObjectBase.h:73
void resize(size_type n)
Change the number of elements.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr findAttribute(const TTSymbol name, TTAttribute **attr)
Find an attribute.
#define addAttributeWithGetterAndSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter and sett...
Definition: TTAttribute.h:57
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37