Vuo 2.4.4
Loading...
Searching...
No Matches
VuoNodeRegistry.cc
Go to the documentation of this file.
1
10#include "VuoNodeRegistry.hh"
11
12#include <dlfcn.h>
13#include <sstream>
14#include "VuoCompositionDiff.hh"
15#include "VuoException.hh"
17#include "VuoRuntimeState.hh"
19
20const unsigned long VuoNodeRegistry::topLevelCompositionIndex = ULONG_MAX;
21const unsigned long VuoNodeRegistry::invalidCompositionIndex = ULONG_MAX - 1;
22
27{
28 this->persistentState = persistentState;
29 vuoTopLevelCompositionIdentifier = NULL;
30}
31
37void VuoNodeRegistry::updateCompositionSymbols(void *compositionBinaryHandle)
38{
39 ostringstream errorMessage;
40
41 vuoTopLevelCompositionIdentifierType *vuoTopLevelCompositionIdentifierPtr = (vuoTopLevelCompositionIdentifierType *) dlsym(compositionBinaryHandle, "vuoTopLevelCompositionIdentifier");
42 if (! vuoTopLevelCompositionIdentifierPtr)
43 {
44 errorMessage << "The composition couldn't be started because its vuoTopLevelCompositionIdentifier variable couldn't be found : " << dlerror();
45 throw VuoException(errorMessage.str());
46 }
47 vuoTopLevelCompositionIdentifier = *vuoTopLevelCompositionIdentifierPtr;
48}
49
54const char * VuoNodeRegistry::defaultToTopLevelCompositionIdentifier(const char *compositionIdentifier)
55{
56 return (strlen(compositionIdentifier) > 0 ? compositionIdentifier : vuoTopLevelCompositionIdentifier);
57}
58
66void VuoNodeRegistry::splitCompositionIdentifier(const string &compositionIdentifier, string &parentCompositionIdentifier, string &nodeIdentifier)
67{
68 size_t pos = compositionIdentifier.rfind("/");
69 if (pos != string::npos)
70 {
71 parentCompositionIdentifier = compositionIdentifier.substr(0, pos);
72 nodeIdentifier = compositionIdentifier.substr(pos + strlen("/"));
73 }
74 else
75 {
76 parentCompositionIdentifier = compositionIdentifier;
77 nodeIdentifier = "";
78 }
79}
80
84string VuoNodeRegistry::buildCompositionIdentifier(const string &parentCompositionIdentifier, const string &nodeIdentifier)
85{
86 return parentCompositionIdentifier + "/" + nodeIdentifier;
87}
88
94void VuoNodeRegistry::splitPortIdentifier(const string &portIdentifier, string &nodeIdentifier, string &portName)
95{
96 size_t pos = portIdentifier.rfind(":");
97 if (pos != string::npos)
98 {
99 nodeIdentifier = portIdentifier.substr(0, pos);
100 portName = portIdentifier.substr(pos + strlen(":"));
101 }
102}
103
110void VuoNodeRegistry::addNodeMetadata(const char *compositionIdentifier, const char *nodeIdentifier,
111 NodeContext *(*compositionCreateContextForNode)(unsigned long),
112 void (*compositionSetPortValue)(VuoCompositionState *, const char *, const char *, bool, bool, bool, bool, bool),
113 char * (*compositionGetPortValue)(VuoCompositionState *, const char *, int, bool),
114 void (*compositionFireTriggerPortEvent)(VuoCompositionState *, const char *),
115 void (*compositionReleasePortData)(void *, unsigned long))
116{
117 NodeMetadata nodeMetadata;
118 nodeMetadata.identifier = nodeIdentifier;
119 nodeMetadata.compositionCreateContextForNode = compositionCreateContextForNode;
120 nodeMetadata.compositionSetPortValue = compositionSetPortValue;
121 nodeMetadata.compositionGetPortValue = compositionGetPortValue;
122 nodeMetadata.compositionFireTriggerPortEvent = compositionFireTriggerPortEvent;
123 nodeMetadata.compositionReleasePortData = compositionReleasePortData;
124 nodeMetadatas[compositionIdentifier].push_back(nodeMetadata);
125}
126
131void VuoNodeRegistry::addPortMetadata(const char *compositionIdentifier, const char *portIdentifier, const char *portName,
132 unsigned long typeIndex, const char *initialValue)
133{
134 PortMetadata portMetadata = { portIdentifier, portName, typeIndex, initialValue };
135 nodeMetadatas[compositionIdentifier].back().portMetadatas.push_back(portMetadata);
136}
137
141string VuoNodeRegistry::getNodeIdentifierForIndex(const char *compositionIdentifier, unsigned long nodeIndex)
142{
143 if (nodeIndex == topLevelCompositionIndex)
144 return "";
145
146 map<string, vector<NodeMetadata> >::iterator iter1 = nodeMetadatas.find(compositionIdentifier);
147 if (iter1 != nodeMetadatas.end())
148 if (nodeIndex < iter1->second.size())
149 return iter1->second[nodeIndex].identifier;
150
151 VUserLog("Couldn't find identifier for node %s/%lu", compositionIdentifier, nodeIndex);
152 return "";
153}
154
158unsigned long VuoNodeRegistry::getNodeIndexForIdentifier(const string &compositionIdentifier, const string &nodeIdentifier)
159{
160 if (nodeIdentifier.empty())
161 return topLevelCompositionIndex;
162
163 map<string, vector<NodeMetadata> >::iterator iter1 = nodeMetadatas.find(compositionIdentifier);
164 if (iter1 != nodeMetadatas.end())
165 for (unsigned long i = 0; i < iter1->second.size(); ++i)
166 if (iter1->second[i].identifier == nodeIdentifier)
167 return i;
168
169 VUserLog("Couldn't find index for node %s", buildCompositionIdentifier(compositionIdentifier, nodeIdentifier).c_str());
170 return invalidCompositionIndex;
171}
172
176const VuoNodeRegistry::NodeMetadata * VuoNodeRegistry::getNodeMetadataForPort(const string &compositionIdentifier, const string &portIdentifier)
177{
178 string nodeIdentifier, portName;
179 splitPortIdentifier(portIdentifier, nodeIdentifier, portName);
180
181 map<string, vector<NodeMetadata> >::iterator iter1 = nodeMetadatas.find(compositionIdentifier);
182 if (iter1 != nodeMetadatas.end())
183 for (unsigned long i = 0; i < iter1->second.size(); ++i)
184 if (iter1->second[i].identifier == nodeIdentifier)
185 return &(iter1->second[i]);
186
187 VUserLog("Couldn't find node metadata for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
188 return NULL;
189}
190
194string VuoNodeRegistry::getCompositionIdentifierForHash(unsigned long compositionIdentifierHash)
195{
196 map<unsigned long, string>::iterator iter1 = compositionIdentifierForHash.find(compositionIdentifierHash);
197 if (iter1 != compositionIdentifierForHash.end())
198 return iter1->second;
199
200 VUserLog("Couldn't find composition identifier for hash %lu", compositionIdentifierHash);
201 return "";
202}
203
207void VuoNodeRegistry::addNodeContext(const char *compositionIdentifier, unsigned long nodeIndex, NodeContext *nodeContext)
208{
209 unsigned long compositionIdentifierHash = VuoRuntimeUtilities::hash(compositionIdentifier);
210
211 map<unsigned long, map<unsigned long, NodeContext *> >::iterator iter1 = nodeContextForIndex.find(compositionIdentifierHash);
212 if (iter1 != nodeContextForIndex.end())
213 {
214 map<unsigned long, NodeContext *>::iterator iter2 = iter1->second.find(nodeIndex);
215 if (iter2 != iter1->second.end())
216 VUserLog("Context overwritten for node %s", buildCompositionIdentifier(compositionIdentifier, getNodeIdentifierForIndex(compositionIdentifier, nodeIndex)).c_str());
217 }
218
219 nodeContextForIndex[compositionIdentifierHash][nodeIndex] = nodeContext;
220
221 compositionIdentifierForHash[ VuoRuntimeUtilities::hash(compositionIdentifier) ] = compositionIdentifier;
222}
223
227void VuoNodeRegistry::removeNodeContext(const char *compositionIdentifier, unsigned long nodeIndex)
228{
229 unsigned long compositionIdentifierHash = VuoRuntimeUtilities::hash(compositionIdentifier);
230
231 map<unsigned long, map<unsigned long, NodeContext *> >::iterator iter1 = nodeContextForIndex.find(compositionIdentifierHash);
232 if (iter1 != nodeContextForIndex.end())
233 {
234 map<unsigned long, NodeContext *>::iterator iter2 = iter1->second.find(nodeIndex);
235 if (iter2 != iter1->second.end())
236 {
237 iter1->second.erase(iter2);
238 if (iter1->second.empty())
239 nodeContextForIndex.erase(iter1);
240
241 string nodeIdentifier = getNodeIdentifierForIndex(compositionIdentifier, nodeIndex);
242 string subcompositionIdentifier = buildCompositionIdentifier(compositionIdentifier, nodeIdentifier);
243 unsigned long subcompositionIdentifierHash = VuoRuntimeUtilities::hash(subcompositionIdentifier.c_str());
244 map<unsigned long, string>::iterator ciIter = compositionIdentifierForHash.find(subcompositionIdentifierHash);
245 if (ciIter != compositionIdentifierForHash.end())
246 compositionIdentifierForHash.erase(ciIter);
247
248 return;
249 }
250 }
251
252 VUserLog("Couldn't find context for node %s", buildCompositionIdentifier(compositionIdentifier, getNodeIdentifierForIndex(compositionIdentifier, nodeIndex)).c_str());
253}
254
258void VuoNodeRegistry::relocateNodeContext(const char *compositionIdentifier, unsigned long nodeIndex)
259{
260 unsigned long compositionIdentifierHash = VuoRuntimeUtilities::hash(compositionIdentifier);
261
262 map<unsigned long, map<unsigned long, NodeContext *> >::iterator iter1 = nodeContextForIndex.find(compositionIdentifierHash);
263 if (iter1 != nodeContextForIndex.end())
264 {
265 map<unsigned long, NodeContext *>::iterator iter2 = iter1->second.find(nodeIndex);
266 if (iter2 != iter1->second.end())
267 {
268 string nodeIdentifier = getNodeIdentifierForIndex(compositionIdentifier, nodeIndex);
269 carriedOverNodeContextForIdentifier[compositionIdentifier][nodeIdentifier] = iter2->second;
270 iter1->second.erase(iter2);
271
272 if (iter1->second.empty())
273 nodeContextForIndex.erase(iter1);
274
275 return;
276 }
277 }
278
279 VUserLog("Couldn't find context for node %s", buildCompositionIdentifier(compositionIdentifier, getNodeIdentifierForIndex(compositionIdentifier, nodeIndex)).c_str());
280}
281
286NodeContext * VuoNodeRegistry::carryOverNodeContext(const char *oldCompositionIdentifier, const char *newCompositionIdentifier,
287 unsigned long nodeIndex)
288{
289 NodeContext *nodeContext = NULL;
290 string nodeIdentifier = getNodeIdentifierForIndex(newCompositionIdentifier, nodeIndex);
291
292 {
293 bool found = false;
294 map<string, map<string, NodeContext *> >::iterator coIter1 = carriedOverNodeContextForIdentifier.find(oldCompositionIdentifier);
295 if (coIter1 != carriedOverNodeContextForIdentifier.end())
296 {
297 map<string, NodeContext *>::iterator coIter2 = coIter1->second.find(nodeIdentifier);
298 if (coIter2 != coIter1->second.end())
299 {
300 nodeContext = coIter2->second;
301 coIter1->second.erase(coIter2);
302 addNodeContext(newCompositionIdentifier, nodeIndex, nodeContext);
303 found = true;
304
305 if (coIter1->second.empty())
306 carriedOverNodeContextForIdentifier.erase(coIter1);
307 }
308 }
309
310 if (! found)
311 VUserLog("Couldn't find context for node %s", buildCompositionIdentifier(oldCompositionIdentifier, nodeIdentifier).c_str());
312 }
313
314 return nodeContext;
315}
316
320NodeContext * VuoNodeRegistry::getNodeContext(const char *compositionIdentifier, unsigned long nodeIndex)
321{
322 unsigned long compositionIdentifierHash = VuoRuntimeUtilities::hash(compositionIdentifier);
323
324 map<unsigned long, map<unsigned long, NodeContext *> >::iterator iter1 = nodeContextForIndex.find(compositionIdentifierHash);
325 if (iter1 != nodeContextForIndex.end())
326 {
327 map<unsigned long, NodeContext *>::iterator iter2 = iter1->second.find(nodeIndex);
328 if (iter2 != iter1->second.end())
329 return iter2->second;
330 }
331
332 VUserLog("Couldn't find context for node %s", buildCompositionIdentifier(compositionIdentifier, getNodeIdentifierForIndex(compositionIdentifier, nodeIndex)).c_str());
333 return NULL;
334}
335
339NodeContext * VuoNodeRegistry::getCompositionContext(const char *compositionIdentifier)
340{
341 string parentCompositionIdentifier, subcompositionNodeIdentifier;
342 splitCompositionIdentifier(compositionIdentifier, parentCompositionIdentifier, subcompositionNodeIdentifier);
343 unsigned long subcompositionNodeIndex = getNodeIndexForIdentifier(parentCompositionIdentifier, subcompositionNodeIdentifier);
344 return getNodeContext(parentCompositionIdentifier.c_str(), subcompositionNodeIndex);
345}
346
350template<typename T>
351bool VuoNodeRegistry::findCachedInfoForPort(const map<string, map<string, T> > &cachedInfoForPort, const string &compositionIdentifier,
352 const string &portIdentifier, typename map<string, T>::const_iterator &foundIter)
353{
354 typename map<string, map<string, T> >::const_iterator compIter = cachedInfoForPort.find(compositionIdentifier);
355 if (compIter != cachedInfoForPort.end())
356 {
357 foundIter = compIter->second.find(portIdentifier);
358 if (foundIter != compIter->second.end())
359 return true;
360 }
361
362 return false;
363}
364
368void * VuoNodeRegistry::getDataForPort(const char *compositionIdentifier, const char *portIdentifier)
369{
370 map<string, void *>::const_iterator foundIter;
371 bool found = findCachedInfoForPort<void *>(dataForPort, compositionIdentifier, portIdentifier, foundIter);
372 if (found)
373 return foundIter->second;
374
375 VUserLog("Couldn't find data for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
376 return NULL;
377}
378
382unsigned long VuoNodeRegistry::getNodeIndexForPort(const char *compositionIdentifier, const char *portIdentifier)
383{
384 map<string, unsigned long>::const_iterator foundIter;
385 bool found = findCachedInfoForPort<unsigned long>(nodeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
386 if (found)
387 return foundIter->second;
388
389 VUserLog("Couldn't find node index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
390 return 0;
391}
392
396unsigned long VuoNodeRegistry::getTypeIndexForPort(const char *compositionIdentifier, const char *portIdentifier)
397{
398 map<string, unsigned long>::const_iterator foundIter;
399 bool found = findCachedInfoForPort<unsigned long>(typeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
400 if (found)
401 return foundIter->second;
402
403 VUserLog("Couldn't find type index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
404 return 0;
405}
406
410void VuoNodeRegistry::addPortIdentifier(const char *compositionIdentifier, const string &portIdentifier,
411 void *data, unsigned long nodeIndex, unsigned long typeIndex)
412{
413 map<string, void *>::const_iterator foundIter;
414 bool found = findCachedInfoForPort<void *>(dataForPort, compositionIdentifier, portIdentifier, foundIter);
415 if (found)
416 VUserLog("Cache overwritten for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
417
418 dataForPort[compositionIdentifier][portIdentifier] = data;
419 nodeIndexForPort[compositionIdentifier][portIdentifier] = nodeIndex;
420 typeIndexForPort[compositionIdentifier][portIdentifier] = typeIndex;
421}
422
426void VuoNodeRegistry::removePortIdentifier(const char *compositionIdentifier, const string &portIdentifier)
427{
428 {
429 map<string, void *>::const_iterator foundIter;
430 bool found = findCachedInfoForPort<void *>(dataForPort, compositionIdentifier, portIdentifier, foundIter);
431 if (found)
432 {
433 dataForPort[compositionIdentifier].erase(portIdentifier);
434
435 if (dataForPort[compositionIdentifier].empty())
436 dataForPort.erase(compositionIdentifier);
437 }
438 else
439 VUserLog("Couldn't find data for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
440 }
441 {
442 map<string, unsigned long>::const_iterator foundIter;
443 bool found = findCachedInfoForPort<unsigned long>(nodeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
444 if (found)
445 {
446 nodeIndexForPort[compositionIdentifier].erase(portIdentifier);
447
448 if (nodeIndexForPort[compositionIdentifier].empty())
449 nodeIndexForPort.erase(compositionIdentifier);
450 }
451 else
452 VUserLog("Couldn't find node index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
453 }
454 {
455 map<string, unsigned long>::const_iterator foundIter;
456 bool found = findCachedInfoForPort<unsigned long>(typeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
457 if (found)
458 {
459 typeIndexForPort[compositionIdentifier].erase(portIdentifier);
460
461 if (typeIndexForPort[compositionIdentifier].empty())
462 typeIndexForPort.erase(compositionIdentifier);
463 }
464 else
465 VUserLog("Couldn't find type index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
466 }
467}
468
472void VuoNodeRegistry::relocatePortIdentifier(const char *compositionIdentifier, const string &portIdentifier)
473{
474 {
475 map<string, void *>::const_iterator foundIter;
476 bool found = findCachedInfoForPort<void *>(dataForPort, compositionIdentifier, portIdentifier, foundIter);
477 if (found)
478 carriedOverDataForPort[compositionIdentifier][portIdentifier] = foundIter->second;
479 else
480 VUserLog("Couldn't find data for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
481 }
482 {
483 map<string, unsigned long>::const_iterator foundIter;
484 bool found = findCachedInfoForPort<unsigned long>(nodeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
485 if (found)
486 carriedOverNodeIndexForPort[compositionIdentifier][portIdentifier] = foundIter->second;
487 else
488 VUserLog("Couldn't find node index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
489 }
490 {
491 map<string, unsigned long>::const_iterator foundIter;
492 bool found = findCachedInfoForPort<unsigned long>(typeIndexForPort, compositionIdentifier, portIdentifier, foundIter);
493 if (found)
494 carriedOverTypeIndexForPort[compositionIdentifier][portIdentifier] = foundIter->second;
495 else
496 VUserLog("Couldn't find type index for port %s", buildCompositionIdentifier(compositionIdentifier, portIdentifier).c_str());
497 }
498
499 removePortIdentifier(compositionIdentifier, portIdentifier);
500}
501
506void VuoNodeRegistry::carryOverPortIdentifier(const char *oldCompositionIdentifier, const char *newCompositionIdentifier,
507 const string &portIdentifier, unsigned long nodeIndex, unsigned long typeIndex)
508{
509 map<string, void *>::const_iterator foundIter;
510 bool found = findCachedInfoForPort<void *>(carriedOverDataForPort, oldCompositionIdentifier, portIdentifier, foundIter);
511 if (! found)
512 {
513 VUserLog("Couldn't find cache for port %s", buildCompositionIdentifier(oldCompositionIdentifier, portIdentifier).c_str());
514 return;
515 }
516
517 dataForPort[newCompositionIdentifier][portIdentifier] = carriedOverDataForPort[oldCompositionIdentifier][portIdentifier];
518 nodeIndexForPort[newCompositionIdentifier][portIdentifier] = nodeIndex;
519 typeIndexForPort[newCompositionIdentifier][portIdentifier] = typeIndex;
520
521 removeCarriedOverPortIdentifier(oldCompositionIdentifier, portIdentifier);
522}
523
528void VuoNodeRegistry::carryOverPortIdentifiersForNode(const char *oldCompositionIdentifier, const char *newCompositionIdentifier,
529 const string &nodeIdentifier, unsigned long nodeIndex,
530 const vector<string> &portIdentifiers, const vector<unsigned long> typeIndexes)
531{
532 for (size_t j = 0; j < portIdentifiers.size(); ++j)
533 carryOverPortIdentifier(oldCompositionIdentifier, newCompositionIdentifier, portIdentifiers[j], nodeIndex, typeIndexes[j]);
534}
535
539void VuoNodeRegistry::removeCarriedOverPortIdentifier(const char *compositionIdentifier, const string &oldPortIdentifier)
540{
541 map<string, void *>::const_iterator foundIter;
542 bool found = findCachedInfoForPort<void *>(carriedOverDataForPort, compositionIdentifier, oldPortIdentifier, foundIter);
543 if (! found)
544 {
545 VUserLog("Couldn't find cache for port %s", buildCompositionIdentifier(compositionIdentifier, oldPortIdentifier).c_str());
546 return;
547 }
548
549 carriedOverDataForPort[compositionIdentifier].erase(oldPortIdentifier);
550 carriedOverNodeIndexForPort[compositionIdentifier].erase(oldPortIdentifier);
551 carriedOverTypeIndexForPort[compositionIdentifier].erase(oldPortIdentifier);
552
553 if (carriedOverDataForPort[compositionIdentifier].empty())
554 carriedOverDataForPort.erase(compositionIdentifier);
555 if (carriedOverNodeIndexForPort[compositionIdentifier].empty())
556 carriedOverNodeIndexForPort.erase(compositionIdentifier);
557 if (carriedOverTypeIndexForPort[compositionIdentifier].empty())
558 carriedOverTypeIndexForPort.erase(compositionIdentifier);
559}
560
566void VuoNodeRegistry::carryOverPortData(const char *oldCompositionIdentifier, const char *newCompositionIdentifier,
567 const string &oldPortIdentifier, const string &newPortIdentifier, PortContext *newPortContext)
568{
569 void *carriedOverData;
570 {
571 map<string, void *>::const_iterator foundIter;
572 bool found = findCachedInfoForPort<void *>(carriedOverDataForPort, oldCompositionIdentifier, oldPortIdentifier, foundIter);
573 if (! found)
574 {
575 VUserLog("Couldn't find data for carried-over port %s", buildCompositionIdentifier(oldCompositionIdentifier, oldPortIdentifier).c_str());
576 return;
577 }
578
579 carriedOverData = foundIter->second;
580 }
581
582 vuoSetPortContextData(newPortContext, carriedOverData);
583
584 {
585 map<string, void *>::const_iterator foundIter;
586 bool found = findCachedInfoForPort<void *>(dataForPort, newCompositionIdentifier, newPortIdentifier, foundIter);
587 if (! found)
588 {
589 VUserLog("Couldn't find data for port %s", buildCompositionIdentifier(newCompositionIdentifier, newPortIdentifier).c_str());
590 return;
591 }
592
593 dataForPort[newCompositionIdentifier][newPortIdentifier] = carriedOverData;
594 }
595}
596
604 unsigned long publishedOutputPortCount)
605{
606 const char *compositionIdentifier = compositionState->compositionIdentifier;
607
608 if (persistentState->compositionDiff->isCompositionStartingOrStopping())
609 {
610 // Create and register a node context for the top-level composition.
611 NodeContext *compositionContext = vuoCreateNodeContext(hasInstanceData, true, publishedOutputPortCount);
612 addNodeContext(compositionIdentifier, topLevelCompositionIndex, compositionContext);
613 }
614 else
615 {
616 carryOverNodeContext(compositionIdentifier, compositionIdentifier, topLevelCompositionIndex);
617 }
618
619 initContextsForCompositionContents(compositionState);
620}
621
626void VuoNodeRegistry::initContextsForCompositionContents(VuoCompositionState *compositionState)
627{
628 const char *compositionIdentifier = compositionState->compositionIdentifier;
629
630 for (size_t nodeIndex = 0; nodeIndex < nodeMetadatas[compositionIdentifier].size(); ++nodeIndex)
631 {
632 NodeMetadata nodeMetadata = nodeMetadatas[compositionIdentifier][nodeIndex];
633 NodeContext *nodeContext = NULL;
634
635 json_object *replacementObj = NULL;
636 VuoCompositionDiff::ChangeType changeType = persistentState->compositionDiff->findNode(compositionIdentifier,
637 nodeMetadata.identifier.c_str(),
638 &replacementObj);
639 if (changeType == VuoCompositionDiff::ChangeStartStop ||
641 {
642 // Create and register a node context for the added node and a port context for each of its ports.
643 NodeContext *nodeContext = nodeMetadata.compositionCreateContextForNode(nodeIndex);
644 addNodeContext(compositionIdentifier, nodeIndex, nodeContext);
645
646 // Add the added node's ports to the port cache.
647 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
648 {
649 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
650 PortContext *portContext = vuoGetNodeContextPortContext(nodeContext, portIndex);
651 void *portData = vuoGetPortContextData(portContext);
652
653 addPortIdentifier(compositionIdentifier, portMetadata.identifier, portData, nodeIndex, portMetadata.typeIndex);
654 }
655
656 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
657 {
658 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
659 PortContext *portContext = vuoGetNodeContextPortContext(nodeContext, portIndex);
660 void *portData = vuoGetPortContextData(portContext);
661
662 if (portData)
663 {
664 string oldNodeIdentifier;
665 string oldPortIdentifier;
666 if (changeType == VuoCompositionDiff::ChangeReplace &&
667 persistentState->compositionDiff->isPortReplacingAnother(portMetadata.name.c_str(), replacementObj, oldNodeIdentifier, oldPortIdentifier))
668 {
669 // Set the replacement port's data from the port it replaces.
670 carryOverPortData(compositionIdentifier, compositionIdentifier, oldPortIdentifier, portMetadata.identifier, portContext);
671
672 // Remove the port from the carried-over port info.
673 removeCarriedOverPortIdentifier(compositionIdentifier, oldPortIdentifier);
674 }
675 else
676 {
677 // Set the added port's data to its initial value.
678 nodeMetadata.compositionSetPortValue(compositionState, portMetadata.identifier.c_str(), portMetadata.initialValue.c_str(),
679 false, false, false, false, true);
680 }
681 }
682 }
683 }
684 else
685 {
686 string oldCompositionIdentifier = compositionIdentifier;
687 if (changeType == VuoCompositionDiff::ChangeMove &&
688 (! persistentState->compositionDiff->isNodeBeingMovedToHere(compositionIdentifier, nodeMetadata.identifier.c_str(), replacementObj, oldCompositionIdentifier)))
689 continue;
690
691 // Restore the kept node's context.
692 nodeContext = carryOverNodeContext(oldCompositionIdentifier.c_str(), compositionIdentifier, nodeIndex);
693
694 // Restore the kept node's ports to the port cache.
695 vector<string> portIdentifiers;
696 vector<unsigned long> typeIndexes;
697 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
698 {
699 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
700 portIdentifiers.push_back(portMetadata.identifier);
701 typeIndexes.push_back(portMetadata.typeIndex);
702 }
703 carryOverPortIdentifiersForNode(oldCompositionIdentifier.c_str(), compositionIdentifier, nodeMetadata.identifier, nodeIndex, portIdentifiers, typeIndexes);
704
705 // If the node has been packaged into a subcomposition, copy the port values with connected published input cables
706 // from here (the node inside the subcomposition) to the new subcomposition node in the parent composition.
707 if (changeType == VuoCompositionDiff::ChangeMove)
708 {
709 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
710 {
711 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
712
713 string destinationCompositionIdentifier;
714 string destinationPortIdentifier;
715 if (persistentState->compositionDiff->isPortBeingCopied(portMetadata.name.c_str(), replacementObj,
716 destinationCompositionIdentifier, destinationPortIdentifier))
717 {
718 char *portValue = getPortValue(compositionState, portMetadata.identifier.c_str(), false);
719
720 const NodeMetadata *destinationPortMetadata = getNodeMetadataForPort(destinationCompositionIdentifier.c_str(), destinationPortIdentifier.c_str());
721 VuoCompositionState *destinationCompositionState = vuoCreateCompositionState(compositionState->runtimeState, destinationCompositionIdentifier.c_str());
722 destinationPortMetadata->compositionSetPortValue(destinationCompositionState, destinationPortIdentifier.c_str(), portValue, false, false, false, true, true);
723 }
724 }
725 }
726 }
727
728 json_object_put(replacementObj);
729
730 // If the node is a subcomposition, initialize the node and port contexts within it.
731 string subcompositionIdentifier = buildCompositionIdentifier(compositionIdentifier, nodeMetadata.identifier);
732 if (nodeMetadatas.find(subcompositionIdentifier) != nodeMetadatas.end())
733 {
734 VuoCompositionState *subcompositionState = vuoCreateCompositionState(compositionState->runtimeState, subcompositionIdentifier.c_str());
735 initContextsForCompositionContents(subcompositionState);
736 vuoFreeCompositionState(subcompositionState);
737 }
738 }
739}
740
748{
749 const char *compositionIdentifier = compositionState->compositionIdentifier;
750
751 if (persistentState->compositionDiff->isCompositionStartingOrStopping())
752 {
753 // Unregister and destroy the node context for the top-level composition.
754 NodeContext *compositionContext = getNodeContext(compositionIdentifier, topLevelCompositionIndex);
755 removeNodeContext(compositionIdentifier, topLevelCompositionIndex);
756 vuoFreeNodeContext(compositionContext);
757 }
758 else
759 {
760 relocateNodeContext(compositionIdentifier, topLevelCompositionIndex);
761 }
762
763 finiContextsForCompositionContents(compositionState);
764
765 nodeMetadatas.clear();
766}
767
772void VuoNodeRegistry::finiContextsForCompositionContents(VuoCompositionState *compositionState)
773{
774 const char *compositionIdentifier = compositionState->compositionIdentifier;
775
776 for (size_t nodeIndex = 0; nodeIndex < nodeMetadatas[compositionIdentifier].size(); ++nodeIndex)
777 {
778 NodeMetadata nodeMetadata = nodeMetadatas[compositionIdentifier][nodeIndex];
779
780 json_object *replacementObj = NULL;
781 VuoCompositionDiff::ChangeType changeType = persistentState->compositionDiff->findNode(compositionIdentifier,
782 nodeMetadata.identifier.c_str(),
783 &replacementObj);
784 if (changeType == VuoCompositionDiff::ChangeStartStop ||
786 {
787 NodeContext *nodeContext = getNodeContext(compositionIdentifier, nodeIndex);
788
789 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
790 {
791 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
792 PortContext *portContext = vuoGetNodeContextPortContext(nodeContext, portIndex);
793 void *portData = vuoGetPortContextData(portContext);
794
795 bool relocated = false;
796 if (portData)
797 {
798 if (changeType == VuoCompositionDiff::ChangeReplace &&
799 persistentState->compositionDiff->isPortBeingReplaced(portMetadata.name.c_str(), replacementObj))
800 {
801 // Retain the being-replaced port's data for after the live-coding reload.
802 vuoRetainPortContextData(portContext);
803
804 // Carry over the port's data
805 relocatePortIdentifier(compositionIdentifier, portMetadata.identifier);
806 relocated = true;
807 }
808 else
809 {
810 // Release the port's data.
811 nodeMetadata.compositionReleasePortData(portData, portMetadata.typeIndex);
812 }
813 }
814
815 if (! relocated)
816 {
817 // Remove the port from the (non-carried-over) port cache.
818 removePortIdentifier(compositionIdentifier, portMetadata.identifier);
819 }
820 }
821
822 // Unregister and destroy the node's context.
823 removeNodeContext(compositionIdentifier, nodeIndex);
824 vuoFreeNodeContext(nodeContext);
825 }
826 else
827 {
828 for (size_t portIndex = 0; portIndex < nodeMetadata.portMetadatas.size(); ++portIndex)
829 {
830 // Carry over the port's data
831 PortMetadata portMetadata = nodeMetadata.portMetadatas[portIndex];
832 relocatePortIdentifier(compositionIdentifier, portMetadata.identifier);
833 }
834
835 // Carry over the node's context
836 relocateNodeContext(compositionIdentifier, nodeIndex);
837 }
838
839 json_object_put(replacementObj);
840
841 string subcompositionIdentifier = buildCompositionIdentifier(compositionIdentifier, nodeMetadata.identifier);
842 if (nodeMetadatas.find(subcompositionIdentifier) != nodeMetadatas.end())
843 {
844 // Recursive call for subcomposition.
845 VuoCompositionState *subcompositionState = vuoCreateCompositionState(compositionState->runtimeState, subcompositionIdentifier.c_str());
846 finiContextsForCompositionContents(subcompositionState);
847 vuoFreeCompositionState(subcompositionState);
848 }
849 }
850}
851
858void VuoNodeRegistry::setPortValue(VuoCompositionState *compositionState, const char *portIdentifier, const char *valueAsString)
859{
860 const NodeMetadata *nm = getNodeMetadataForPort(compositionState->compositionIdentifier, portIdentifier);
861 if (!nm)
862 return;
863
864 nm->compositionSetPortValue(compositionState, portIdentifier, valueAsString, true, true, true, true, true);
865}
866
873char * VuoNodeRegistry::getPortValue(VuoCompositionState *compositionState, const char *portIdentifier, bool shouldUseInterprocessSerialization)
874{
875 const NodeMetadata *nm = getNodeMetadataForPort(compositionState->compositionIdentifier, portIdentifier);
876 if (!nm)
877 return nullptr;
878
879 return nm->compositionGetPortValue(compositionState, portIdentifier, shouldUseInterprocessSerialization ? 2 : 1, true);
880}
881
888char * VuoNodeRegistry::getPortSummary(VuoCompositionState *compositionState, const char *portIdentifier)
889{
890 const NodeMetadata *nm = getNodeMetadataForPort(compositionState->compositionIdentifier, portIdentifier);
891 if (!nm)
892 return nullptr;
893
894 return nm->compositionGetPortValue(compositionState, portIdentifier, 0, true);
895}
896
903void VuoNodeRegistry::fireTriggerPortEvent(VuoCompositionState *compositionState, const char *portIdentifier)
904{
905 const NodeMetadata *nm = getNodeMetadataForPort(compositionState->compositionIdentifier, portIdentifier);
906 if (!nm)
907 return;
908
909 nm->compositionFireTriggerPortEvent(compositionState, portIdentifier);
910}
911
915void VuoNodeRegistry::print(void)
916{
917 const char *indent = " ";
918
919 ostringstream oss;
920 oss << "=== node metadatas ===" << endl << endl;
921 for (map<string, vector<NodeMetadata> >::iterator i = nodeMetadatas.begin(); i != nodeMetadatas.end(); ++i)
922 {
923 oss << indent << i->first << endl;
924 for (size_t j = 0; j < i->second.size(); ++j)
925 oss << indent << indent << j << " " << i->second[j].identifier << ", " << i->second[j].portMetadatas.size() << " ports" << endl;
926 }
927 oss << endl;
928
929 oss << "=== node contexts ===" << endl << endl;
930 for (map<unsigned long, map<unsigned long, NodeContext *> >::iterator i = nodeContextForIndex.begin(); i != nodeContextForIndex.end(); ++i)
931 {
932 string compositionIdentifier = getCompositionIdentifierForHash(i->first);
933 oss << indent << compositionIdentifier << endl;
934 for (map<unsigned long, NodeContext *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
935 oss << indent << indent << getNodeIdentifierForIndex(compositionIdentifier.c_str(), j->first) << " " << j->second << endl;
936 }
937 oss << endl;
938
939 oss << "=== carried-over node contexts ===" << endl << endl;
940 for (map<string, map<string, NodeContext *> >::iterator i = carriedOverNodeContextForIdentifier.begin(); i != carriedOverNodeContextForIdentifier.end(); ++i)
941 {
942 oss << indent << i->first << endl;
943 for (map<string, NodeContext *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
944 oss << indent << indent << j->first << " " << j->second << endl;
945 }
946 oss << endl;
947
948 oss << "=== cached ports ===" << endl << endl;
949 for (map<string, map<string, void *> >::iterator i = dataForPort.begin(); i != dataForPort.end(); ++i)
950 {
951 oss << indent << i->first << endl;
952 for (map<string, void *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
953 oss << indent << indent << j->first << " " << j->second << endl;
954 }
955 oss << endl;
956
957 oss << "=== carried-over cached ports ===" << endl << endl;
958 for (map<string, map<string, void *> >::iterator i = carriedOverDataForPort.begin(); i != carriedOverDataForPort.end(); ++i)
959 {
960 oss << indent << i->first << endl;
961 for (map<string, void *>::iterator j = i->second.begin(); j != i->second.end(); ++j)
962 oss << indent << indent << j->first << " " << j->second << endl;
963 }
964 oss << endl;
965
966 VUserLog("\n%s", oss.str().c_str());
967}
968
969extern "C"
970{
971
977void vuoAddNodeMetadata(VuoCompositionState *compositionState, const char *nodeIdentifier,
978 NodeContext *(*compositionCreateContextForNode)(unsigned long),
979 void (*compositionSetPortValue)(VuoCompositionState *, const char *, const char *, bool, bool, bool, bool, bool),
980 char * (*compositionGetPortValue)(VuoCompositionState *, const char *, int, bool),
981 void (*compositionFireTriggerPortEvent)(VuoCompositionState *, const char *),
982 void (*compositionReleasePortData)(void *, unsigned long))
983{
985 const char *compositionIdentifier = compositionState->compositionIdentifier;
986 runtimeState->persistentState->nodeRegistry->addNodeMetadata(compositionIdentifier, nodeIdentifier,
987 compositionCreateContextForNode, compositionSetPortValue,
988 compositionGetPortValue, compositionFireTriggerPortEvent,
989 compositionReleasePortData);
990}
991
995void vuoAddPortMetadata(VuoCompositionState *compositionState, const char *portIdentifier, const char *portName,
996 unsigned long typeIndex, const char *initialValue)
997{
999 const char *compositionIdentifier = compositionState->compositionIdentifier;
1000 runtimeState->persistentState->nodeRegistry->addPortMetadata(compositionIdentifier, portIdentifier, portName, typeIndex, initialValue);
1001}
1002
1006NodeContext * vuoGetNodeContext(VuoCompositionState *compositionState, unsigned long nodeIndex)
1007{
1009 const char *compositionIdentifier = compositionState->compositionIdentifier;
1010 return runtimeState->persistentState->nodeRegistry->getNodeContext(compositionIdentifier, nodeIndex);
1011}
1012
1017{
1019 const char *compositionIdentifier = compositionState->compositionIdentifier;
1020 return runtimeState->persistentState->nodeRegistry->getCompositionContext(compositionIdentifier);
1021}
1022
1026void * vuoGetDataForPort(VuoCompositionState *compositionState, const char *portIdentifier)
1027{
1029 const char *compositionIdentifier = compositionState->compositionIdentifier;
1030 return runtimeState->persistentState->nodeRegistry->getDataForPort(compositionIdentifier, portIdentifier);
1031}
1032
1036unsigned long vuoGetNodeIndexForPort(VuoCompositionState *compositionState, const char *portIdentifier)
1037{
1039 const char *compositionIdentifier = compositionState->compositionIdentifier;
1040 return runtimeState->persistentState->nodeRegistry->getNodeIndexForPort(compositionIdentifier, portIdentifier);
1041}
1042
1046unsigned long vuoGetTypeIndexForPort(VuoCompositionState *compositionState, const char *portIdentifier)
1047{
1049 const char *compositionIdentifier = compositionState->compositionIdentifier;
1050 return runtimeState->persistentState->nodeRegistry->getTypeIndexForPort(compositionIdentifier, portIdentifier);
1051}
1052
1058void vuoInitContextForTopLevelComposition(VuoCompositionState *compositionState, bool hasInstanceData, unsigned long publishedOutputPortCount)
1059{
1061 return runtimeState->persistentState->nodeRegistry->initContextForTopLevelComposition(compositionState, hasInstanceData, publishedOutputPortCount);
1062}
1063
1074
1075}