19 #define thisTTClass TTContainer
20 #define thisTTClassName "Container"
21 #define thisTTClassTags "node, container"
23 TT_MODULAR_CONSTRUCTOR,
25 mDescription(kTTSym_none),
26 mService(kTTSym_none),
30 mAddress(kTTAdrsEmpty),
32 activityAttribute(NULL),
33 contentAttribute(NULL)
35 if(arguments.size() == 2)
37 mReturnAddressCallback = arguments[0];
38 mReturnValueCallback = arguments[1];
82 this->findAttribute(kTTSym_activity, &activityAttribute);
83 this->findAttribute(kTTSym_content, &contentAttribute);
86 TTContainer::~TTContainer()
88 setAlias(kTTAdrsEmpty);
94 TTValue hk, cacheElement, v, none;
97 TTAddress aRelativeAddress, topAddress, belowAddress, keyAddress;
109 aRelativeAddress = AddressAndValue[0];
115 attrOrMess = kTTSym_value;
118 if (strrchr(aRelativeAddress.
c_str(), C_WILDCARD)) {
123 aRelativeAddress.
splitAt(0, topAddress, belowAddress);
129 for (i = 0; i < mObjectsObserversCache.
getSize(); i++) {
141 if (this->Send(AddressAndValue, none))
155 if (this->Send(AddressAndValue, none))
172 anObject = cacheElement[0];
175 if (anObject.
name() == kTTSym_Data && attrOrMess == kTTSym_value) {
178 anObject.
get(kTTSym_service, v);
182 if (service == kTTSym_return)
186 anObject.
send(kTTSym_Command, *valueToSend);
194 if (anObject.
name() == kTTSym_Viewer && attrOrMess == kTTSym_value) {
197 anObject.
send(kTTSym_Send, *valueToSend);
206 err = anObject.
set(attrOrMess, *valueToSend);
210 anObject.
send(attrOrMess, *valueToSend);
217 aRelativeAddress.
splitAt(0, topAddress, belowAddress);
220 err = mObjectsObserversCache.
lookup(topAddress, cacheElement);
225 anObject = cacheElement[0];
228 if (anObject.
name() == kTTSym_Container) {
230 AddressAndValue[0] = belowAddress;
231 anObject.
send(kTTSym_Send, AddressAndValue);
246 TTErr TTContainer::Init()
275 TTList nodeList, nameList, initializedList;
278 aNode->
getChildren(S_WILDCARD, S_WILDCARD, nodeList);
281 nodeList.sort(&compareNodePriorityThenNameThenInstance);
284 for (nodeList.begin(); nodeList.end(); nodeList.next())
289 nameList.
append(nameInstance);
293 while (!nameList.isEmpty())
296 TTSymbol name = nameList.current()[0];
297 TTSymbol instance = nameList.current()[1];
304 aNode->
getChildren(S_WILDCARD, S_WILDCARD, nodeList);
307 nodeList.sort(&compareNodePriorityThenNameThenInstance);
309 for (nodeList.begin(); nodeList.end(); nodeList.next())
316 if (initializedList.findEquals(nameInstance, found))
317 nameList.
append(nameInstance);
325 initializedList.append(nameList.current());
326 nameList.remove(nameList.current());
334 if (anObject.valid())
337 if (anObject.name() == kTTSym_Data)
345 anObject.get(kTTSym_service, v);
348 if (service == kTTSym_parameter)
349 anObject.send(kTTSym_Init);
352 else if (anObject.name() == kTTSym_Container)
353 anObject.send(kTTSym_Init);
364 if (inputValue.
size() == 1) {
368 TTSymbol newNameInstance = inputValue[0];
377 newNameInstance = outputValue[0];
391 TTErr TTContainer::AliasRemove()
393 return setAlias(kTTAdrsEmpty);
401 if (mAddress != kTTAdrsEmpty)
428 if (oldAlias != mAlias) {
430 if (oldAlias != kTTAdrsEmpty) {
435 mObjectsObserversCache.
getKeys(hk);
436 for (i = 0; i < mObjectsObserversCache.
getSize(); i++) {
440 aliasKey = oldAlias.
c_str();
441 aliasKey += S_SEPARATOR.c_str();
442 aliasKey += key.
c_str();
445 mObjectsObserversCache.
lookup(key, cacheElement);
451 anObject = cacheElement[0];
453 if (anObject.
name() == kTTSym_Container)
454 anObject.
set(kTTSym_alias, kTTAdrsEmpty);
458 if (mAlias != kTTAdrsEmpty && mAddress != kTTAdrsEmpty) {
463 mObjectsObserversCache.
getKeys(hk);
464 for (i = 0; i < mObjectsObserversCache.
getSize(); i++) {
468 aliasKey = mAlias.
c_str();
469 aliasKey += S_SEPARATOR.c_str();
470 aliasKey += key.
c_str();
473 mObjectsObserversCache.
lookup(key, cacheElement);
479 anObject = cacheElement[0];
481 if (anObject.
name() == kTTSym_Container)
538 TTErr TTContainer::bind()
542 TTList aNodeList, allObjectsNodes;
546 mObjectsObserversCache.
clear();
556 for (allObjectsNodes.begin(); allObjectsNodes.end(); allObjectsNodes.next()) {
559 makeCacheElement(aNode);
565 mObserver.
set(kTTSym_baton, baton);
575 TTValue cacheElement, baton, v, none;
583 aNode->
getAddress(aRelativeAddress, mAddress);
587 if (!anObject.
valid())
591 err = mObjectsObserversCache.
lookup(aRelativeAddress, cacheElement);
595 std::cout <<
"TTContainer::makeCacheElement -- object at " << (
const char*)aRelativeAddress.
c_str() <<
" already exists" << std::endl;
598 mObjectsObserversCache.
remove(aRelativeAddress);
602 cacheElement.
append(anObject);
605 if (anObject.
name() == kTTSym_Data) {
608 anObject.
get(kTTSym_service, v);
612 if (service == kTTSym_message) {
615 cacheElement.
append(empty);
626 valueObserver.
set(kTTSym_baton, baton);
632 cacheElement.
append(valueObserver);
637 else if (anObject.
name() == kTTSym_Viewer) {
646 returnedValueObserver.
set(kTTSym_baton, baton);
652 cacheElement.
append(returnedValueObserver);
656 else if (anObject.
name() == kTTSym_Container) {
665 activityObserver.
set(kTTSym_baton, baton);
671 cacheElement.
append(activityObserver);
675 else if (anObject.
name() == kTTSym_PresetManager) {
678 cacheElement.
append(empty);
683 cacheElement.
append(empty);
689 mObjectsObserversCache.
append(aRelativeAddress, cacheElement);
707 aNode->
getAddress(aRelativeAddress, mAddress);
710 err = mObjectsObserversCache.
lookup(aRelativeAddress, cacheElement);
718 if (anObject.
valid()) {
721 if (anObject.
name() == kTTSym_Data) {
724 anObserver = cacheElement[1];
734 else if (anObject.
name() == kTTSym_Viewer) {
737 anObserver = cacheElement[1];
746 else if (anObject.
name() == kTTSym_Container) {
749 anObserver = cacheElement[1];
759 err = mObjectsObserversCache.
remove(aRelativeAddress);
767 TTErr TTContainer::updateContent()
780 TTErr TTContainer::unbind()
792 mObjectsObserversCache.
getKeys(hk);
794 for (i = 0; i < mObjectsObserversCache.
getSize(); i++) {
797 mObjectsObserversCache.
lookup(key, cacheElement);
798 anObject = cacheElement[0];
800 if (anObject.
valid()) {
805 if (anObject.
name() == kTTSym_Data) {
808 aValueObserver = cacheElement[1];
815 else if (anObject.
name() == kTTSym_Viewer) {
818 aValueObserver = cacheElement[1];
825 else if (anObject.
name() == kTTSym_Container) {
828 aValueObserver = cacheElement[1];
838 mObjectsObserversCache.
clear();
847 mAddress = kTTAdrsEmpty;
855 TTTextHandlerPtr aTextHandler = TTTextHandlerPtr(o.
instance());
860 TTUInt16 i, numInput = 0, numOutput = 0;
861 TTValue keys, cacheElement, s, arg, tags, none;
865 buffer = aTextHandler->mWriter;
868 *buffer =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">";
870 *buffer +=
"\t<head>";
871 *buffer +=
"\t\t<meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-16\">";
872 *buffer +=
"<title>";
873 *buffer += this->mAddress.
c_str();
874 *buffer +=
"</title>";
876 this->cssDefinition(buffer);
878 *buffer +=
"\t</head>";
883 *buffer +=
"\t<div id=\"jmod_header\">";
886 *buffer +=
"\t<img src=\"../../../documentation/graphics/jmodular.icon.png\" width=\"128\" height=\"128\">";
888 *buffer += this->mAddress.
c_str();
891 *buffer += this->mDescription.
c_str();
895 *buffer +=
"\t<h6><a href=\"../../../documentation/html/index.html\">Table of Contents</a> | <a href=\"../../../documentation/html/modules.html\">Index of Modules</a> | <a href=\"../../../documentation/html/credits.html\">Credits</a> | <a href=\"http://pledgie.com/campaigns/5615\">Donate</a> | <a href=\"http://www.jamoma.org/\">Jamoma.org</a></h6>";
896 *buffer +=
"\t</div>";
904 *buffer +=
"\t<h3> Configuration </h3>";
905 *buffer +=
"\t<p> Tags : <code>";
907 *buffer +=
"</code> <br>";
915 for (i = 0; i < keys.
size(); i++)
918 mObjectsObserversCache.
lookup(name, cacheElement);
919 anObject = cacheElement[0];
921 if (anObject.
name() == kTTSym_Input || anObject.
name() == kTTSym_InputAudio)
924 if (anObject.
name() == kTTSym_Output || anObject.
name() == kTTSym_OutputAudio)
932 *buffer +=
"\t<p>Number of signal inlets : <code> ";
933 *buffer += toWrite.data();
934 *buffer +=
" </code> <br/>";
940 *buffer +=
"\t<p>Number of signal outlets : <code> ";
942 *buffer +=
" </code> <br/>";
947 *buffer +=
"\t<h3> Parameters </h3>";
948 this->dataHeading(buffer);
950 for (i = 0; i < keys.
size(); i++)
953 mObjectsObserversCache.
lookup(name, cacheElement);
954 anObject = cacheElement[0];
956 if (anObject.
name() == kTTSym_Data) {
957 anObject.
get(kTTSym_service, s);
960 if (service == kTTSym_parameter) {
961 *buffer +=
"\t\t<tr>";
962 *buffer +=
"\t\t\t<td class=\"instructionName\"> ";
963 *buffer += name.
c_str();
967 aTextHandler->setAttributeValue(kTTSym_object, arg);
969 anObject.
send(
"WriteAsText", inputValue);
970 *buffer +=
"\t\t<tr>";
976 *buffer +=
"\t</table>";
978 *buffer +=
"\t<p> </p>";
984 *buffer +=
"\t<h3> Messages </h3>";
985 this->dataHeading(buffer);
987 for (i = 0; i < keys.
size(); i++)
990 mObjectsObserversCache.
lookup(name, cacheElement);
991 anObject = cacheElement[0];
993 if (anObject.
name() == kTTSym_Data) {
994 anObject.
get(kTTSym_service, s);
997 if (service == kTTSym_message) {
998 *buffer +=
"\t\t<tr>";
999 *buffer +=
"\t\t\t<td class=\"instructionName\"> ";
1000 *buffer += name.
c_str();
1004 aTextHandler->setAttributeValue(kTTSym_object, arg);
1006 anObject.
send(
"WriteAsText", inputValue);
1007 *buffer +=
"\t\t<tr>";
1013 *buffer +=
"\t</table>";
1015 *buffer +=
"\t<p> </p>";
1022 *buffer +=
"\t<h3> Returns </h3>";
1023 this->dataHeading(buffer);
1025 for (i = 0; i < keys.
size(); i++)
1028 mObjectsObserversCache.
lookup(name, cacheElement);
1029 anObject = cacheElement[0];
1031 if (anObject.
name() == kTTSym_Data) {
1032 anObject.
get(kTTSym_service, s);
1035 if (service == kTTSym_return) {
1036 *buffer +=
"\t\t<tr>";
1037 *buffer +=
"\t\t\t<td class=\"instructionName\"> ";
1038 *buffer += name.
c_str();
1042 aTextHandler->setAttributeValue(kTTSym_object, arg);
1044 anObject.
send(
"WriteAsText", inputValue);
1045 *buffer +=
"\t\t<tr>";
1051 *buffer +=
"\t</table>";
1053 *buffer +=
"\t<p> </p>";
1058 *buffer +=
"\t<h3> About Jamoma </h3>";
1059 *buffer +=
"\t<p> Jamoma is a system for creating and exchanging structured Max patches. ";
1060 *buffer +=
"\tIt consists of both a set of guidelines and an implementation of those guidelines. ";
1061 *buffer +=
"\tFor more information please visit <a href=\"http://jamoma.org/\">jamoma.org</a>. </p> ";
1064 *buffer +=
"</body>";
1065 *buffer +=
"</html>";
1070 void TTContainer::dataHeading(
TTString *buffer)
1072 *buffer +=
"\t<table>";
1073 *buffer +=
"\t\t<tr class=\"tableHeading2\">";
1074 *buffer +=
"\t\t\t<td> name </td>";
1075 *buffer +=
"\t\t\t<td> type </td>";
1076 *buffer +=
"\t\t\t<td> bounds </td>";
1077 *buffer +=
"\t\t\t<td> clipmode </td>";
1078 *buffer +=
"\t\t\t<td> ramp/drive </td>";
1080 *buffer +=
"\t\t\t<td> ramp/function </td>";
1082 *buffer +=
"\t\t\t<td> dataspace </td>";
1083 *buffer +=
"\t\t\t<td> dataspace/unit </td>";
1084 *buffer +=
"\t\t\t<td> repetitions/filter </td>";
1085 *buffer +=
"\t\t\t<td> description </td>";
1086 *buffer +=
"\t\t<tr>";
1089 void TTContainer::cssDefinition(
TTString *buffer)
1091 *buffer +=
"<style type=\"text/css\">";
1096 font-family: Arial, Helvetica, sans-serif;\
1112 text-transform: lowercase;\
1117 border-bottom: 1px solid #333;\
1121 margin-bottom: 10px;\
1130 margin-bottom: 0px;\
1147 padding-bottom: 1em;\
1160 padding: 0em 0em 0.3em;\
1164 padding: 10px 10px 0px 0px;\
1170 margin: 0 0 40px 0;\
1186 background-color: #c5c5c5;\
1188 vertical-align: top;\
1191 .moduleDescription {\
1193 background-color: #000000;\
1196 vertical-align: top;\
1200 background-color: #eee;\
1202 vertical-align: top;\
1211 margin-bottom: 10px;\
1220 font-family: 'Courier New', Courier, mono;\
1221 background-color: #edd;\
1222 vertical-align: top;\
1226 font-family: 'Times New Roman', Times, serif;\
1227 background-color: #eee;\
1228 vertical-align: top;\
1231 .instructionDataspace {\
1232 font-family: 'Times New Roman', Times, serif;\
1233 background-color: #eed;\
1234 vertical-align: top;\
1237 .instructionDataspaceUnit {\
1238 font-family: 'Times New Roman', Times, serif;\
1239 background-color: #eee;\
1240 vertical-align: top;\
1243 .instructionRangeBounds {\
1244 font-family: 'Times New Roman', Times, serif;\
1245 background-color: #eed;\
1246 vertical-align: top;\
1248 .instructionRangeClipmode {\
1249 font-family: 'Times New Roman', Times, serif;\
1250 background-color: #eee;\
1251 vertical-align: top;\
1253 .instructionRampDrive {\
1254 font-family: 'Times New Roman', Times, serif;\
1255 background-color: #eed;\
1256 vertical-align: top;\
1258 .instructionRampFunction {\
1259 font-family: 'Times New Roman', Times, serif;\
1260 background-color: #eee;\
1261 vertical-align: top;\
1263 .instructionRepetitionsFilter {\
1264 font-family: 'Times New Roman', Times, serif;\
1265 background-color: #eed;\
1266 vertical-align: top;\
1268 .instructionDescription {\
1269 font-family: 'Times New Roman', Times, serif;\
1270 background-color: #eee;\
1271 vertical-align: top;\
1274 padding-right: 5px;\
1278 list-style-type: disc;\
1292 font-style: italic;\
1295 font-family: 'Courier New', Courier, mono;\
1298 font-family: 'Courier New', Courier, mono;\
1302 *buffer +=
"</style>";
1307 #pragma mark Some Methods
1322 hisContext = baton[1];
1325 anAddress = data[0];
1328 anObserver = data[3];
1338 aContainer->makeCacheElement(aNode);
1346 aContainer->deleteCacheElement(aNode);
1363 TTAddress relativeAddress, relativeDataAddress;
1367 if (baton.
size() == 2) {
1372 aContainer = baton[0];
1373 relativeAddress = baton[1];
1378 err =
TTContainerPtr(aContainer.
instance())->mObjectsObserversCache.lookup(relativeAddress, cacheElement);
1382 anObject = cacheElement[0];
1385 if (!anObject.
valid()) {
1388 std::cout <<
"TTContainerValueAttributeCallback -- object at " << (
const char*)relativeAddress.
c_str() <<
" is not valid" << std::endl;
1395 if (anObject.
name() != kTTSym_Container) {
1403 relativeDataAddress = data[0];
1404 relativeAddress = relativeAddress.
appendAddress(relativeDataAddress);
1434 TTPtr c, t_c, p_c = NULL;
1457 return (c == t_c) || (c != t_c && p_c == t_c );
1480 if (!o1.
get(kTTSym_priority, v))
1488 if (!o2.
get(kTTSym_priority, v))
1492 if (p1 == 0 && p2 == 0)
return v1 < v2;
1494 if (p1 == 0)
return NO;
1495 if (p2 == 0)
return YES;
TTAddress appendAddress(const TTAddress &toAppend)
Return a new TTAddress with the appended part.
bool TTBoolean
Boolean flag, same as Boolean on the Mac.
std::uint16_t TTUInt16
16 bit unsigned integer
TTErr registerObserverForNotifications(const TTObject &observingObject)
Register an observer.
this flag means that a TTNode have been destroyed in the tree structure
TTErr send(const TTSymbol aName)
Send a message to this object with no arguments.
TTErr getKeysSorted(TTValue &hashKeysSorted, TTBoolean(*comparisonFunction)(TTValue &, TTValue &)=NULL)
Get an array of all of the keys sorted for the hash table.
TTAddress appendAttribute(TTSymbol anAttribute)
Return a new TTAddress with attribute part.
TTErr unregisterObserverForNotifications(const TTObject &observingObject)
Unregister an observer for notifications.
TTSymbol & getName()
Get the name of the node.
TTString toString(TTBoolean quotes=YES) const
Return the content as a single string with spaces between elements.
TTErr lookup(const TTSymbol key, TTValue &value)
Find the value for the given key.
TTBoolean TTContainerTestObjectAndContext(TTNodePtr n, TTPtr args)
#define addAttribute(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom getter...
We build a directory of TTNodes, and you can request a pointer for any TTNode, or add an observer to ...
void copyFrom(const TTValue &obj, TTUInt16 index)
Copy a value starting from an index until the last element.
#define accessApplicationFrom(anAddress)
Access to any application using an address.
TTErr AliasRemove(TTAddress alias)
Create an alias address.
TTAddress getParent()
Get a pointer to the parent address.
TTPtr getContext()
Get a pointer to the context of this node.
The TTAddress class is used to represent a string and efficiently pass and compare that string...
Create and use Jamoma object instances.
TTObject & getObject()
Get the object binded by this node.
size_type size() const noexcept
Return the number of elements.
TTBoolean TTContainerCompareObjectPriority(TTValue &v1, TTValue &v2)
compare priority attribute of object's
TTErr AliasCreate(TTAddress alias, TTAddress anAddress)
Create an alias address.
TTErr TTContainerValueAttributeCallback(const TTValue &baton, const TTValue &data)
TTUInt32 getSize()
Return the number of keys in the hash table.
TTErr sendNotification(const TTSymbol name, const TTValue &arguments)
Send a notification.
this flag means that an address have no leading slash
TTErr getKeys(TTValue &hashKeys)
Get an array of all of the keys for the hash table.
This class represents a single attribute, as used by the TTObjectBase class.
TTErr notifyObservers(TTAddress anAddress, TTNodePtr aNode, TTAddressNotificationFlag flag)
Notify life cycle observers that something appends below this TTNode.
friend TTErr TTMODULAR_EXPORT TTContainerValueAttributeCallback(const TTValue &baton, const TTValue &data)
TTErr TTContainerDirectoryCallback(const TTValue &baton, const TTValue &data)
This is a special type used by TTAttribute to indicate that a value is a TTValue and is locally maint...
TTBoolean valid
If the object isn't completely built, or is in the process of freeing, this will be false...
friend TTErr TTMODULAR_EXPORT TTContainerDirectoryCallback(const TTValue &baton, const TTValue &data)
void prepend(const TTValue &aValueToPrepend)
Insert another TTValue before the first element.
void append(const T &anElementValueToAppend)
Insert a single TTElement at the end.
void * TTPtr
A generic pointer.
TTErr get(const TTSymbol aName, T &aReturnedValue) const
Get an attribute value for an object.
TTSymbol name() const
Return the name of this class.
this flag means that address1 an address2 refer to the same node in the tree structure ...
TTSymbol & getInstance()
Get the instance of the node.
#define addAttributeProperty(attributeName, propertyName, initialValue)
A convenience macro to be used for registering properties of attributes.
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...
TTErr append(const TTSymbol key, const TTValue &value)
Insert an item into the hash table.
Boolean (1/0) or (true/false) flag.
TTSymbol & getAttribute()
Get the attribute part.
#define addMessageWithArguments(name)
A convenience macro to be used by subclasses for registering messages.
const char * c_str() const
Return a pointer to the internal string as a C-string.
std::int32_t TTInt32
32 bit signed integer
TTErr clear()
Remove all items from the hash table.
TTAddressComparisonFlag
Comparison flags between address returned by address1->compare(address2).
TTErr getAddress(TTAddress &returnedAddress, TTAddress from=kTTAdrsEmpty)
Get the address of the node.
this flag means that address1 refers to a node at a upper level than address2 in the tree structure ...
32-bit signed integer, range is -2,147,483,648 through 2,147,483,647.
Something went wrong, but what exactly is not known. Typically used for context-specific problems...
TTAddressType getType()
Get the type.
TTErr remove(const TTSymbol key)
Remove an item from the hash table.
TTErr
Jamoma Error Codes Enumeration of error codes that might be returned by any of the TTBlue functions a...
signed char TTInt8
8 bit signed integer (char)
this flag means that a TTNode have been created in the tree structure
std::uint32_t TTUInt32
32 bit unsigned integer
TTErr splitAt(TTUInt32 whereToSplit, TTAddress &returnedPart1, TTAddress &returnedPart2)
A parsing tool : split address in two part from a given '/' position.
#define addAttributeWithSetter(name, type)
A convenience macro to be used by subclasses for registering attributes with a custom setter...
#define addMessage(name)
A convenience macro to be used by subclasses for registering messages.
TTErr getChildren(TTSymbol &name, TTSymbol &instance, TTList &returnedChildren)
Get a linklist of children of the node : select them by name and instance (use wilcards to select the...
TTObjectBase * instance() const
Return a direct pointer to the internal instance.
TTAddressComparisonFlag compare(const TTAddress &toCompare, TTInt8 &depthDifference)
A comparison tool.
TTAddress removeAttribute()
Return a new TTAddress without attribute part.
The TTString class is used to represent a string.
TTBoolean valid() const
Determine if the object contained by this TTObject is truly ready for use.
We build a tree of TTNodes, and you can request a pointer for any TTNode, or add an observer to any T...
#define accessApplicationLocalDirectory
Access to the local application directory.
[doxygenAppendixC_copyExample]
TTNodePtr getParent()
Get a pointer to the parent node of the node.
TTErr findAttribute(const TTSymbol name, TTAttribute **attr)
Find an attribute.
unsigned char TTUInt8
8 bit unsigned integer (char)
#define addMessageProperty(messageName, propertyName, initialValue)
A convenience macro to be used for registering properties of messages.