Jamoma API  0.6.0.a19
TTCueManager.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A CueManager 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 "TTCueManager.h"
18 #include <libxml/encoding.h>
19 #include <libxml/xmlwriter.h>
20 #include <libxml/xmlreader.h>
21 
22 #define thisTTClass TTCueManager
23 #define thisTTClassName "CueManager"
24 #define thisTTClassTags "cue, manager"
25 
26 TT_MODULAR_CONSTRUCTOR,
27 mCurrent(kTTSymEmpty),
28 mCurrentPosition(0),
29 mNamespace(kTTSym_none),
30 mAddress(kTTAdrsRoot),
31 mDefaultNamespace(NULL)
32 {
33  if (arguments.size() == 1)
34  mReturnLineCallback = arguments[0];
35 
37  addAttributeProperty(Names, readOnly, YES);
38 
39  addAttribute(Current, kTypeSymbol);
40  addAttributeProperty(Current, readOnly, YES);
41 
42  addAttribute(CurrentPosition, kTypeInt32);
43  addAttributeProperty(CurrentPosition, readOnly, YES);
44 
45  addAttribute(Namespace, kTypeSymbol);
46 
48 
49  registerAttribute(TTSymbol("currentDescription"), kTypeLocalValue, NULL, (TTGetterMethod)&TTCueManager::getCurrentDescription, (TTSetterMethod)&TTCueManager::setCurrentDescription);
50  registerAttribute(TTSymbol("currentRamp"), kTypeLocalValue, NULL, (TTGetterMethod)&TTCueManager::getCurrentRamp, (TTSetterMethod)&TTCueManager::setCurrentRamp);
51 
53  addAttributeProperty(Cues, readOnly, YES);
54  addAttributeProperty(Cues, hidden, YES);
55 
56  addMessageWithArguments(NamespaceSelect);
57  addMessageWithArguments(NamespaceUnselect);
58  addMessageWithArguments(NamespaceGrab);
59 
60  addMessage(Clear);
61 
67  addMessageWithArguments(Interpolate);
74  addMessageWithArguments(Optimize);
75 
76  // needed to be handled by a TTXmlHandler
77  addMessageWithArguments(WriteAsXml);
78  addMessageProperty(WriteAsXml, hidden, YES);
79  addMessageWithArguments(ReadFromXml);
80  addMessageProperty(ReadFromXml, hidden, YES);
81 
82  // needed to be handled by a TTTextHandler
83  addMessageWithArguments(WriteAsText);
84  addMessageProperty(WriteAsText, hidden, YES);
85  addMessageWithArguments(ReadFromText);
86  addMessageProperty(ReadFromText, hidden, YES);
87 
88  mDefaultNamespace = new TTAddressItem();
89 }
90 
91 TTCueManager::~TTCueManager()
92 {
93  delete mDefaultNamespace;
94  mDefaultNamespace = NULL;
95 }
96 
97 TTErr TTCueManager::getCues(TTValue& value)
98 {
99  value = TTPtr(&mCues);
100  return kTTErrNone;
101 }
102 
103 TTErr TTCueManager::getCurrentDescription(TTValue& value)
104 {
105  TTValue v;
106 
107  // if cue exists
108  if (!mCues.lookup(mCurrent, v)) {
109 
110  mCurrentCue = v[0];
111  return mCurrentCue.get(kTTSym_description, value);
112  }
113 
114  return kTTErrGeneric;
115 }
116 
117 TTErr TTCueManager::setCurrentDescription(const TTValue& value)
118 {
119  TTValue v;
120 
121  // if cue exists
122  if (!mCues.lookup(mCurrent, v)) {
123 
124  mCurrentCue = v[0];
125  v = value;
126  mCurrentCue.set(kTTSym_description, v);
127  }
128 
129  return kTTErrGeneric;
130 }
131 
132 TTErr TTCueManager::getCurrentRamp(TTValue& value)
133 {
134  TTValue v;
135 
136  // if cue exists
137  if (!mCues.lookup(mCurrent, v)) {
138 
139  mCurrentCue = v[0];
140  return mCurrentCue.get(kTTSym_ramp, value);
141  }
142 
143  value = 0;
144  return kTTErrGeneric;
145 }
146 
147 TTErr TTCueManager::setCurrentRamp(const TTValue& value)
148 {
149  TTValue v;
150 
151  // if cue exists
152  if (!mCues.lookup(mCurrent, v)) {
153 
154  mCurrentCue = v[0];
155  v = value;
156  mCurrentCue.set(kTTSym_ramp, v);
157  }
158 
159  return kTTErrGeneric;
160 }
161 
162 TTErr TTCueManager::setAddress(const TTValue& value)
163 {
164  TTObject aCue;
165  TTSymbol cueName;
166  TTValue v, names;
167  TTUInt32 i;
168 
169  if (value.size() == 1) {
170 
171  if (value[0].type() == kTypeSymbol) {
172 
173  mAddress = value[0];
174 
175  mCues.getKeys(names);
176  for (i = 0; i < names.size(); i++) {
177 
178  cueName = names[i];
179  mCues.lookup(cueName, v);
180  aCue = v[0];
181  aCue.set(kTTSym_address, mAddress);
182  }
183 
184  return kTTErrNone;
185  }
186  }
187 
188  return kTTErrGeneric;
189 }
190 
191 TTErr TTCueManager::NamespaceSelect(const TTValue& inputValue, TTValue& outputValue)
192 {
193  TTAddressItemPtr aSelection, anItem;
194  TTAddress address;
195  TTUInt32 i;
196 
197  aSelection = getNamespace();
198 
199  for (i = 0; i < inputValue.size(); i++) {
200 
201  if (inputValue[i].type() == kTypeSymbol) {
202 
203  address = inputValue[i];
204 
205  // in relative address case : use the mAddress
206  if (address.getType() == kAddressRelative)
207  address = mAddress.appendAddress(address);
208  /*
209  // wildcard case
210  TTNodePtr aNode;
211  TTList aNodeList;
212  TTValue v, none;
213 
214  mDirectory->Lookup(address, aNodeList, &aNode);
215 
216  for (aNodeList.begin(); aNodeList.end(); aNodeList.next()) {
217 
218  aNode = TTNodePtr((TTPtr)aNodeList.current()[0]);
219 
220  }
221 */
222  if (address == kTTAdrsRoot)
223  aSelection->setSelection(YES, YES);
224 
225  else if (!aSelection->find(address, &anItem))
226  anItem->setSelection(YES, YES);
227  }
228  }
229 
230  // refresh all namespace handlers (TTExplorer only)
231  aSelection->iterateHandlersSendingMessage(kTTSym_SelectionRefresh);
232 
233  return kTTErrNone;
234 }
235 
236 TTErr TTCueManager::NamespaceUnselect(const TTValue& inputValue, TTValue& outputValue)
237 {
238  TTAddressItemPtr aSelection, anItem;
239  TTAddress address;
240  TTUInt32 i;
241 
242  aSelection = getNamespace();
243 
244  for (i = 0; i < inputValue.size(); i++) {
245 
246  if (inputValue[i].type() == kTypeSymbol) {
247 
248  address = inputValue[i];
249 
250  // in relative address case : use the mAddress
251  if (address.getType() == kAddressRelative)
252  address = mAddress.appendAddress(address);
253 
254  if (address == kTTAdrsRoot)
255  aSelection->setSelection(NO, YES);
256 
257  else if (!aSelection->find(address, &anItem))
258  anItem->setSelection(NO, YES);
259  }
260  }
261 
262  // refresh all namespace handlers (TTExplorer only)
263  aSelection->iterateHandlersSendingMessage(kTTSym_SelectionRefresh);
264 
265  return kTTErrNone;
266 }
267 
268 TTErr TTCueManager::NamespaceGrab(const TTValue& inputValue, TTValue& outputValue)
269 {
270  TTAddressItemPtr aSelection;
271  TTValue v, none;
272 
273  if (inputValue.size() == 1) {
274 
275  // get cue name
276  if (inputValue[0].type() == kTypeSymbol)
277  mCurrent = inputValue[0];
278 
279  // get cue at position
280  if (inputValue[0].type() == kTypeInt32) {
281 
282  mCurrentPosition = inputValue[0];
283 
284  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
285  mCurrent = mNames[mCurrentPosition-1];
286  else
287  return kTTErrGeneric;
288  }
289  }
290 
291  // if cue exists
292  if (!mCues.lookup(mCurrent, v)) {
293 
294  mCurrentCue = v[0];
295 
296  // get the namespace
297  aSelection = getNamespace();
298 
299  mCurrentCue.send("Select", (TTPtr)aSelection);
300 
301  // refresh all namespace handlers (TTExplorer only)
302  aSelection->iterateHandlersSendingMessage(kTTSym_SelectionRefresh);
303 
304  return kTTErrNone;
305  }
306  else
307  mCurrentPosition = 0;
308 
309  return kTTErrGeneric;
310 }
311 
312 TTErr TTCueManager::Clear()
313 {
314  mCues.clear();
315  mCurrentCue = TTObject();
316  mCurrent = kTTSymEmpty;
317  mCurrentPosition = 0;
318  mNames.clear();
319 
320  notifyNamesObservers();
321 
322  return kTTErrNone;
323 }
324 
325 TTErr TTCueManager::New(const TTValue& inputValue, TTValue& outputValue)
326 {
327  TTValue v, args, out;
328  TTErr err;
329 
330  // get cue name
331  if (inputValue.size() == 1)
332  if (inputValue[0].type() == kTypeSymbol)
333  mCurrent = inputValue[0];
334 
335  // get cue position and name
336  if (inputValue.size() == 2)
337  if (inputValue[1].type() == kTypeSymbol)
338  mCurrent = inputValue[1];
339 
340  if (mCurrent == kTTSymEmpty)
341  return kTTErrGeneric;
342 
343  // don't create two cues with the same name
344  if (mCues.lookup(mCurrent, v)) {
345 
346  // prepare arguments
347  args.append(mReturnLineCallback);
348 
349  // Create a new cue
350  mCurrentCue = TTObject(kTTSym_Cue, args);
351 
352  mCurrentCue.set(kTTSym_name, mCurrent);
353  mCurrentCue.set(kTTSym_address, mAddress);
354 
355  // Append the new cue
356  mCues.append(mCurrent, mCurrentCue);
357  mNames.append(mCurrent);
358  mCurrentPosition = mNames.size();
359 
360  notifyNamesObservers();
361  }
362  else {
363  mCurrentCue = v[0];
364  mCurrentCue.send("Clear");
365  }
366 
367  // select the namespace
368  v = TTValue((TTPtr)getNamespace());
369  err = mCurrentCue.send("Store", v, out);
370 
371  // Move the cue at position
372  if (inputValue.size() == 2) {
373 
374  v = mCurrent;
375  v.append(inputValue[0]);
376 
377  err = Move(v, out);
378  }
379 
380  return err;
381 }
382 
383 TTErr TTCueManager::Update(const TTValue& inputValue, TTValue& outputValue)
384 {
385  TTValue v, none;
386  TTSymbol anAddress = kTTAdrsRoot;
387 
388  if (inputValue.size() >= 1) {
389 
390  // get cue name
391  if (inputValue[0].type() == kTypeSymbol) {
392  mCurrent = inputValue[0];
393 
394  TTSymbol name;
395  for (TTUInt32 i = 0; i < mNames.size(); i++) {
396  name = mNames[i];
397  if (name == mCurrent) {
398  mCurrentPosition = i+1;
399  break;
400  }
401  }
402  }
403 
404  // get cue at position
405  if (inputValue[0].type() == kTypeInt32) {
406 
407  mCurrentPosition = inputValue[0];
408 
409  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
410  mCurrent = mNames[mCurrentPosition-1];
411  else
412  return kTTErrGeneric;
413  }
414  }
415 
416  // get address from where update starts (default : kAdrsRoot)
417  if (inputValue.size() == 2)
418  if (inputValue[1].type() == kTypeSymbol)
419  anAddress = inputValue[1];
420 
421  // if cue exists
422  if (!mCues.lookup(mCurrent, v)) {
423 
424  mCurrentCue = v[0];
425 
426  return mCurrentCue.send(kTTSym_Update, anAddress);
427  }
428 
429  return kTTErrGeneric;
430 }
431 
432 TTErr TTCueManager::Append(const TTValue& inputValue, TTValue& outputValue)
433 {
434  TTValue v, args, lineValue, parsedLine;
435 
436  if (inputValue.size() >= 1) {
437 
438  // get cue name
439  if (inputValue[0].type() == kTypeSymbol) {
440  mCurrent = inputValue[0];
441 
442  TTSymbol name;
443  for (TTUInt32 i = 0; i < mNames.size(); i++) {
444  name = mNames[i];
445  if (name == mCurrent) {
446  mCurrentPosition = i+1;
447  break;
448  }
449  }
450  }
451 
452  // get cue at position
453  if (inputValue[0].type() == kTypeInt32) {
454 
455  mCurrentPosition = inputValue[0];
456 
457  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
458  mCurrent = mNames[mCurrentPosition-1];
459  else
460  return kTTErrGeneric;
461  }
462  }
463 
464  // edit lineValue to append
465  lineValue.copyFrom(inputValue, 1);
466 
467  // if cue exists
468  if (!mCues.lookup(mCurrent, v)) {
469 
470  mCurrentCue = v[0];
471 
472  return mCurrentCue.send("Append", lineValue, parsedLine);
473  }
474  // else create a new cue and call Append method again
475  else {
476 
477  // Create a new cue
478  mCurrentCue = TTObject(kTTSym_Cue, mReturnLineCallback);
479 
480  mCurrentCue.set(kTTSym_name, mCurrent);
481  mCurrentCue.set(kTTSym_address, mAddress);
482 
483  // Append the new cue
484  mCues.append(mCurrent, mCurrentCue);
485  mNames.append(mCurrent);
486  mCurrentPosition = mNames.size();
487 
488  notifyNamesObservers();
489 
490  // Append - cue cueName
491  v = kTTSym_dash;
492  v.append(TTSymbol("cue"));
493  v.append(mCurrent);
494  mCurrentCue.send("Append", v, parsedLine);
495 
496  // Append - description
497  v = kTTSym_dash;
498  v.append(TTSymbol("description"));
499  mCurrentCue.send("Append", v, parsedLine);
500 
501  // Append an comment line
502  v = kTTSym_sharp;
503  mCurrentCue.send("Append", v, parsedLine);
504 
505  // Append given lineValue
506  return mCurrentCue.send("Append", lineValue, parsedLine);
507  }
508 
509  return kTTErrGeneric;
510 }
511 
512 TTErr TTCueManager::Recall(const TTValue& inputValue, TTValue& outputValue)
513 {
514  TTValue v, none;
515  TTSymbol anAddress = kTTAdrsRoot;
516 
517  if (inputValue.size() >= 1) {
518 
519  // get cue name
520  if (inputValue[0].type() == kTypeSymbol) {
521  mCurrent = inputValue[0];
522 
523  TTSymbol name;
524  for (TTUInt32 i = 0; i < mNames.size(); i++) {
525  name = mNames[i];
526  if (name == mCurrent) {
527  mCurrentPosition = i+1;
528  break;
529  }
530  }
531  }
532 
533  // get cue at position
534  if (inputValue[0].type() == kTypeInt32) {
535 
536  mCurrentPosition = inputValue[0];
537 
538  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
539  mCurrent = mNames[mCurrentPosition-1];
540  else
541  return kTTErrGeneric;
542  }
543  }
544 
545  // get address from where recall starts (default : kAdrsRoot)
546  if (inputValue.size() == 2)
547  if (inputValue[1].type() == kTypeSymbol)
548  anAddress = inputValue[1];
549 
550  // if cue exists
551  if (!mCues.lookup(mCurrent, v)) {
552 
553  mCurrentCue = v[0];
554 
555  return mCurrentCue.send(kTTSym_Recall, anAddress);
556  }
557 
558  return kTTErrGeneric;
559 }
560 
561 TTErr TTCueManager::Output(const TTValue& inputValue, TTValue& outputValue)
562 {
563  TTValue v, none;
564  TTSymbol anAddress = kTTAdrsRoot;
565 
566  if (inputValue.size() >= 1) {
567 
568  // get cue name
569  if (inputValue[0].type() == kTypeSymbol) {
570  mCurrent = inputValue[0];
571 
572  TTSymbol name;
573  for (TTUInt32 i = 0; i < mNames.size(); i++) {
574  name = mNames[i];
575  if (name == mCurrent) {
576  mCurrentPosition = i+1;
577  break;
578  }
579  }
580  }
581 
582  // get cue at position
583  if (inputValue[0].type() == kTypeInt32) {
584 
585  mCurrentPosition = inputValue[0];
586 
587  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
588  mCurrent = mNames[mCurrentPosition-1];
589  else
590  return kTTErrGeneric;
591  }
592  }
593 
594  // get address from where recall starts
595  if (inputValue.size() == 2)
596  if (inputValue[1].type() == kTypeSymbol)
597  anAddress = inputValue[1];
598 
599  // if cue exists
600  if (!mCues.lookup(mCurrent, v)) {
601 
602  mCurrentCue = v[0];
603 
604  return mCurrentCue.send("Output", anAddress);
605  }
606 
607  return kTTErrGeneric;
608 }
609 
610 TTErr TTCueManager::Interpolate(const TTValue& inputValue, TTValue& outputValue)
611 {
612  TTValue v1, v2;
613  TTUInt32 i1, i2;
614  TTSymbol name1, name2;
615  TTObject cue1, cue2;
616  TTFloat32 position;
617 
618  if (inputValue.size() == 3) {
619 
620  // get cues by name
621  if (inputValue[0].type() == kTypeSymbol && inputValue[1].type() == kTypeSymbol && inputValue[2].type() == kTypeFloat64) {
622 
623  name1 = inputValue[0] ;
624  name2 = inputValue[1] ;
625  position = inputValue[2] ;
626  }
627 
628  // get cues by position
629  else if (inputValue[0].type() == kTypeInt32 && inputValue[1].type() == kTypeInt32 && inputValue[2].type() == kTypeFloat64) {
630 
631  i1 = inputValue[0] ;
632  if (i1 >= 0 && i1 < mNames.size())
633  name1 = mNames[i1-1];
634  else
635  return kTTErrGeneric;
636 
637  i2 = inputValue[1];
638  if (i2 >= 0 && i2 < mNames.size())
639  name2 = mNames[i2-1];
640  else
641  return kTTErrGeneric;
642 
643  position = inputValue[2] ;
644  }
645 
646  // if cues exist
647  if (!mCues.lookup(name1, v1) && !mCues.lookup(name2, v2)) {
648 
649  cue1 = v1[0];
650  cue2 = v2[0];
651 
652  if (cue1.valid() && cue2.valid())
653  return TTCueInterpolate(cue1, cue2, position);
654  }
655  }
656 
657  return kTTErrGeneric;
658 }
659 
660 TTErr TTCueManager::Mix(const TTValue& inputValue, TTValue& outputValue)
661 {
662  TTInt32 i, mixSize;
663  TTUInt32 id;
664  TTSymbol name;
665  TTObject cue;
666  TTValue v, cues, factors;
667 
668  mixSize = inputValue.size() / 2;
669  if (inputValue.size() != mixSize * 2)
670  return kTTErrGeneric;
671 
672  for (i = 0; i < mixSize * 2; i = i+2) {
673 
674  if (inputValue[i].type() == kTypeSymbol && inputValue[i+1].type() == kTypeFloat64) {
675 
676  name = inputValue[i] ;
677  }
678  else if (inputValue[i].type() == kTypeInt32 && inputValue[i+1].type() == kTypeFloat64) {
679 
680  id = inputValue[i];
681  if (id > 0 && id <= mNames.size())
682  name = mNames[id-1];
683  else
684  return kTTErrGeneric;
685  }
686 
687  // if cue exist
688  if (!mCues.lookup(name, v)) {
689 
690  cue = v[0];
691 
692  if (cue.valid()) {
693  cues.append(cue);
694  factors.append(TTFloat64(inputValue[i+1]));
695  }
696  }
697  }
698 
699  return TTCueMix(cues, factors);
700 }
701 
702 TTErr TTCueManager::Move(const TTValue& inputValue, TTValue& outputValue)
703 {
704  TTList temp;
705  TTSymbol name;
706  TTUInt32 i, newPosition = 0;
707  TTValue v;
708 
709  if (inputValue.size() >= 1) {
710 
711  // get cue name
712  if (inputValue[0].type() == kTypeSymbol)
713  mCurrent = inputValue[0];
714 
715  // get cue at position
716  if (inputValue[0].type() == kTypeInt32) {
717 
718  mCurrentPosition = inputValue[0];
719 
720  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
721  mCurrent = mNames[mCurrentPosition-1];
722  else
723  return kTTErrGeneric;
724  }
725  }
726 
727  // get new position
728  if (inputValue.size() == 2)
729  if (inputValue[1].type() == kTypeInt32)
730  newPosition = inputValue[1] ;
731 
732  if (newPosition < 1 || newPosition > mNames.size())
733  return kTTErrGeneric;
734 
735  // if cue exists
736  if (!mCues.lookup(mCurrent, v)) {
737 
738  mCurrentCue = v[0];
739 
740  // copy all the mNames names into a TTList
741  // except the mCurrent
742  for (i = 0; i < mNames.size(); i++) {
743  name = mNames[i];
744 
745  if (name == mCurrent)
746  continue;
747 
748  v = TTValue(name);
749  temp.append(v);
750  }
751 
752  // insert the mCurrent
753  v = TTValue(mCurrent);
754  temp.insert(newPosition-1, v);
755  mNames.clear();
756 
757  // copy the TTList names into a newNames
758  for (temp.begin(); temp.end(); temp.next()) {
759  name = temp.current()[0];
760  mNames.append(name);
761  }
762 
763  mCurrentPosition = newPosition;
764 
765  notifyNamesObservers();
766 
767  return kTTErrNone;
768  }
769 
770  return kTTErrGeneric;
771 }
772 
773 TTErr TTCueManager::Delete(const TTValue& inputValue, TTValue& outputValue)
774 {
775  TTSymbol name;
776  TTValue v, newNames;
777 
778  if (inputValue.size() == 1) {
779 
780  // get cue name
781  if (inputValue[0].type() == kTypeSymbol)
782  mCurrent = inputValue[0];
783 
784  // get cue at position
785  if (inputValue[0].type() == kTypeInt32) {
786 
787  mCurrentPosition = inputValue[0];
788 
789  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
790  mCurrent = mNames[mCurrentPosition-1];
791  else
792  return kTTErrGeneric;
793  }
794  }
795 
796  // if cue exists
797  if (!mCues.lookup(mCurrent, v)) {
798 
799  mCues.remove(mCurrent);
800 
801  // remove the name without changing the order
802  for (TTUInt32 i = 0; i < mNames.size(); i++) {
803 
804  name = mNames[i];
805 
806  if (name != mCurrent)
807  newNames.append(name);
808  }
809 
810  mCurrentCue = TTObject();
811  mCurrent = kTTSymEmpty;
812  mCurrentPosition = 0;
813  mNames = newNames;
814 
815  notifyNamesObservers();
816 
817  return kTTErrNone;
818  }
819 
820  return kTTErrGeneric;
821 }
822 
823 TTErr TTCueManager::Order(const TTValue& inputValue, TTValue& outputValue)
824 {
825  TTSymbol name;
826  TTValue v, newNames;
827 
828  // check if each name is part of the list
829  for (TTUInt32 i = 0; i < inputValue.size(); i++) {
830 
831  name = inputValue[i];
832 
833  if (!mCues.lookup(name, v))
834  newNames.append(name);
835 
836  // update current position
837  if (name == mCurrent)
838  mCurrentPosition = i;
839  }
840 
841  // if the newNames size is not equal to the current name list
842  if (newNames.size() != mNames.size())
843  return kTTErrGeneric;
844 
845  mNames = newNames;
846 
847  return kTTErrNone;
848 }
849 
850 TTErr TTCueManager::Rename(const TTValue& inputValue, TTValue& outputValue)
851 {
852  TTSymbol name, newName;
853  TTUInt32 i;
854  TTValue v;
855 
856  if (inputValue.size() >= 1) {
857 
858  // get cue name
859  if (inputValue[0].type() == kTypeSymbol)
860  mCurrent = inputValue[0];
861 
862  // get cue at position
863  if (inputValue[0].type() == kTypeInt32) {
864 
865  mCurrentPosition = inputValue[0];
866 
867  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
868  mCurrent = mNames[mCurrentPosition-1];
869  else
870  return kTTErrGeneric;
871  }
872  }
873 
874  // get new name
875  if (inputValue.size() == 2)
876  if (inputValue[1].type() == kTypeSymbol)
877  newName = inputValue[1] ;
878 
879  if (newName == kTTSymEmpty)
880  return kTTErrGeneric;
881 
882  // if cue exists
883  if (!mCues.lookup(mCurrent, v)) {
884 
885  mCurrentCue = v[0];
886 
887  // replace the name in the hash table
888  mCues.remove(mCurrent);
889  mCues.append(newName, v);
890 
891  mCurrentCue.set(kTTSym_name, newName);
892 
893  // replace the name in the order
894  for (i = 0; i < mNames.size(); i++) {
895 
896  name = mNames[i];
897 
898  if (name == mCurrent) {
899  mNames[i] = newName;
900  break;
901  }
902  }
903 
904  mCurrent = newName;
905  mCurrentPosition = i+1;
906 
907  notifyNamesObservers();
908 
909  return kTTErrNone;
910  }
911 
912  return kTTErrGeneric;
913 }
914 
915 TTErr TTCueManager::Copy(const TTValue& inputValue, TTValue& outputValue)
916 {
917  TTObject aCueCopy;
918  TTSymbol nameCopy;
919  TTString s;
920  TTInt32 positionCopy;
921  TTValue v, none;
922 
923  if (inputValue.size() >= 1) {
924 
925  // get cue name
926  if (inputValue[0].type() == kTypeSymbol)
927  mCurrent = inputValue[0];
928 
929  // get cue at position
930  if (inputValue[0].type() == kTypeInt32) {
931 
932  mCurrentPosition = inputValue[0];
933 
934  if (mCurrentPosition > 0 && mCurrentPosition <= mNames.size())
935  mCurrent = mNames[mCurrentPosition-1];
936  else
937  return kTTErrGeneric;
938  }
939  }
940 
941  // if cue exists
942  if (!mCues.lookup(mCurrent, v)) {
943 
944  mCurrentCue = v[0];
945 
946  // create a new cue
947  aCueCopy = TTObject(kTTSym_Cue, mReturnLineCallback);
948 
949  // copy the current cue into
950  TTCueCopy(mCurrentCue, aCueCopy);
951 
952  // maybe there is a name for the copy
953  if (inputValue.size() >= 2) {
954 
955  if (inputValue[1].type() == kTypeSymbol)
956  nameCopy = inputValue[1] ;
957 
958  }
959  else {
960  // edit a name copy : current cue name - copy
961  s = mCurrent.c_str();
962  s += " - copy";
963  nameCopy = TTSymbol(s.data());
964  }
965 
966  // rename the copy
967  aCueCopy.set(kTTSym_name, nameCopy);
968 
969  // append the copy
970  v = TTValue(aCueCopy);
971  mCues.append(nameCopy, v);
972  mNames.append(nameCopy);
973  mCurrent = nameCopy;
974  mCurrentPosition = mNames.size();
975 
976  // maybe there is a position for the copy
977  if (inputValue.size() == 3) {
978 
979  if (inputValue[2].type() == kTypeInt32) {
980 
981  positionCopy = inputValue[2] ;
982 
983  v = (int)mCurrentPosition;
984  v.append((int)positionCopy);
985  return Move(v, none);
986  }
987  }
988  else
989  return notifyNamesObservers();
990  }
991 
992  return kTTErrGeneric;
993 }
994 
995 TTErr TTCueManager::Optimize(const TTValue& inputValue, TTValue& outputValue)
996 {
997  TTUInt32 i;
998  TTSymbol nameToMerge, nameToOptimize;
999  TTObject aCueToMerge, aCueToOptimize, stateCue, optimizedCue;
1000  TTValue v;
1001  TTErr err;
1002 
1003  if (!inputValue.size())
1004  return kTTErrGeneric;
1005 
1006  // create an empty cue to merge the current state into
1007  stateCue = TTObject(kTTSym_Cue, mReturnLineCallback);
1008 
1009  // merge and optimize each cues except the first
1010  for (i = 1; i < inputValue.size(); i++) {
1011 
1012  if (inputValue[i-1].type() == kTypeSymbol && inputValue[i].type() == kTypeSymbol) {
1013 
1014  nameToMerge = inputValue[i-1];
1015  nameToOptimize = inputValue[i];
1016 
1017  // if cue exists
1018  if (!mCues.lookup(nameToMerge, v))
1019  aCueToMerge = v[0];
1020 
1021  if (!mCues.lookup(nameToOptimize, v))
1022  aCueToOptimize = v[0];
1023 
1024  if (aCueToMerge.valid() && aCueToOptimize.valid()) {
1025 
1026  // merge the cue before into the current state
1027  TTCueMerge(aCueToMerge, stateCue);
1028 
1029  // create an empty cue to store the result of optimization
1030  optimizedCue = TTObject(kTTSym_Cue, mReturnLineCallback);
1031  optimizedCue.set(kTTSym_name, nameToOptimize);
1032  optimizedCue.set(kTTSym_address, mAddress);
1033 
1034  // optimize the cue considering the current state
1035  err = TTCueOptimize(aCueToOptimize, stateCue, optimizedCue);
1036 
1037  if (!err) {
1038 
1039  // replace the cue to optimize by the optimized cue
1040  mCues.remove(nameToOptimize);
1041  mCues.append(nameToOptimize, optimizedCue);
1042  }
1043  }
1044  }
1045  }
1046 
1047  return kTTErrNone;
1048 }
1049 
1050 TTErr TTCueManager::WriteAsXml(const TTValue& inputValue, TTValue& outputValue)
1051 {
1052  TTObject o = inputValue[0];
1053  TTXmlHandlerPtr aXmlHandler = (TTXmlHandlerPtr)o.instance();
1054  if (!aXmlHandler)
1055  return kTTErrGeneric;
1056 
1057  TTSymbol cueName;
1058  TTValue v;
1059  TTUInt32 i;
1060 
1061  for (i = 0; i < mNames.size(); i++) {
1062 
1063  cueName = mNames[i];
1064  if (!mCues.lookup(cueName, v)) {
1065 
1066  TTValue name = cueName;
1067  name.toString(NO); //no quotes
1068  TTString s = TTString(name[0]);
1069 
1070  // start to write a cue
1071  xmlTextWriterStartElement((xmlTextWriterPtr)aXmlHandler->mWriter, BAD_CAST "cue");
1072  xmlTextWriterWriteAttribute((xmlTextWriterPtr)aXmlHandler->mWriter, BAD_CAST "name", BAD_CAST s.c_str());
1073 
1074  aXmlHandler->setAttributeValue(kTTSym_object, v);
1075  aXmlHandler->sendMessage(TTSymbol("Write"));
1076 
1077  // end to write a cue
1078  xmlTextWriterEndElement((xmlTextWriterPtr)aXmlHandler->mWriter);
1079  }
1080  }
1081 
1082  return kTTErrNone;
1083 }
1084 
1085 TTErr TTCueManager::ReadFromXml(const TTValue& inputValue, TTValue& outputValue)
1086 {
1087  TTObject o = inputValue[0];
1088  TTXmlHandlerPtr aXmlHandler = (TTXmlHandlerPtr)o.instance();
1089  if (!aXmlHandler)
1090  return kTTErrGeneric;
1091 
1092  TTValue v, args;
1093 
1094  // Switch on the name of the XML node
1095 
1096  // Starts file reading : clear the cue list
1097  if (aXmlHandler->mXmlNodeName == kTTSym_xmlHandlerReadingStarts) {
1098  Clear();
1099  return kTTErrNone;
1100  }
1101 
1102  // Ends file reading : bind on first cue
1103  if (aXmlHandler->mXmlNodeName == kTTSym_xmlHandlerReadingEnds) {
1104 
1105  // try to set the former current as current
1106  mCurrent = mLastCurrent;
1107  if (!mCues.lookup(mCurrent, v))
1108  mCurrentCue = v[0];
1109 
1110  // else bind on the first cue
1111  else if (mNames.size()) {
1112 
1113  mCurrent = mNames[0];
1114  if (!mCues.lookup(mCurrent, v))
1115  mCurrentCue = v[0];
1116  }
1117 
1118  if (mCurrentCue.valid()) {
1119 
1120  // send the end file to the cue to process the namespace
1121  aXmlHandler->setAttributeValue(kTTSym_object, mCurrentCue);
1122  aXmlHandler->sendMessage(TTSymbol("Read"));
1123  }
1124 
1125  notifyNamesObservers();
1126 
1127  return kTTErrNone;
1128  }
1129 
1130  // Flag node :
1131  if (aXmlHandler->mXmlNodeName == TTSymbol("cue")) {
1132 
1133  if (!aXmlHandler->mXmlNodeStart)
1134  return kTTErrNone;
1135 
1136  // Get cue name
1137  if (!aXmlHandler->getXmlAttribute(kTTSym_name, v, YES)) {
1138 
1139  if (v.size() == 1) {
1140  if (v[0].type() == kTypeSymbol) {
1141 
1142  mCurrent = v[0];
1143 
1144  // Create a new cue
1145  mCurrentCue = TTObject(kTTSym_Cue, mReturnLineCallback);
1146 
1147  mCurrentCue.set(kTTSym_name, mCurrent);
1148  mCurrentCue.set(kTTSym_address, mAddress);
1149 
1150  mCues.append(mCurrent, mCurrentCue);
1151  mNames.append(mCurrent);
1152  }
1153  }
1154  }
1155 
1156  // go back to the element to allow the cue to parse it
1157  xmlTextReaderMoveToElement((xmlTextReaderPtr)aXmlHandler->mReader);
1158  }
1159 
1160  // edit the current cue from the xml file using the XmlHandler
1161  if (mCurrentCue.valid()) {
1162 
1163  aXmlHandler->setAttributeValue(kTTSym_object, mCurrentCue);
1164  return aXmlHandler->sendMessage(TTSymbol("Read"));
1165  }
1166  else
1167  return kTTErrGeneric;
1168 }
1169 
1170 TTErr TTCueManager::WriteAsText(const TTValue& inputValue, TTValue& outputValue)
1171 {
1172  TTObject o = inputValue[0];
1173  TTTextHandlerPtr aTextHandler = (TTTextHandlerPtr)o.instance();
1174  if (!aTextHandler)
1175  return kTTErrGeneric;
1176 
1177  TTString *buffer;
1178  TTSymbol cueName;
1179  TTValue v;
1180 
1181  buffer = aTextHandler->mWriter;
1182 
1183  for (TTUInt32 i = 0; i < mNames.size(); i++) {
1184 
1185  cueName = mNames[i];
1186  if (!mCues.lookup(cueName, v)) {
1187 
1188  aTextHandler->setAttributeValue(kTTSym_object, v);
1189  aTextHandler->sendMessage(TTSymbol("Write"));
1190 
1191  *buffer += "\n";
1192  }
1193  }
1194 
1195  return kTTErrNone;
1196 }
1197 
1198 TTErr TTCueManager::ReadFromText(const TTValue& inputValue, TTValue& outputValue)
1199 {
1200  TTObject o = inputValue[0];
1201  TTTextHandlerPtr aTextHandler = (TTTextHandlerPtr)o.instance();
1202  if (!aTextHandler)
1203  return kTTErrGeneric;
1204 
1205  TTDictionaryBasePtr line;
1206  TTSymbol flagName;
1207  TTValue v, args;
1208 
1209  // if it is the first line :
1210  if (aTextHandler->mFirstLine) {
1211 
1212  mLastCurrent = mCurrent;
1213  Clear();
1214  }
1215 
1216  // parse the buffer line into TTDictionary
1217  line = TTScriptParseLine(*(aTextHandler->mLine));
1218 
1219  if (line) {
1220 
1221  // replace the buffer line value by the parsed line dictionary
1222  delete aTextHandler->mLine;
1223  aTextHandler->mLine = new TTValue((TTPtr)line);
1224 
1225  // match cue flag line : - cue name
1226  if (line->getSchema() == kTTSym_flag) {
1227 
1228  line->lookup(kTTSym_name, v);
1229  flagName = v[0];
1230 
1231  if (flagName == TTSymbol("cue")) {
1232 
1233  // get cue name
1234  if (!line->getValue(v)) {
1235 
1236  // convert in string in case of int or float name with no quotes for internal symbol
1237  v.toString(NO);
1238  mCurrent = TTSymbol(TTString(v[0]));
1239 
1240  if (mCurrent != kTTSymEmpty) {
1241 
1242  // Create a new cue
1243  mCurrentCue = TTObject(kTTSym_Cue, mReturnLineCallback);
1244 
1245  mCurrentCue.set(kTTSym_name, mCurrent);
1246  mCurrentCue.set(kTTSym_address, mAddress);
1247 
1248  mCues.append(mCurrent, mCurrentCue);
1249  mNames.append(mCurrent);
1250  }
1251  }
1252  }
1253  }
1254 
1255  // edit the current cue with the line
1256  if (mCurrentCue.valid()) {
1257 
1258  aTextHandler->setAttributeValue(kTTSym_object, mCurrentCue);
1259  return aTextHandler->sendMessage(TTSymbol("Read"));
1260  }
1261  }
1262 
1263  // if it is the last line : bind on the first cue
1264  if (aTextHandler->mLastLine) {
1265 
1266  // théo - since the workshop in june 2014 in Albi we decide to force the script to be flattened
1267  // but we should review all the #TTCue and #TTScript architecture to improve this
1268  for (TTUInt32 i = 0; i < mNames.size(); i++) {
1269 
1270  TTSymbol cueName = mNames[i];
1271 
1272  if (!mCues.lookup(cueName, v)) {
1273 
1274  TTObject aCue = v[0];
1275  TTValue none;
1276  aCue.send("ReadFromText", inputValue);
1277  }
1278  }
1279 
1280  // try to set the former current as current
1281  mCurrent = mLastCurrent;
1282  if (!mCues.lookup(mCurrent, v))
1283  mCurrentCue = v[0];
1284 
1285  // else bind on the first cue
1286  else if (mNames.size()) {
1287 
1288  mCurrent = mNames[0];
1289  if (!mCues.lookup(mCurrent, v))
1290  mCurrentCue = v[0];
1291  }
1292 
1293  notifyNamesObservers();
1294 
1295  return kTTErrNone;
1296  }
1297 
1298 
1299  return kTTErrGeneric;
1300 }
1301 
1302 TTErr TTCueManager::notifyNamesObservers()
1303 {
1304  TTAttributePtr anAttribute = NULL;
1305  TTErr err;
1306 
1307  err = this->findAttribute(kTTSym_names, &anAttribute);
1308 
1309  if (!err)
1310  anAttribute->sendNotification(kTTSym_notify, mNames); // we use kTTSym_notify because we know that observers are TTCallback
1311 
1312  return kTTErrNone;
1313 }
1314 
1315 TTAddressItemPtr TTCueManager::getNamespace()
1316 {
1317  TTValue v;
1318  TTAddressItemPtr aSelection = TTModularSelectionLookup(mNamespace);
1319 
1320  if (!aSelection) {
1321 
1322  TTModularApplicationManager->getAttributeValue(TTSymbol("applicationNames"), v);
1323 
1324  // fill the default namespace with the local directory
1325  if (v.size() == 1) {
1326 
1327  accessApplicationLocalDirectory->fillAddressItem(mDefaultNamespace);
1328 
1329  }
1330  // fill the default namespace with all directories
1331  else {
1332 
1333  TTSymbol applicationName;
1334  TTAddressItemPtr applicationItem;
1335 
1336  for (TTUInt32 i = 0; i < v.size(); i++) {
1337 
1338  applicationName = v[i];
1339 
1340  mDefaultNamespace->append(TTAddress(applicationName), &applicationItem);
1341 
1342  accessApplicationDirectory(applicationName)->fillAddressItem(applicationItem);
1343  }
1344  }
1345 
1346  aSelection = mDefaultNamespace;
1347  }
1348 
1349  return aSelection;
1350 }
1351 
1352 #if 0
1353 #pragma mark -
1354 #pragma mark Some Methods
1355 #endif
TTErr sendMessage(const TTSymbol name)
TODO: Document this function.
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
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
#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.
void copyFrom(const TTValue &obj, TTUInt16 index)
Copy a value starting from an index until the last element.
Definition: TTValue.h:147
const char * c_str() const
Return a pointer to the internal C-string.
Definition: TTString.h:83
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Definition: TTAddress.h:29
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTErr getXmlAttribute(TTSymbol attributeName, TTValue &returnedValue, TTBoolean addQuote=NO, TTBoolean numberAsSymbol=NO)
Get the value of an xml element attribute.
size_type size() const noexcept
Return the number of elements.
TTAddressItemPtr TTMODULAR_EXPORT TTModularSelectionLookup(const TTSymbol selectionName)
Get a selection or create one if it doesn't exist yet.
Definition: TTModular.cpp:110
TTErr sendNotification(const TTSymbol name, const TTValue &arguments)
Send a notification.
TTErr getAttributeValue(const TTSymbol name, TTValue &value)
Get an attribute value for an object.
this flag means that an address have no leading slash
Definition: TTAddressBase.h:64
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
const TTSymbol getSchema() const
TODO: Add documentation.
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
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
Definition: TTValue.h:243
#define addAttributeWithGetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:38
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTMODULAR_EXPORT TTApplicationManagerPtr TTModularApplicationManager
Export a pointer to a TTApplicationManager instance.
Definition: TTModular.cpp:34
A CueManager Object.
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
TTBoolean mXmlNodeStart
true if the Reader starts to read a Node
Definition: TTXmlHandler.h:65
float TTFloat32
32 bit floating point number
Definition: TTBase.h:187
void get(const TTUInt16 index, T &returnedElementValue) const
DEPRECATED.
Definition: TTValue.h:591
#define accessApplicationDirectory(applicationName)
Access to an application directory by name.
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
TTErr lookup(const TTSymbol key, TTValue &value) const
Find the value for the given key.
std::int32_t TTInt32
32 bit signed integer
Definition: TTBase.h:177
void set(const TTUInt16 index, const T &anElementValue)
DEPRECATED.
Definition: TTValue.h:569
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
TTAddressType getType()
Get the type.
Definition: TTAddress.h:136
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
TTSymbol mXmlNodeName
the Node name being read by the Reader
Definition: TTXmlHandler.h:67
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
Pointer type.
Definition: TTBase.h:284
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
Definition: TTAttribute.h:47
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:19
Write / Read mecanism.
Definition: TTXmlHandler.h:48
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
The TTString class is used to represent a string.
Definition: TTString.h:34
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
#define accessApplicationLocalDirectory
Access to the local application directory.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr getValue(TTValue &returnedValue) const
TODO: Add documentation.
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37