Jamoma API  0.6.0.a19
TTMirror.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A Mirror 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 "TTMirror.h"
18 
19 #define thisTTClass TTMirror
20 #define thisTTClassName "Mirror"
21 #define thisTTClassTags "mirror"
22 
23 TT_MODULAR_CONSTRUCTOR,
24 mType(kTTSymEmpty)
25 {
26  TTValue attributeNames, messageNames, none;
27  TTSymbol name;
28  TTAttributePtr anAttribute;
29  TTAttributeFlags attributeFlags = kTTAttrPassObject;
30  TTMessagePtr aMessage;
31 
32  if (arguments.size() >= 1)
33  mType = arguments[0];
34 
35  if (mType != kTTSymEmpty) {
36 
37  if (arguments.size() >= 2)
38  mGetAttributeCallback = arguments[1];
39 
40  if (arguments.size() >= 3)
41  mSetAttributeCallback = arguments[2];
42 
43  if (arguments.size() >= 4)
44  mSendMessageCallback = arguments[3];
45 
46  if (arguments.size() >= 5)
47  mListenAttributeCallback = arguments[4];
48 
49  // if the class exist
50  if (!ttEnvironment->isClassRegistered(mType)) {
51 
52  TTObject anObject = TTObject(mType);
53 
54  if (anObject.valid()) {
55 
56  anObject.attributes(attributeNames);
57  for (TTUInt32 i = 0; i < attributeNames.size(); i++) {
58 
59  anAttribute = NULL;
60  name = attributeNames[i];
61  anObject.instance()->getAttribute(name, &anAttribute);
62 
63  if (mGetAttributeCallback.valid())
64  addMirrorAttribute(name, anAttribute->type);
65 
66  // else cache the attribute value
67  else {
68 
69  addMirrorCachedAttribute(name, anAttribute->type);
70 
71  mAttributeValueCache.append(name, none);
72  }
73 
74  setAttributeGetterFlags(name, attributeFlags);
75  setAttributeSetterFlags(name, attributeFlags);
76 
77  // TODO : addMirrorAttributeProperty
78  //addMirrorAttributeProperty(name, readOnly, anAttribute->readOnly);
79  }
80 
81  anObject.messages(messageNames);
82  for (TTUInt32 i = 0; i < messageNames.size(); i++) {
83 
84  name = messageNames[i];
85  anObject.instance()->getMessage(name, &aMessage);
86 
87  addMirrorMessage(name, aMessage->flags);
88 
89  // TODO : addMirrorMessageProperty
90  }
91  }
92  }
93  }
94 
95  addMessageWithArguments(AttributesInstantiate);
96  addMessageWithArguments(MessagesInstantiate);
97 
98  addMessageWithArguments(AttributeCache);
99  addMessageWithArguments(AttributeUncache);
100 }
101 
102 TTMirror::~TTMirror()
103 {
104  ;
105 }
106 
107 TTSymbol TTMirror::getName()
108 {
109  return mType;
110 }
111 
112 TTErr TTMirror::AttributesInstantiate(const TTValue& inputValue, TTValue& outputValue)
113 {
114  TTAttributeFlags attributeFlags = kTTAttrPassObject;
115  TTValue none;
116 
117  for (TTUInt32 i = 0; i < inputValue.size(); i++) {
118 
119  if (inputValue[i].type() == kTypeSymbol) {
120 
121  TTSymbol name = inputValue[i];
122 
123  if (mGetAttributeCallback.valid())
125 
126  // else cache the attribute value
127  else {
128 
130 
131  mAttributeValueCache.append(name, none);
132  }
133 
134  setAttributeGetterFlags(name, attributeFlags);
135  setAttributeSetterFlags(name, attributeFlags);
136  }
137  }
138 
139  return kTTErrNone;
140 }
141 
142 TTErr TTMirror::MessagesInstantiate(const TTValue& inputValue, TTValue& outputValue)
143 {
144  TTMessageFlags messageFlags = kTTMessageDefaultFlags;
145  TTValue none;
146 
147  for (TTUInt32 i = 0; i < inputValue.size(); i++) {
148 
149  if (inputValue[i].type() == kTypeSymbol) {
150 
151  TTSymbol name = inputValue[i];
152 
153  addMirrorMessage(name, messageFlags);
154  }
155  }
156 
157  return kTTErrNone;
158 }
159 
160 TTErr TTMirror::AttributeCache(const TTValue& inputValue, TTValue& outputValue)
161 {
162  if (inputValue.size() >= 1) {
163 
164  if (inputValue[0].type() == kTypeSymbol) {
165 
166  TTSymbol name = inputValue[0];
167  TTValue v;
168  TTValuePtr valueToCache;
169 
170  // if the attribute is not already cached
171  if (mAttributeValueCache.lookup(name, v)) {
172 
173  TTAttributePtr anAttribute;
174 
175  // get attribute
176  if (!this->findAttribute(name, &anAttribute)) {
177 
178  // change getter and setter
179  anAttribute->getter = (TTGetterMethod)& TTMirror::getMirrorCachedAttribute;
180  anAttribute->setter = (TTSetterMethod)& TTMirror::setMirrorCachedAttribute;
181 
182  if (inputValue.size() == 2) {
183 
184  if (inputValue[1].type() == kTypePointer) {
185 
186  valueToCache = TTValuePtr(TTPtr(inputValue[1]));
187 
188  // add it as a cached attribute with the given value
189  mAttributeValueCache.append(name, *valueToCache);
190 
191  return kTTErrNone;
192  }
193  }
194 
195  // add it as a cached attribute
196  mAttributeValueCache.append(name, v);
197 
198  return kTTErrNone;
199  }
200  }
201  }
202  }
203 
204  return kTTErrGeneric;
205 }
206 
207 TTErr TTMirror::AttributeUncache(const TTValue& inputValue, TTValue& outputValue)
208 {
209  if (inputValue.size() == 1) {
210 
211  if (inputValue[0].type() == kTypeSymbol) {
212 
213  TTSymbol name = inputValue[0];
214 
215  // if the attribute is cached
216  if (!mAttributeValueCache.lookup(name, outputValue)) {
217 
218  TTAttributePtr anAttribute;
219 
220  // get attribute
221  this->findAttribute(name, &anAttribute);
222 
223  // change getter and setter
224  anAttribute->getter = (TTGetterMethod)& TTMirror::getMirrorAttribute;
225  anAttribute->setter = (TTSetterMethod)& TTMirror::setMirrorAttribute;
226 
227  // remove it from the cache
228  mAttributeValueCache.remove(name);
229 
230  return kTTErrNone;
231  }
232  }
233  }
234 
235  return kTTErrGeneric;
236 }
237 
238 TTErr TTMirror::getMirrorAttribute(TTAttribute& anAttribute, TTValue& value)
239 {
240  if (mGetAttributeCallback.valid()) {
241 
242  TTValue data, none;
243 
244  data.append(anAttribute.name);
245  data.append((TTPtr)&value);
246 
247  mGetAttributeCallback.send("notify", data);
248 
249  if (value.size() > 0)
250  return kTTErrNone;
251  }
252 
253  return kTTErrGeneric;
254 }
255 
256 TTErr TTMirror::setMirrorAttribute(TTAttribute& anAttribute, const TTValue& value)
257 {
258  TTValue data, none;
259  TTErr err = kTTErrNone;
260 
261  if (mSetAttributeCallback.valid()) {
262 
263  data.append(anAttribute.name);
264  data.append((TTPtr)&value);
265 
266  err = mSetAttributeCallback.send("notify", data);
267 
268  // if the mirror cannot listen value : notify observers ourself
269  if (!mListenAttributeCallback.valid())
270  anAttribute.sendNotification(kTTSym_notify, value); // we use kTTSym_notify because we know that observers are TTCallback
271  }
272 
273  return err;
274 }
275 
276 TTErr TTMirror::getMirrorCachedAttribute(TTAttribute& anAttribute, TTValue& value)
277 {
278  TTValue data;
279 
280  data.append(anAttribute.name);
281 
282  // get the value from the cache
283  if (!mAttributeValueCache.lookup(anAttribute.name, value)) {
284 
285  data.append((TTPtr)&value);
286 
287  if (value.size() > 0)
288  return kTTErrNone;
289  }
290 
291  return kTTErrGeneric;
292 }
293 
294 TTErr TTMirror::setMirrorCachedAttribute(TTAttribute& anAttribute, const TTValue& value)
295 {
296  TTValue data, cached, none;
297  TTErr err = kTTErrNone;
298 
299  if (mSetAttributeCallback.valid()) {
300 
301  data.append(anAttribute.name);
302  data.append((TTPtr)&value);
303 
304  // update the cache with the value
305  if (!mAttributeValueCache.lookup(anAttribute.name, cached)) {
306  mAttributeValueCache.remove(anAttribute.name);
307  mAttributeValueCache.append(anAttribute.name, value);
308  }
309 
310  err = mSetAttributeCallback.send("notify", data);
311 
312  // if the mirror cannot listen value : notify observers ourself
313  if (!mListenAttributeCallback.valid())
314  anAttribute.sendNotification(kTTSym_notify, value); // we use kTTSym_notify because we know that observers are TTCallback
315  }
316 
317  return err;
318 }
319 
320 TTErr TTMirror::sendMirrorMessage(const TTSymbol* messageName, const TTValue& inputValue, TTValue& outputValue)
321 {
322  TTValue data, none;
323  TTErr err = kTTErrNone;
324 
325  if (mSendMessageCallback.valid()) {
326 
327  data.append(messageName);
328  data.append((TTPtr)&inputValue);
329 
330  err = mSetAttributeCallback.send("notify", data);
331  }
332 
333  return err;
334 }
335 
336 TTErr TTMirror::updateAttributeValue(const TTSymbol attributeName, TTValue& value)
337 {
338  TTAttributePtr anAttribute = NULL;
339  TTErr err;
340 
341  err = this->findAttribute(attributeName, &anAttribute);
342 
343  // if attributes are cached
344  if (!mGetAttributeCallback.valid()) {
345 
346  TTValue cached;
347 
348  // update the cache with the value
349  if (!mAttributeValueCache.lookup(attributeName, cached)) {
350  mAttributeValueCache.remove(attributeName);
351  mAttributeValueCache.append(attributeName, value);
352  }
353  }
354 
355  if (!err)
356  anAttribute->sendNotification(kTTSym_notify, value); // we use kTTSym_notify because we know that observers are TTCallback
357 
358  return err;
359 }
360 
362 {
363  TTValue data, none;
364  TTErr err = kTTErrNone;
365 
366  // disable the listening if there is no more observers on the attribute
367  if (!enable && anAttribute.getObserverCount() != 0)
368  return kTTErrGeneric;
369 
370  // enable the listening only one time for the first observer
371  if (enable && anAttribute.getObserverCount() != 1)
372  return kTTErrGeneric;
373 
374  if (mListenAttributeCallback.valid()) {
375 
376  data.append(anAttribute.name);
377  data.append(enable);
378 
379  err = mListenAttributeCallback.send("notify", data);
380  }
381 
382  return err;
383 }
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
The default set of flags will be used if this is specified. At this time the default is #kTTMethodPas...
Definition: TTObjectBase.h:85
TTErr enableListening(const TTAttribute &anAttribute, TTBoolean enable)
Enable the listening of an attribute value using protocol solution if exist.
Definition: TTMirror.cpp:361
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
void messages(TTValue &returnedMessageNames) const
Return a list of names of the available messages.
Definition: TTObject.cpp:123
This class represents a single message, as used by the TTObjectBase class.
Definition: TTMessage.h:55
TTErr getMessage(const TTSymbol name, TTMessagePtr *messageObject)
Search for and locate a message.
Definition: TTObjectBase.h:360
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
Definition: TTHash.cpp:76
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.
TTErr setAttributeGetterFlags(const TTSymbol name, TTAttributeFlags &value)
Set the getterFlags of an attribute.
#define addMirrorMessage(name, flag)
TODO : how to have TTGetterMethod and TTSetterMethod for Mirror attribute Property ...
Definition: TTMirror.h:57
TTErr setAttributeSetterFlags(const TTSymbol name, TTAttributeFlags &value)
Set the setterFlags of an attribute.
Create and use Jamoma object instances.
Definition: TTObject.h:29
TTErr getAttribute(const TTSymbol name, TTAttributePtr *attributeObject)
Search for and locate an attribute.
Definition: TTObjectBase.h:350
#define addMirrorCachedAttribute(name, type)
A convenience macro to be used for registering mirror cached attribute.
Definition: TTMirror.h:40
size_type size() const noexcept
Return the number of elements.
TTErr sendNotification(const TTSymbol name, const TTValue &arguments)
Send a notification.
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
TTSetterMethod setter
Method to set the attribute value.
Definition: TTAttribute.h:87
Symbol type.
Definition: TTBase.h:282
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
void * TTPtr
A generic pointer.
Definition: TTBase.h:248
TTMessageFlags
Flags that determine the behavior of messages.
Definition: TTObjectBase.h:84
Attribute accessors will first be passed a reference to the TTAttribute object, then it will be passe...
Definition: TTObjectBase.h:97
The TTSymbol class is used to represent a string and efficiently pass and compare that string...
Definition: TTSymbol.h:26
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
Definition: TTHash.cpp:70
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
TTUInt32 getObserverCount() const
Query an object to get the number of observers.
Definition: TTObjectBase.h:149
const TTSymbol name
The name of the attribute.
Definition: TTAttribute.h:83
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
Definition: TTBase.h:344
TTErr remove(const TTSymbol key)
Remove an item from the hash table.
Definition: TTHash.cpp:108
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
Definition: TTBase.h:342
void attributes(TTValue &returnedAttributeNames) const
Return a list of names of the available attributes.
Definition: TTObject.cpp:111
std::uint32_t TTUInt32
32 bit unsigned integer
Definition: TTBase.h:178
Pointer type.
Definition: TTBase.h:284
A Mirror Object.
TTAttributeFlags
Flags that determine the behavior of messages.
Definition: TTObjectBase.h:94
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
TTErr isClassRegistered(const TTSymbol &className)
Check if a class is registered.
#define addMirrorAttribute(name, type)
TTMirror ...
Definition: TTMirror.h:33
TTGetterMethod getter
Method to fetch the attribute value.
Definition: TTAttribute.h:86
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
TTMessageFlags flags
define the behavior of the message.
Definition: TTMessage.h:59
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr findAttribute(const TTSymbol name, TTAttribute **attr)
Find an attribute.