Jamoma API  0.6.0.a19
TTPreset.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A Preset 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 "TTPreset.h"
18 
19 #define thisTTClass TTPreset
20 #define thisTTClassName "Preset"
21 #define thisTTClassTags "preset"
22 
23 TT_MODULAR_CONSTRUCTOR,
24 mName(kTTSymEmpty),
25 mDescription("something about this preset"),
26 mAddress(kTTAdrsEmpty),
27 mDirectory(NULL)
28 {
30  addAttribute(Description, kTypeSymbol);
32 
33  addMessage(Clear);
34  addMessage(Store);
35  addMessage(Update);
38 
39  // needed to be handled by a TTXmlHandler
40  addMessageWithArguments(WriteAsXml);
41  addMessageProperty(WriteAsXml, hidden, YES);
42  addMessageWithArguments(ReadFromXml);
43  addMessageProperty(ReadFromXml, hidden, YES);
44 
45  // needed to be handled by a TTTextHandler
46  addMessageWithArguments(WriteAsText);
47  addMessageProperty(WriteAsText, hidden, YES);
48  addMessageWithArguments(ReadFromText);
49  addMessageProperty(ReadFromText, hidden, YES);
50 
51  mScript = TTObject(kTTSym_Script, arguments);
52 }
53 
54 TTPreset::~TTPreset()
55 {
56  ;
57 }
58 
59 TTErr TTPreset::setAddress(const TTValue& value)
60 {
61  Clear();
62  mAddress = value[0];
63 
64  mDirectory = accessApplicationDirectoryFrom(mAddress);
65 
66  if (mDirectory) {
67 
68  mScript.set(kTTSym_address, mAddress);
69  return kTTErrNone;
70  }
71  else
72  return kTTErrGeneric; // else wait for directory or not ?
73 }
74 
75 TTErr TTPreset::Store()
76 {
77  TTNodePtr aNode;
78  TTObject anObject;
79  TTList aNodeList, allObjectNodes;
80  TTAddress aRelativeAddress;
81  TTValue v, parsedLine;
82 
83  Clear();
84 
85  if (mDirectory) {
86 
87  // 1. Append a preset flag with the name
88  v = TTValue(TTSymbol("preset"));
89  v.append(mName);
90  mScript.send("AppendFlag", v, parsedLine);
91 
92  // 2. Append a description flag with the description
93  v = TTValue(TTSymbol("description"));
94  v.append(mDescription);
95  mScript.send("AppendFlag", v, parsedLine);
96 
97  // 3. Append a comment line at the beginning
98  v = TTValue(TTSymbol("###########################################"));
99  mScript.send("AppendComment", v, parsedLine);
100 
101  // 4. Append an empty comment line
102  v.clear();
103  mScript.send("AppendComment", v, parsedLine);
104 
105  // 5. Look for all Objects under the address into the directory (and sort them using object priority order then alphabetical order)
106  mDirectory->Lookup(mAddress, aNodeList, &aNode);
107  mDirectory->LookFor(&aNodeList, &TTPresetTestObject, NULL, allObjectNodes, &aNode, 0, &compareNodePriorityThenNameThenInstance);
108 
109  // 7. Append a script line for each object found
110  for (allObjectNodes.begin(); allObjectNodes.end(); allObjectNodes.next()) {
111 
112  aNode = TTNodePtr((TTPtr)allObjectNodes.current()[0]);
113 
114  // get relative address
115  aNode->getAddress(aRelativeAddress, mAddress);
116 
117  // get object
118  anObject = aNode->getObject();
119 
120  // append command line
121  if (anObject.valid()) {
122 
123  // DATA case
124  if (anObject.name() == kTTSym_Data) {
125 
126  v.clear();
127  anObject.get(kTTSym_value, v);
128 
129  if (v.empty())
130  continue;
131 
132  v.prepend(aRelativeAddress);
133  mScript.send("AppendCommand", v, parsedLine);
134  }
135  }
136  }
137 
138  // 8. Append an empty comment line
139  v.clear();
140  mScript.send("AppendComment", v, parsedLine);
141 
142  // 9. Append a comment line at the end
143  v = TTValue(TTSymbol("###########################################"));
144  mScript.send("AppendComment", v, parsedLine);
145 
146  return kTTErrNone;
147  }
148  else
149  return kTTErrGeneric;
150 }
151 
152 TTErr TTPreset::Update()
153 {
154  TTValue v, none;
155  TTBoolean flattened;
156 
157  // is the preset already flattened ?
158  mScript.get(kTTSym_flattened, v);
159  flattened = v[0];
160 
161  if (!flattened)
162  mScript.send(kTTSym_Flatten, mAddress);
163 
164  return processUpdate(mScript);
165 }
166 
167 TTErr TTPreset::processUpdate(TTObject& aScript)
168 {
169  TTListPtr lines;
170  TTDictionaryBasePtr aLine;
171  TTAddress anAddress;
172  TTNodePtr aNode;
173  TTObject anObject;
174  TTSymbol service;
175  TTValue v;
176  TTErr err;
177 
178  aScript.get("flattenedLines", v);
179  lines = TTListPtr((TTPtr)v[0]);
180 
181  // lookat each line of the script
182  for (lines->begin(); lines->end(); lines->next()) {
183 
184  aLine = TTDictionaryBasePtr((TTPtr)lines->current()[0]);
185 
186  // if it is a Data object
187  if (!aLine->lookup(kTTSym_target, v)) {
188 
189  anAddress = v[0];
190  err = accessApplicationDirectoryFrom(anAddress)->getTTNode(anAddress, &aNode);
191 
192  if (!err) {
193 
194  anObject = aNode->getObject();
195 
196  if (anObject.valid()) {
197 
198  if (anObject.name() == kTTSym_Data) {
199 
200  // get his service attribute value
201  anObject.get(kTTSym_service, v);
202  service = v[0];
203 
204  // update only parameters
205  if (service == kTTSym_parameter) {
206 
207  // get his current value
208  err = anObject.get(kTTSym_value, v);
209 
210  if (!err) {
211 
212  // replace the former value
213  aLine->remove(kTTSym_value);
214  aLine->append(kTTSym_value, v);
215  }
216  }
217  }
218  }
219  }
220  }
221  }
222 
223  return kTTErrNone;
224 }
225 
226 TTErr TTPreset::Clear()
227 {
228  return mScript.send("Clear");
229 }
230 
231 TTErr TTPreset::Recall(const TTValue& inputValue, TTValue& outputValue)
232 {
233  TTAddress anAddress = kTTAdrsRoot;
234  TTBoolean flattened;
235  TTValue v, none;
236 
237  if (inputValue.size() == 1)
238  if (inputValue[0].type() == kTypeSymbol)
239  anAddress = inputValue[0];
240 
241  // is the cue already flattened ?
242  mScript.get(kTTSym_flattened, v);
243  flattened = v[0];
244 
245  if (!flattened)
246  mScript.send(kTTSym_Flatten, mAddress);
247 
248  // if an address is passed, run the line at address
249  if (anAddress != kTTAdrsRoot)
250  return mScript.send("RunCommand", inputValue);
251 
252  // else run all the script
253  else
254  return mScript.send(kTTSym_Run, mAddress);
255 }
256 
257 TTErr TTPreset::Output(const TTValue& inputValue, TTValue& outputValue)
258 {
259  TTAddress anAddress = kTTAdrsRoot;
260  TTBoolean flattened;
261  TTValue v, none;
262 
263  if (inputValue.size() == 1)
264  if (inputValue[0].type() == kTypeSymbol)
265  anAddress = inputValue[0];
266 
267  // is the preset already flattened ?
268  mScript.get(kTTSym_flattened, v);
269  flattened = v[0];
270 
271  if (!flattened)
272  mScript.send(kTTSym_Flatten, kTTAdrsRoot);
273 
274  // if an address is passed, dump the line at address
275  if (anAddress != kTTAdrsRoot)
276  return mScript.send("DumpLine", inputValue);
277 
278  // else dump all the script
279  else
280  return mScript.send(kTTSym_Dump, inputValue);
281 }
282 
283 TTErr TTPreset::WriteAsXml(const TTValue& inputValue, TTValue& outputValue)
284 {
285  TTObject o = inputValue[0];
286  TTXmlHandlerPtr aXmlHandler = (TTXmlHandlerPtr)o.instance();
287  if (!aXmlHandler)
288  return kTTErrGeneric;
289 
290  // use WriteAsXml of the script
291  aXmlHandler->setAttributeValue(kTTSym_object, mScript);
292  aXmlHandler->sendMessage(TTSymbol("Write"));
293 
294  return kTTErrNone;
295 }
296 
297 TTErr TTPreset::ReadFromXml(const TTValue& inputValue, TTValue& outputValue)
298 {
299  TTObject o = inputValue[0];
300  TTXmlHandlerPtr aXmlHandler = (TTXmlHandlerPtr)o.instance();
301  if (!aXmlHandler)
302  return kTTErrGeneric;
303 
304  TTValue v, parsedLine;
305 
306  // Preset node : append a preset flag with the name
307  if (aXmlHandler->mXmlNodeName == TTSymbol("preset")) {
308 
309  if (!aXmlHandler->mXmlNodeStart)
310  return kTTErrNone;
311 
312  v = TTValue("preset", mName);
313  mScript.send("AppendFlag", v, parsedLine);
314 
315  return kTTErrNone;
316  }
317 
318  // use ReadFromXml of the script
319  aXmlHandler->setAttributeValue(kTTSym_object, mScript);
320  aXmlHandler->sendMessage(TTSymbol("Read"));
321 
322  return kTTErrNone;
323 }
324 
325 TTErr TTPreset::WriteAsText(const TTValue& inputValue, TTValue& outputValue)
326 {
327  TTObject o = inputValue[0];
328  TTTextHandlerPtr aTextHandler = (TTTextHandlerPtr)o.instance();
329  if (!aTextHandler)
330  return kTTErrGeneric;
331 
332  TTValue v;
333 
334  // théo - since the workshop in june 2014 in Albi we decide to force the script to be flattened
335  // but we should review all the #TTCue and #TTScript architecture to improve this
336  // so here we need to unflatten the script before to write it ...
337  TTBoolean flattened;
338 
339  // is the preset already flattened ?
340  mScript.get(kTTSym_flattened, v);
341  flattened = v[0];
342 
343  if (flattened)
344  mScript.send("Unflatten");
345 
346  // use WriteAsBuffer of the script
347  aTextHandler->setAttributeValue(kTTSym_object, mScript);
348  aTextHandler->sendMessage(TTSymbol("Write"));
349 
350  return kTTErrNone;
351 }
352 
353 TTErr TTPreset::ReadFromText(const TTValue& inputValue, TTValue& outputValue)
354 {
355  TTObject o = inputValue[0];
356  TTTextHandlerPtr aTextHandler = (TTTextHandlerPtr)o.instance();
357  if (!aTextHandler)
358  return kTTErrGeneric;
359 
360  TTDictionaryBasePtr line;
361  TTValue v;
362 
363  // if it is the first line :
364  if (aTextHandler->mFirstLine)
365  Clear();
366 
367  if (inputValue.size() == 0)
368  return kTTErrGeneric;
369 
370  // if needed : parse the buffer line into TTDictionary
371  if ((*(aTextHandler->mLine))[0].type() != kTypePointer) {
372 
373  line = TTScriptParseLine(*(aTextHandler->mLine));
374 
375  if (line)
376 
377  // replace the buffer line value by the parsed line dictionary
378  aTextHandler->mLine = new TTValue((TTPtr)line);
379  }
380  else
381  line = TTDictionaryBasePtr((TTPtr)aTextHandler->mLine[0]);
382 
383  // match description or tag flag lines :
384  if (line) {
385 
386  if (line->getSchema() == kTTSym_flag) {
387 
388  line->lookup(kTTSym_name, v);
389  TTSymbol flagName = v[0];
390 
391  if (flagName == TTSymbol("description")) {
392 
393  // get description
394  if (!line->getValue(v)) {
395 
396  mDescription = v[0];
397  }
398  }
399  }
400  }
401 
402  // use ReadFromText of the script
403  aTextHandler->setAttributeValue(kTTSym_object, mScript);
404  aTextHandler->sendMessage(TTSymbol("Read"));
405 
406  return kTTErrNone;
407 }
408 
409 #if 0
410 #pragma mark -
411 #pragma mark Some Methods
412 #endif
413 
415 {
416  TTObject o;
417  TTValue v;
418  TTSymbol s;
419 
420  // Here we decide to keep nodes which binds on :
421  // - Data with @service == parameter
422  o = node->getObject();
423  if (o.valid()) {
424 
425  if (o.name() == kTTSym_Data) {
426  o.get(kTTSym_service, v);
427  s = v[0];
428  return s == kTTSym_parameter;
429  }
430  }
431 
432  return NO;
433 }
434 
435 TTErr TTPresetInterpolate(TTObject preset1, TTObject preset2, TTFloat64 position)
436 {
437  TTBoolean flattened1, flattened2;
438  TTValue v, none;
439 
440  // is the preset1 already flattened ?
441  TTPresetPtr(preset1.instance())->mScript.get(kTTSym_flattened, v);
442  flattened1 = v[0];
443 
444  if (!flattened1)
445  TTPresetPtr(preset1.instance())->mScript.send(kTTSym_Flatten, TTPresetPtr(preset1.instance())->mAddress);
446 
447  // is the preset2 already flattened ?
448  TTPresetPtr(preset2.instance())->mScript.get(kTTSym_flattened, v);
449  flattened2 = v[0];
450 
451  if (!flattened2)
452  TTPresetPtr(preset2.instance())->mScript.send(kTTSym_Flatten, TTPresetPtr(preset2.instance())->mAddress);
453 
454  return TTScriptInterpolate(TTPresetPtr(preset1.instance())->mScript, TTPresetPtr(preset2.instance())->mScript, position);
455 }
456 
457 TTErr TTPresetMix(const TTValue& presets, const TTValue& factors)
458 {
459  TTObject aPreset;
460  TTValue scripts;
461  TTBoolean flattened;
462  TTValue v, none;
463  TTUInt32 i;
464 
465  for (i = 0; i < presets.size(); i++) {
466 
467  aPreset = presets[i];
468 
469  // is the preset1 already flattened ?
470  TTPresetPtr(aPreset.instance())->mScript.get(kTTSym_flattened, v);
471  flattened = v[0];
472 
473  if (!flattened)
474  TTPresetPtr(aPreset.instance())->mScript.send(kTTSym_Flatten, TTPresetPtr(aPreset.instance())->mAddress);
475 
476  scripts.append(TTPresetPtr(aPreset.instance())->mScript);
477  }
478 
479  return TTScriptMix(scripts, factors);
480 }
481 
482 
483 TTErr TTPresetCopy(TTObject aPresetToCopy, TTObject aPresetCopy)
484 {
485  TTPresetPtr(aPresetCopy.instance())->mName = TTPresetPtr(aPresetToCopy.instance())->mName;
486  TTPresetPtr(aPresetCopy.instance())->mAddress = TTPresetPtr(aPresetToCopy.instance())->mAddress;
487  TTPresetPtr(aPresetCopy.instance())->mDirectory = TTPresetPtr(aPresetToCopy.instance())->mDirectory;
488  return TTScriptCopy(TTPresetPtr(aPresetToCopy.instance())->mScript, TTPresetPtr(aPresetCopy.instance())->mScript);
489 }
TTErr sendMessage(const TTSymbol name)
TODO: Document this function.
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
Definition: TTBase.h:167
#define accessApplicationDirectoryFrom(anAddress)
Access to an application directory using an address.
TTDictionaryBase * TTDictionaryBasePtr
Pointer to a TTDictionary.
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTBoolean TTPresetTestObject(TTNodePtr node, TTPtr args)
Return Yes if the node have to be part of the preset.
Definition: TTPreset.cpp:414
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
Definition: TTNode.h:59
A type that contains a key and a value.
A Preset Object.
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
TTObject & getObject()
Get the object binded by this node.
Definition: TTNode.cpp:468
size_type size() const noexcept
Return the number of elements.
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
TTErr Lookup(TTAddress anAddress, TTList &returnedTTNodes, TTNodePtr *firstReturnedTTNode)
Find TTNodes by address.
double TTFloat64
64 bit floating point number
Definition: TTBase.h:188
void prepend(const TTValue &aValueToPrepend)
Insert another TTValue before the first element.
Definition: TTValue.h:162
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
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTSymbol name() const
Return the name of this class.
Definition: TTObject.cpp:129
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
#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.
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
TTErr LookFor(TTListPtr whereToSearch, TTBoolean(*testFunction)(TTNodePtr node, TTPtr args), void *argument, TTList &returnedTTNodes, TTNodePtr *firstReturnedTTNode, TTUInt8 depthLimit=0, TTBoolean(*comparisonFunction)(TTValue &v1, TTValue &v2)=NULL)
Find TTNodes by testing each TTNodes below an address.
TTErr getAddress(TTAddress &returnedAddress, TTAddress from=kTTAdrsEmpty)
Get the address of the node.
Definition: TTNode.cpp:478
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.
TTPreset ...
Definition: TTPreset.h:30
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
TTSymbol mXmlNodeName
the Node name being read by the Reader
Definition: TTXmlHandler.h:67
TTErr get(const TTSymbol aName, T &aReturnedValue)
Get an attribute value for an object This is the same as calling getAttributeValue().
Definition: TTObjectBase.h:280
Pointer type.
Definition: TTBase.h:284
TTErr remove(const TTSymbol key)
Remove an item from the hash table.
#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
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
[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