Jamoma API  0.6.0.a19
TTSender.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup modularLibrary
4  *
5  * @brief A Sender 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 "TTSender.h"
18 
19 #define thisTTClass TTSender
20 #define thisTTClassName "Sender"
21 #define thisTTClassTags "node, sender"
22 
23 TT_MODULAR_CONSTRUCTOR,
24 mAddress(kTTAdrsEmpty),
25 mObjectCache(NULL)
26 {
27  // a Sender can handle a signal
28  if (arguments.size() == 1)
29  mSignal = arguments[0];
30 
32 
33  addAttribute(ObjectCache, kTypePointer);
34  addAttributeProperty(ObjectCache, hidden, YES);
35  addAttributeProperty(ObjectCache, readOnly, YES);
36 
38  addMessageProperty(Send, hidden, YES);
39 
40  mIsSending = false;
41 
42  mObjectCache = new TTList();
43  mObjectCache->setThreadProtection(true);
44 }
45 
46 TTSender::~TTSender()
47 {
48  unbindAddress(accessApplicationDirectoryFrom(mAddress));
49  unbindApplication();
50 
51  delete mObjectCache;
52 }
53 
54 TTErr TTSender::setAddress(const TTValue& newValue)
55 {
56  unbindAddress(accessApplicationDirectoryFrom(mAddress));
57  unbindApplication();
58 
59  mAddress = newValue[0];
60 
61  if (mAddress != kTTAdrsEmpty) {
62 
63  // default attribute to bind is value
64  if (mAddress.getAttribute() == NO_ATTRIBUTE)
65  mAddress = mAddress.appendAttribute(kTTSym_value);
66 
67  return bindAddress(accessApplicationDirectoryFrom(mAddress));
68  }
69 
70  return kTTErrGeneric;
71 }
72 
73 #if 0
74 #pragma mark -
75 #pragma mark Some Methods
76 #endif
77 
78 TTErr TTSender::Send(TTValue& valueToSend, TTValue& outputValue)
79 {
80  TTObject anObject;
81  TTValue aCacheElement, v, c, none;
82  TTAttributePtr anAttribute;
83  TTSymbol ttAttributeName;
84  TTMessagePtr aMessage;
85  TTAddress relativeAddress;
86  TTErr err = kTTErrNone;
87 
88  if (!accessApplicationDirectoryFrom(mAddress) || mAddress == kTTAdrsEmpty)
89  return kTTErrGeneric;
90 
91  if (!mIsSending) {
92 
93  // lock
94  mIsSending = true;
95 
96  if (!mObjectCache->isEmpty()) {
97 
98  ttAttributeName = ToTTName(mAddress.getAttribute());
99 
100  // send data to each node of the selection
101  for (mObjectCache->begin(); mObjectCache->end(); mObjectCache->next()) {
102 
103  aCacheElement = mObjectCache->current();
104 
105  // then his object
106  anObject = aCacheElement[0];
107 
108  if (anObject.valid()) {
109  // DATA CASE for value attribute
110  if (anObject.name() == kTTSym_Data && ttAttributeName == kTTSym_value) {
111 
112  // set the value attribute using a command
113  anObject.send(kTTSym_Command, valueToSend);
114  }
115  // CONTAINER CASE for value attribute
116  else if (anObject.name() == kTTSym_Container && ttAttributeName == kTTSym_value) {
117 
118  if (valueToSend.size() >= 1 ) {
119  if (valueToSend[0].type() == kTypeSymbol) {
120  relativeAddress = valueToSend[0];
121  c.copyFrom(valueToSend, 1);
122 
123  v = TTValue(relativeAddress);
124  v.append((TTPtr*)&c);
125 
126  // send the value
127  anObject.send(kTTSym_Send, v);
128  }
129  else
130  err = kTTErrGeneric;
131  }
132  else
133  err = kTTErrGeneric;
134 
135  }
136  else if ((anObject.name() == kTTSym_Input || anObject.name() == kTTSym_InputAudio) && ttAttributeName == kTTSym_signal) {
137 
138  // send the value
139  anObject.send(kTTSym_Send, valueToSend);
140  }
141  // DEFAULT CASE
142  // Look for attribute and set it
143  else if (!anObject.instance()->findAttribute(ttAttributeName, &anAttribute))
144  anObject.set(ttAttributeName, valueToSend);
145 
146  // Or look for message and send it
147  else if (!anObject.instance()->findMessage(ttAttributeName, &aMessage))
148  anObject.send(ttAttributeName, valueToSend);
149  }
150  }
151  }
152 
153  // unlock
154  mIsSending = false;
155  }
156 
157  return err;
158 }
159 
160 TTErr TTSender::bindAddress(TTNodeDirectoryPtr aDirectory)
161 {
162  TTNodePtr aNode;
163  TTObject anObject;
164  TTValue aCacheElement;
165  TTList aNodeList;
166  TTValue v, baton;
167 
168  if (!aDirectory)
169  return bindApplication();
170 
171  // 1. Look for the node(s) into the directory
172  aDirectory->Lookup(mAddress, aNodeList, &aNode);
173 
174  // 2. make a cache containing each object
175  for (aNodeList.begin(); aNodeList.end(); aNodeList.next()) {
176  aNode = TTNodePtr((TTPtr)aNodeList.current()[0]);
177  anObject = aNode->getObject();
178  mObjectCache->append(anObject);
179  }
180 
181  // 3. Observe any creation or destruction below the address
182  mAddressObserver = TTObject("callback");
183 
184  mAddressObserver.set(kTTSym_baton, TTPtr(this)); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
185  mAddressObserver.set(kTTSym_function, TTPtr(&TTSenderDirectoryCallback));
186 
187  aDirectory->addObserverForNotifications(mAddress, mAddressObserver, 0); // ask for notification only for equal addresses
188 
189  return kTTErrNone;
190 }
191 
192 TTErr TTSender::unbindAddress(TTNodeDirectoryPtr aDirectory)
193 {
194  TTErr err = kTTErrNone;
195 
196  if (mAddress != kTTAdrsEmpty) {
197 
198  mObjectCache->clear();
199 
200  // stop life cycle observation
201  if(mAddressObserver.valid() && aDirectory) {
202 
203  err = aDirectory->removeObserverForNotifications(mAddress, mAddressObserver);
204 
205  mAddressObserver = TTObject();
206  }
207  }
208 
209  return kTTErrNone;
210 }
211 
212 TTErr TTSender::bindApplication()
213 {
214  if (!mApplicationObserver.valid()) {
215 
216  mApplicationObserver = TTObject("callback");
217 
218  mApplicationObserver.set(kTTSym_baton, TTPtr(this)); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
219  mApplicationObserver.set(kTTSym_function, TTPtr(&TTSenderApplicationManagerCallback));
220 
221  return TTApplicationManagerAddApplicationObserver(mAddress.getDirectory(), mApplicationObserver);
222  }
223 
224  return kTTErrGeneric;
225 }
226 
227 TTErr TTSender::unbindApplication()
228 {
229 
230  if (mApplicationObserver.valid()) {
231 
232  TTApplicationManagerRemoveApplicationObserver(mAddress.getDirectory(), mApplicationObserver);
233 
234  mApplicationObserver = TTObject();
235  }
236 
237  return kTTErrNone;
238 }
239 
240 TTErr TTSenderDirectoryCallback(const TTValue& baton, const TTValue& data)
241 {
242  TTValue aCacheElement;
243  TTSenderPtr aSender;
244  TTNodePtr aNode;
245  TTObject anObject, aCacheObject;
246  TTAddress anAddress;
247  TTValue v;
248  TTUInt8 flag;
249 
250  // unpack baton (a #TTSenderPtr)
251  aSender = TTSenderPtr((TTPtr)baton[0]); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
252 
253  // Unpack data (address, aNode, flag, anObserver)
254  anAddress = data[0];
255  aNode = TTNodePtr((TTPtr)data[1]);
256  flag = data[2];
257 
258  switch (flag) {
259 
260  case kAddressCreated :
261  {
262  anObject = aNode->getObject();
263  if (anObject.valid())
264  aSender->mObjectCache->appendUnique(anObject);
265 
266  break;
267  }
268 
269  case kAddressDestroyed :
270  {
271  anObject = aNode->getObject();
272 
273  // find the object in the cache and remove it
274  for (aSender->mObjectCache->begin(); aSender->mObjectCache->end(); aSender->mObjectCache->next()) {
275 
276  // get a node
277  aCacheObject = aSender->mObjectCache->current()[0];
278 
279  if (aCacheObject == anObject) {
280  aSender->mObjectCache->remove(aSender->mObjectCache->current());
281  break;
282  }
283  }
284  break;
285  }
286 
287  default:
288  break;
289  }
290 
291  return kTTErrNone;
292 }
293 
295 {
296  TTSenderPtr aSender;
297  TTSymbol anApplicationName;
298  TTObject anApplication;
299  TTValue v;
300  TTUInt8 flag;
301 
302  // unpack baton (a #TTSenderPtr)
303  aSender = TTSenderPtr((TTPtr)baton[0]); // théo -- we have to register our self as a #TTPtr to not reference this instance otherwhise the destructor will never be called
304 
305  // Unpack data (applicationName, application, flag, observer)
306  anApplicationName = data[0];
307  anApplication = data[1];
308  flag = data[2];
309 
310  switch (flag) {
311 
313  {
314  aSender->bindAddress(accessApplicationDirectoryFrom(aSender->mAddress));
315  break;
316  }
317 
319  {
320  break;
321  }
322 
324  {
325  break;
326  }
327 
328  case kApplicationReleased :
329  {
330  aSender->unbindAddress(accessApplicationDirectoryFrom(aSender->mAddress));
331  break;
332  }
333 
334  default:
335  break;
336  }
337 
338  return kTTErrNone;
339 }
an application have been released by the application manager
#define accessApplicationDirectoryFrom(anAddress)
Access to an application directory using an address.
this flag means that a TTNode have been destroyed in the tree structure
Definition: TTAddressBase.h:56
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
Definition: TTObject.cpp:135
TTAddress appendAttribute(TTSymbol anAttribute)
Return a new TTAddress with attribute part.
Definition: TTAddress.h:161
This class represents a single message, as used by the TTObjectBase class.
Definition: TTMessage.h:55
TTSymbol & getDirectory()
Get the directory part.
Definition: TTAddress.h:106
#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
void copyFrom(const TTValue &obj, TTUInt16 index)
Copy a value starting from an index until the last element.
Definition: TTValue.h:147
application's protocol will be stopped
TTErr TTSenderDirectoryCallback(const TTValue &baton, const TTValue &data)
Definition: TTSender.cpp:240
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.
This class represents a single attribute, as used by the TTObjectBase class.
Definition: TTAttribute.h:79
TTErr findMessage(const TTSymbol name, TTMessage **message)
Find a message registered with this object.
Symbol type.
Definition: TTBase.h:282
TTErr Lookup(TTAddress anAddress, TTList &returnedTTNodes, TTNodePtr *firstReturnedTTNode)
Find TTNodes by address.
TTErr TTMODULAR_EXPORT TTApplicationManagerAddApplicationObserver(TTSymbol anApplicationName, const TTObject anObserver)
Add a TTCallback as observer of application creation/destruction note : it uses the extern TTModularA...
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
application's protocol have been started
friend TTErr TTMODULAR_EXPORT TTSenderDirectoryCallback(const TTValue &baton, const TTValue &data)
Definition: TTSender.cpp:240
TTSymbol name() const
Return the name of this class.
Definition: TTObject.cpp:129
#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 addObserverForNotifications(TTAddress anAddress, TTObject &anObserver, TTInt8 maxDepthDifference=-1)
Add a TTCallback as a life cycle observer of all nodes below this one.
#define ToTTName(appName)
Convert a tt name TTSymbol into a local application name.
TTErr TTMODULAR_EXPORT TTApplicationManagerRemoveApplicationObserver(TTSymbol anApplicationName, const TTObject anObserver)
Remove a TTCallback as observer of application creation/destruction note : it uses the extern TTModul...
TTSymbol & getAttribute()
Get the attribute part.
Definition: TTAddress.h:130
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
Definition: TTMessage.h:27
TTErr TTSenderApplicationManagerCallback(const TTValue &baton, const TTValue &data)
Definition: TTSender.cpp:294
friend TTErr TTMODULAR_EXPORT TTSenderApplicationManagerCallback(const TTValue &baton, const TTValue &data)
Definition: TTSender.cpp:294
an application have been intantiated by the application manager
A Sender Object.
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
this flag means that a TTNode have been created in the tree structure
Definition: TTAddressBase.h:57
TTErr removeObserverForNotifications(TTAddress anAddress, TTObject &anObserver)
Remove a TTCallback as a life cycle observer of all nodes below this one.
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
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
Definition: TTObject.cpp:105
No Error.
Definition: TTBase.h:343
TTSender ...
Definition: TTSender.h:27
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
Definition: TTObject.cpp:179
We build a tree of TTNodes, and you can request a pointer for any TTNode, or add an observer to any T...
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr findAttribute(const TTSymbol name, TTAttribute **attr)
Find an attribute.
unsigned char TTUInt8
8 bit unsigned integer (char)
Definition: TTBase.h:174
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.
Definition: TTMessage.h:37