Jamoma API  0.6.0.a19
TTEnvironment.cpp
Go to the documentation of this file.
1 /** @file
2  *
3  * @ingroup foundationLibrary
4  *
5  * @brief TTEnvironment is a global object providing information on the environemt.
6  *
7  * @details The global TTEnvironent object maintains all global attributes/settings for the Jamoma environment.
8  * All attribute members of the environment are made public, since essentially every class is a friend.
9  * They should, however, be treated as read-only.
10  *
11  * @author Timothy Place, Nils Peters, Trond Lossius
12  *
13  * @copyright Copyright © 2008, Timothy Place @n
14  * This code is licensed under the terms of the "New BSD License" @n
15  * http://creativecommons.org/licenses/BSD/
16  */
17 
18 
19 #include "TTFoundation.h"
20 #include "TTEnvironment.h"
21 #include "TTClass.h"
22 
23 #define thisTTClass TTEnvironment
24 
25 
26 // The environment object has one instance, which is global in scope.
28 
29 
30 /****************************************************************************************************/
31 
33  : TTObjectBase(TTValue()), mDebugBasic(false), mDebugMessaging(false), mSampleRate(0), mBenchmarking(false)
34 {
35  classes = new TTHash();
36  tags = new TTHash();
37 
38  addAttribute(DebugBasic, kTypeBoolean);
39  addAttribute(DebugMessaging, kTypeBoolean);
40  addAttribute(SampleRate, kTypeUInt32);
41  addAttribute(Benchmarking, kTypeBoolean);
42 
46 
47  // can't use the SymbolCache here because it hasn't been initialized yet!
48  setAttributeValue("sampleRate", 44100);
49 }
50 
51 
53 {
54  // If on Windows, we need to call FreeLibrary() on all plug-ins loaded with LoadLibrary()
55  // On the Mac, we may need to do the equivalent
56 
57  delete tags;
58  delete classes;
59 }
60 
61 
62 TTErr TTEnvironment::getVersion(const TTValue& anInputValue, TTValue &anOutputValue)
63 {
64  anOutputValue = TTSymbol(TTFOUNDATION_VERSION_STRING);
65  return kTTErrNone;
66 }
67 
68 
69 TTErr TTEnvironment::registerClass(const TTSymbol className, const TTString& tagString, const TTObjectBaseInstantiationMethod anInstantiationMethod)
70 {
71  TTValue v((TTString&)tagString); // The tags to be associated with the class we are registering.
72  TTValue tagObjects; // Contains a TTList of objects in the environment with the given tag.
73  TTClassPtr theClass;
74  TTErr err;
75  TTList* classNamesForTag; // The TTList contained by tagObjects
76  TTUInt16 size;
77  TTSymbol tag(kTTSymEmpty);
78  TTValue result;
79 
80  TTLogDebug("Jamoma registering class: %s\n", className.c_str());
81 
82  err = classes->lookup(className, result);
83 
84  // If a class is already registered with this name, then we do not want to register another class with the same name!
85  if (err == kTTErrValueNotFound) {
86 
87  // 1. Turn the string into an array of symbols
89 
90  // 2. Create the class and associate it with its name
91  theClass = new TTClass(className, v, anInstantiationMethod);
92 
93  // 3. For each symbol in the TTValue array...
94  size = v.size();
95  for (TTUInt16 i=0; i<size; i++) {
96  tag = v[i];
97 
98  // 4. Look to see if this tag exists yet
99  err = tags->lookup(tag, tagObjects);
100  if (!err) {
101  classNamesForTag = (TTList*)(TTPtr(tagObjects));
102 
103  // TODO: The following code demonstrates so extreme lameness that we need to evaluate.
104  // First, we should probably just do this section of code with TTValue instead of TTList (but we needed code to test TTList)
105  // Second, TTList is taking references but keeping things internally as pointers, which leads to lots of confusion
106  // Third, we have to pass objects that are permanent - so no temporaries are allowed unless we make TTList do a copy
107  // etc.
108 
109  // TODO: We need to factor out a function to add a tag for a named class (or a given class ptr)
110 
111  classNamesForTag->append(className);
112  //classNamesForTag->append(TTValue(className));
113  }
114  else {
115  classNamesForTag = new TTList;
116  tagObjects = TTPtr(classNamesForTag);
117  tags->append(tag ,tagObjects);
118  //classNamesForTag->append(*new TTValue(className));
119  classNamesForTag->append(className);
120  }
121  }
122 
123  // 4. Register it
124  err = registerClass(theClass);
125  }
126  return err;
127 }
128 
129 
131 {
132  return classes->append(theClass->name, TTPtr(theClass));
133 }
134 
135 
136 TTErr TTEnvironment::getAllClassNames(const TTValue& anInputValue, TTValue &anOutputValue)
137 {
138  return classes->getKeys(anOutputValue);
139 }
140 
141 
142 TTErr TTEnvironment::getClassNamesForTags(const TTValue& anInputValue, TTValue &anOutputValue)
143 {
144  return getClassNamesWithTags(anOutputValue, anInputValue);
145  /*
146  TTValue v;
147  TTErr err;
148 
149  err = getClassNamesWithTags(v, searchTagsIn_classNamesOut);
150  if (!err)
151  searchTagsIn_classNamesOut = v;
152  return err;
153  */
154 }
155 
156 
158 {
159  TTUInt16 size = searchTags.size();
160  TTSymbol tag(kTTSymEmpty);
161  TTValue tagObjects;
162  TTErr err = kTTErrGeneric;
163  TTList* classNamesForTag;
164 
165  classNames.clear();
166 
167  tag = searchTags[0];
168  err = tags->lookup(tag, tagObjects);
169  if (err)
170  return err;
171 
172  classNamesForTag = (TTList*)(TTPtr(tagObjects));
173 
174  for (TTUInt16 i=0; i<classNamesForTag->getSize(); i++) {
175  TTValue classNameValue;
176  TTSymbol className(kTTSymEmpty);
177  TTValue tags;
178  TTValue aClassValue;
179  TTClassPtr aClass;
180  TTUInt16 success = 1;
181 
182  classNamesForTag->getIndex(i, classNameValue);
183  className = classNameValue[0];
184 
185  classes->lookup(className, aClassValue);
186  aClass = TTClassPtr(TTPtr(aClassValue));
187  tags = aClass->tags;
188 
189  for (TTUInt16 j=0; j < tags.size(); j++){
190  TTSymbol someTag(kTTSymEmpty);
191 
192  someTag = tags[j];
193 
194  for (TTUInt16 k=1; k<size; k++){
195  tag = searchTags[k];
196  if (tag == someTag) {
197  success += 1;
198  break;
199  }
200  }
201 
202  if (success == size)
203  break;
204  }
205  if (success == size)
206  classNames.append(className);
207  }
208  return kTTErrNone;
209 }
210 
211 
213 {
214  TTValue v;
215  return classes->lookup(className, v);
216 }
217 
218 
219 TTErr TTEnvironment::createInstance(const TTSymbol className, TTObjectBasePtr* anObject, const TTValue& anArgument)
220 {
221  TTValue v;
222  TTClassPtr theClass;
223  TTErr err;
224  TTObjectBasePtr newObject = NULL;
225  TTObjectBasePtr oldObject = NULL;
226 
227  err = classes->lookup(className, v);
228 
229  if (!err) {
230  theClass = TTClassPtr(TTPtr(v));
231 
232  if (theClass)
233  err = theClass->createInstance(&newObject, anArgument);
234  else
235  err = kTTErrGeneric;
236  }
237 
238  if (!err && newObject) {
239  if (*anObject)
240  oldObject = *anObject;
241  *anObject = newObject;
242  if (oldObject)
243  releaseInstance(&oldObject);
244 
245  (*anObject)->classPtr = theClass;
246  (*anObject)->valid = true;
247  }
248 
249  //TODO: Add instance tracking. For each instance of a class, we push the instance onto a linked list of instances for that class
250  // When the object is freed using deleteInstance(), then we pop it.
251  // What would this achieve?
252  // - we could check statistics on them or do other logging
253  // - we could access instances remotely, and perhaps then manipulate them remotely in a shared manner
254  // - if an object is referenced by another object, and thus shared, then we need to reference counting here before freeing.
255  // THEREFORE: we should have an addReference() and release() method (instead of a deleteInstance() method).
256  // - the reference counting itself should probably be done inside of TTObjectBase though, yes?
257  return err;
258 }
259 
261 {
262  if (anObject) {
263  anObject->referenceCount++;
264 
265  if (anObject->valid) { // Théo : this is avoiding the log of the reference count when the object is stored in a TTValue for objectFreeing notification (see in TTEnvironment::releaseInstance)
266  if (anObject->track)
267  TTLogMessage("TTEnvironment::referenceInstance : \t%p is referenced %d times\n", anObject, anObject->referenceCount);
268  }
269  }
270 
271  return anObject;
272 }
273 
274 // TODO: find a better way to avoid the problem of infinite feedback from
275 // objects duplicating to provide notification
276 // This current technique is not threadsafe (for example, if we are deleting objects on the non-main thread).
277 //static TTBoolean sFreeInProgress = NO;
278 #include <unordered_map>
279 static std::unordered_map<TTObjectBasePtr, TTBoolean> sFreeInProgress;
280 
282 {
283  if (sFreeInProgress[*anObject])
284  return kTTErrNone;
285 
286  TT_ASSERT("can only release a valid instance", *anObject && (*anObject)->valid == 1 && (*anObject)->referenceCount);
287 
288  (*anObject)->referenceCount--;
289  if ((*anObject)->track)
290  TTLogMessage("TTEnvironment::releaseInstance : \t%p is referenced %d times\n", (*anObject), (*anObject)->referenceCount);
291 
292  if ((*anObject)->referenceCount < 1) {
293 
294  (*anObject)->valid = false;
295  waitForLock(); // in case an object is processing a vector of audio in another thread or something...
296  sFreeInProgress[*anObject] = YES;
297 
298  // the following must happen in a block so that 'v' will go out of scope before we
299  // delete the object.
300  {
301  TTValue v = TTObject(*anObject);
302  (*anObject)->observers.iterateObjectsSendingMessage("objectFreeing", v);
303  }
304  if ((*anObject)->track)
305  TTLogMessage("TTEnvironment::releaseInstance : \t%p is not a %s instance anymore\n", (*anObject), (*anObject)->getName().c_str());
306  delete *anObject;
307  sFreeInProgress.erase(*anObject);
308  *anObject = NULL;
309  }
310  return kTTErrNone;
311 }
312 
313 
314 #if 0
315 #pragma mark -
316 #pragma mark Public Interface
317 #endif
318 
319 
320 TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr* returnedObjectPtr, const TTValue arguments)
321 {
322  return ttEnvironment->createInstance(className, returnedObjectPtr, arguments);
323 }
324 
325 
326 TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr* returnedObjectPtr, const TTUInt16 arguments)
327 {
328  TTValue v(arguments);
329  return ttEnvironment->createInstance(className, returnedObjectPtr, v);
330 }
331 
332 
334 {
335  return ttEnvironment->referenceInstance(anObject);
336 }
337 
338 
340 {
341  if (*anObject)
342  return ttEnvironment->releaseInstance(anObject);
343  else
344  return kTTErrNone;
345 }
346 
347 
348 TTErr TTClassRegister(const TTSymbol className, const TTString& tagString, const TTObjectBaseInstantiationMethod anInstantiationMethod)
349 {
350  return ttEnvironment->registerClass(className, tagString, anInstantiationMethod);
351 }
352 
353 TTErr TTClassRegister(const TTSymbol className, TTImmutableCString tagString, const TTObjectBaseInstantiationMethod anInstantiationMethod)
354 {
355  return ttEnvironment->registerClass(className, TTString(tagString), anInstantiationMethod);
356 }
357 
358 
360 {
361  TTValue unused;
362  return ttEnvironment->getAllClassNames(unused, classNames);
363 }
364 
365 
366 TTErr TTGetRegisteredClassNamesForTags(TTValue& classNames, const TTValue& searchTags)
367 {
368  return ttEnvironment->getClassNamesWithTags(classNames, searchTags);
369 }
370 
TTClass * TTClassPtr
Pointer to a TTClass.
Definition: TTClass.h:86
std::uint16_t TTUInt16
16 bit unsigned integer
Definition: TTBase.h:176
TTErr getClassNamesWithTags(TTValue &classNames, const TTValue &searchTags)
Retreive the names of all registered TTObjectBase classes in the environment that are associated with...
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
Definition: TTHash.cpp:76
The TTClass object represents a class in the Jamoma environment.
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
Definition: TTAttribute.h:29
TTErr TTObjectBaseRelease(TTObjectBasePtr *anObject)
DEPRECATED.
TTErr getAllClassNames(const TTValue &anInputValue, TTValue &anOutputValue)
Remove a class from the environment's registry.
Create and use Jamoma object instances.
Definition: TTObject.h:29
size_type size() const noexcept
Return the number of elements.
TTEnvironment()
Constructor.
TTErr getKeys(TTValue &hashKeys)
Get an array of all of the keys for the hash table.
Definition: TTHash.cpp:126
Base class for all first-class Jamoma objects.
Definition: TTObjectBase.h:109
TTObjectBase *(* TTObjectBaseInstantiationMethod)(TTSymbol className, const TTValue arguments)
A function pointer for an instance creation function required to be provided by all classes...
Definition: TTEnvironment.h:29
TTErr setAttributeValue(const TTSymbol name, TTValue &value)
Set an attribute value for an object.
Maintain a collection of TTValue objects indexed by TTSymbol pointers.
Definition: TTHash.h:36
TTBoolean valid
If the object isn't completely built, or is in the process of freeing, this will be false...
Definition: TTObjectBase.h:124
TTErr createInstance(const TTSymbol className, TTObjectBasePtr *anObject, const TTValue &anArgument)
Create a new instance of a registered TTObjectBase class.
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 releaseInstance(TTObjectBasePtr *anObject)
Release an instance of a TTObjectBase class.
The TTClass object represents a class in the Jamoma environment.
Definition: TTClass.h:32
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
TTEnvironment * ttEnvironment
The environment object has one instance, which is global in scope.
TTErr TTGetRegisteredClassNamesForTags(TTValue &classNames, const TTValue &searchTags)
DEPRECATED.
TTObjectBasePtr referenceInstance(TTObjectBasePtr anObject)
Create a reference to an object.
Boolean (1/0) or (true/false) flag.
Definition: TTBase.h:281
TTBoolean track
enable the print of a log message to ease the track of reference counting mechanism on an instance ...
Definition: TTObjectBase.h:125
TTBoolean waitForLock()
If the object is locked (e.g.
Definition: TTObjectBase.h:550
TTErr transformCSVStringToSymbolArray()
Convert a comma-separated-value string into an array of TTSymbols.
Definition: TTValue.h:463
A value was not found when doing a look up for it (in a TTHash, TTList, or other class).
Definition: TTBase.h:352
#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
TTErr registerClass(const TTSymbol className, const TTString &tagString, const TTObjectBaseInstantiationMethod anInstantiationMethod)
Register the unit name, and associate it with the constructor to be called.
void clear()
Clear all values from the vector, leaving with size of 0.
Definition: TTValue.h:131
TTEnvironment is a global object providing information on the environemt.
void TTFOUNDATION_EXPORT TTLogMessage(TTImmutableCString message,...)
Platform and host independent method for posting log messages.
Definition: TTBase.cpp:534
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
virtual ~TTEnvironment()
Destructor.
TTErr TTObjectBaseInstantiate(const TTSymbol className, TTObjectBasePtr *returnedObjectPtr, const TTValue arguments)
DEPRECATED.
void TTFOUNDATION_EXPORT TTLogDebug(TTImmutableCString message,...)
Platform and host independent method for posting messages only when debugging is enabled in the envir...
Definition: TTBase.cpp:591
32-bit unsigned integer, range is 0 through 4,294,967,295.
Definition: TTBase.h:278
TTErr TTGetRegisteredClassNames(TTValue &classNames)
DEPRECATED.
No Error.
Definition: TTBase.h:343
TTErr isClassRegistered(const TTSymbol &className)
Check if a class is registered.
The TTString class is used to represent a string.
Definition: TTString.h:34
TTErr getVersion(const TTValue &anInputValue, TTValue &anOutputValue)
Retrieve the environment version number.
TTObjectBasePtr TTObjectBaseReference(TTObjectBasePtr anObject)
DEPRECATED.
[doxygenAppendixC_copyExample]
Definition: TTValue.h:34
TTErr createInstance(TTObjectBase **anObject, const TTValue &anArgument)
Create a new instance of a registered TTObjectBase class.
Definition: TTClass.cpp:37
TTErr getClassNamesForTags(const TTValue &anInputValue, TTValue &anOutputValue)
A message-bound version of getClassNamesWithTags()
The global object maintains all global attributes/settings for the Jamoma environment.
Definition: TTEnvironment.h:47