void model_preset_amenities(TTPtr self) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTAddress modelAdrs; TTValue v, a, args, none; TTAddress presetAddress; // get model:address EXTRA->modelInfo->get(kTTSym_address, v); modelAdrs = v[0]; // create the preset manager jamoma_presetManager_create((t_object*)x, *EXTRA->presetManager); // suscribe it under a preset node presetAddress = modelAdrs.appendAddress(TTAddress("preset")); args = TTValue(presetAddress, *EXTRA->presetManager, x->patcherPtr); if (!MaxApplication.send("ObjectRegister", args, none)) { EXTRA->presetManager->set(kTTSym_address, modelAdrs); defer_low(x, (method)model_preset_default, 0, 0, 0L); } }
TTErr TTAddressItem::append(TTAddress addressToAppend, TTAddressItemPtr *returnedItem) { TTAddressItemPtr anItem = this; TTAddressItemPtr nextItem; TTList nameInstanceList; TTSymbol nameInstance(kTTSymEmpty); addressToAppend.listNameInstance(nameInstanceList); for (nameInstanceList.begin(); nameInstanceList.end(); nameInstanceList.next()) { nameInstance = nameInstanceList.current()[0]; nextItem = anItem->getItem(nameInstance); if (!nextItem) { nextItem = new TTAddressItem(nameInstance, anItem); ((TTListPtr)anItem)->append((TTPtr)nextItem); } anItem = nextItem; } anItem->options->appendUnique(addressToAppend.getAttribute()); *returnedItem = anItem; return kTTErrNone; }
TTErr makeInternals_viewer(TTPtr self, TTAddress address, TTSymbol name, t_symbol *callbackMethod, TTObject& returnedViewer, TTBoolean deferlow) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue v, baton; TTAddress adrs; // check the internals do not exist yet if (!x->internals->lookup(name, v)) { returnedViewer = v[0]; JamomaDebug object_post((t_object*)x, "makeInternals_viewer : \"%s\" internal already exists", name.c_str()); return kTTErrNone; } returnedViewer = TTObject(kTTSym_Viewer); baton = TTValue(TTPtr(x), TTPtr(callbackMethod), deferlow); returnedViewer.set(kTTSym_baton, baton); returnedViewer.set(kTTSym_function, TTPtr(&jamoma_callback_return_value)); // edit address adrs = address.appendAddress(TTAddress(name)); // default registration case : store object only (see in unregister method) x->internals->append(name, returnedViewer); // set address attribute (after registration as the value can be updated in the same time) returnedViewer.set(kTTSym_address, adrs); JamomaDebug object_post((t_object*)x, "makes internal \"%s\" viewer to bind on : %s", name.c_str(), adrs.c_str()); return kTTErrNone; }
TTErr makeInternals_sender(TTPtr self, TTAddress address, TTSymbol name, TTObject& returnedSender, TTBoolean appendNameAsAttribute) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue v; TTAddress adrs; // check the internals do not exist yet if (!x->internals->lookup(name, v)) { returnedSender = v[0]; JamomaDebug object_post((t_object*)x, "makeInternals_sender : \"%s\" internal already exists", name.c_str()); return kTTErrNone; } returnedSender = TTObject(kTTSym_Sender); // edit address if (appendNameAsAttribute) adrs = address.appendAttribute(name); else adrs = address.appendAddress(TTAddress(name.c_str())); // default registration case : store object only (see in unregister method) x->internals->append(name, returnedSender); // set address attribute returnedSender.set(kTTSym_address, adrs); JamomaDebug object_post((t_object*)x, "makes internal \"%s\" sender to bind on : %s", name.c_str(), adrs.c_str()); return kTTErrNone; }
void init_subscribe(t_init *x) { TTValue v, args, none; TTAddress contextAddress = kTTAdrsEmpty; TTAddress returnedAddress; TTNodePtr returnedNode = NULL; TTNodePtr returnedContextNode = NULL; TTObject returnAddressCallback, returnValueCallback, empty; // for relative address if (x->address.getType() == kAddressRelative) { if (!jamoma_subscriber_create((t_object*)x, empty, x->address, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) { // get the context address to make // a receiver on the contextAddress:initialized attribute x->subscriberObject.get("contextAddress", v); contextAddress = v[0]; } // bind on the /model:address parameter (view patch) or return (model patch) if (contextAddress != kTTAdrsEmpty) { // Make a TTReceiver object returnAddressCallback = TTObject("callback"); returnAddressCallback.set(kTTSym_baton, TTPtr(x)); returnAddressCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_address)); args.append(returnAddressCallback); returnValueCallback = TTObject("callback"); returnValueCallback.set(kTTSym_baton, TTPtr(x)); returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value)); args.append(returnValueCallback); x->initReceiver = TTObject(kTTSym_Receiver, args); x->initReceiver.set(kTTSym_address, contextAddress.appendAttribute(kTTSym_initialized)); } // while the context node is not registered : try to binds again :( // (to -- this is not a good way todo. For binding we should make a subscription // to a notification mechanism and each time an TTObjet subscribes to the namespace // using jamoma_subscriber_create we notify all the externals which have used // jamoma_subscriber_create with NULL object to bind) else { // release the subscriber x->subscriberObject = TTObject(); // The following must be deferred because we have to interrogate our box, // and our box is not yet valid until we have finished instantiating the object. // Trying to use a loadbang method instead is also not fully successful (as of Max 5.0.6) defer_low((t_object*)x, (method)init_subscribe, NULL, 0, 0); } } else object_error((t_object*)x, "can't bind because %s is not a relative address", x->address.c_str()); }
void out_subscribe(TTPtr self) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTAddress signalAddress; TTAddress outputAddress; TTAddress inputAddress; TTValue v, args; TTNodePtr returnedNode = NULL; TTNodePtr returnedContextNode = NULL; TTAddress returnedAddress, parentAddress; TTString formatDescription, sInstance; t_object *modelOrView = NULL; #ifdef J_OUT_TILDE signalAddress = TTAddress("audio"); #endif #ifdef J_OUT_MULTI signalAddress = TTAddress("audio"); #endif #ifndef J_OUT_TILDE #ifndef J_OUT_MULTI signalAddress = TTAddress("data"); #endif #endif // edit "signal/out.instance" address outputAddress = signalAddress.appendAddress(TTAddress("out")).appendInstance(EXTRA->instance); // if the subscription is successful if (!jamoma_subscriber_create((t_eobj*)x, x->wrappedObject, outputAddress, x->subscriberObject, returnedAddress, &returnedNode, &returnedContextNode)) { // get patcher x->patcherPtr = ((t_eobj*)x)->o_canvas; // update instance symbol in case of duplicate instance EXTRA->instance = returnedAddress.getInstance(); // observe /parent/in address in order to link/unlink with an Input object below returnedNode->getParent()->getAddress(parentAddress); inputAddress = parentAddress.appendAddress(TTAddress("in")).appendInstance(EXTRA->instance); x->wrappedObject.set("inputAddress", inputAddress); // get model or view object jamoma_patcher_get_model_or_view(x->patcherPtr, &modelOrView); // notify the model there is something new concerning signal processing if (modelOrView) object_method_typed(modelOrView, gensym("output_created"), 0, NULL, NULL); } }
TTErr makeInternals_data(TTPtr self, TTAddress address, TTSymbol name, t_symbol *callbackMethod, TTPtr context, TTSymbol service, TTObject& returnedData, TTBoolean deferlow) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue baton, v, out; TTAddress dataAddress, dataRelativeAddress; TTNodePtr dataNode; returnedData = TTObject(kTTSym_Data, service); baton = TTValue(TTPtr(x), TTPtr(callbackMethod), deferlow); returnedData.set(kTTSym_baton, baton); returnedData.set(kTTSym_function, TTPtr(&jamoma_callback_return_value)); // absolute registration dataAddress = address.appendAddress(TTAddress(name)); v = TTValue(dataAddress, returnedData, context); out = MaxApplication.send("ObjectRegister", v); // retreive relative effective address dataAddress = out[0]; dataNode = TTNodePtr((TTPtr)out[1]); dataNode->getAddress(dataRelativeAddress, address); // absolute registration case : set the address in second position (see in unregister method) v = TTValue(returnedData, dataAddress); x->internals->append(dataRelativeAddress, v); JamomaDebug object_post((t_object*)x, "makes internal \"%s\" %s at : %s", dataRelativeAddress.c_str(), service.c_str(), dataAddress.c_str()); return kTTErrNone; }
TTErr WebSocketAnswerManager::ReceiveDiscoverAnswer(TTSymbol from, TTAddress address, const TTValue& value, TTErr error) { TTValue v; TTString key; WebSocketAnswerPtr anAnswer; TTErr err; key = from.string(); key += address.string(); err = mDiscoverAnswers->lookup(TTSymbol(key), v); if (!err) { anAnswer = WebSocketAnswerPtr((TTPtr)v[0]); if (anAnswer->getState() != TIMEOUT_EXCEEDED) { anAnswer->setAnswer(value, error); return kTTErrNone; } } else cout << "WebSocketAnswerManager::ReceiveDiscoverAnswer can't find a request at " << key << endl; return kTTErrGeneric; }
TTErr TTAddressItem::remove(TTAddress addressToRemove) { TTAddressItemPtr anItem, parentItem; // if the item exist if (!this->find(addressToRemove, &anItem)) { // remove option (even empty option) anItem->options->remove(addressToRemove.getAttribute()); // if there no more options if (anItem->options->isEmpty()) { // destroy upper parents if there are empty after removing the item do { parentItem = anItem->getParent(); ((TTListPtr)parentItem)->remove((TTPtr)anItem); destroy(anItem); anItem = parentItem; } while (anItem->isEmpty()) ; } return kTTErrNone; } return kTTErrValueNotFound; }
TTErr TTProtocol::ReceiveGetRequest(TTSymbol from, TTAddress address) { TTErr err; TTValue returnedValue; if (!mRunning) return kTTErrGeneric; // discover the namespace if (address.getAttribute() == NO_ATTRIBUTE) address = address.appendAttribute(kTTSym_value); err = mApplicationManager.send("ApplicationGet", address, returnedValue); return SendGetAnswer(from, address, returnedValue, err); }
TTErr TTProtocol::ReceiveSetRequest(TTSymbol from, TTAddress address, const TTValue& newValue) { TTValue v, none; TTErr err; // set the an object in the namespace if (address.getAttribute() == NO_ATTRIBUTE) address = address.appendAttribute(kTTSym_value); v.append(address); v.append((TTPtr)&newValue); err = mApplicationManager.send("ApplicationSet", v); // TODO : test error and send notification if error return err; }
TTErr makeInternals_receiver(TTPtr self, TTAddress address, TTSymbol name, t_symbol *callbackMethod, TTObject& returnedReceiver, TTBoolean deferlow, TTBoolean appendNameAsAttribute) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue v, args, baton; TTObject returnValueCallback, empty; TTAddress adrs; // check the internals do not exist yet if (!x->internals->lookup(name, v)) { returnedReceiver = v[0]; JamomaDebug object_post((t_object*)x, "makeInternals_receiver : \"%s\" internal already exists", name.c_str()); returnedReceiver.send("Get"); return kTTErrNone; } // prepare arguments // we don't want the address back args.append(empty); returnValueCallback = TTObject("callback"); baton = TTValue(TTPtr(x), TTPtr(callbackMethod), deferlow); returnValueCallback.set(kTTSym_baton, baton); returnValueCallback.set(kTTSym_function, TTPtr(&jamoma_callback_return_value)); args.append(returnValueCallback); returnedReceiver = TTObject(kTTSym_Receiver, args); // edit address if (appendNameAsAttribute) adrs = address.appendAttribute(name); else adrs = address.appendAddress(TTAddress(name.c_str())); // default registration case : store object only (see in unregister method) x->internals->append(name, returnedReceiver); // set address attribute (after registration as the value can be updated in the same time) returnedReceiver.set(kTTSym_address, adrs); JamomaDebug object_post((t_object*)x, "makes internal \"%s\" receiver to bind on : %s", name.c_str(), adrs.c_str()); return kTTErrNone; }
void WebSocketAnswerManager::AddDiscoverAnswer(TTSymbol from, TTAddress address, int timeOutInMs) { TTString key = from.string(); key += address.string(); WebSocketAnswerPtr anAnswer = new WebSocketAnswer(); anAnswer->setTimeOut(timeOutInMs); mDiscoverAnswers->append(TTSymbol(key), (TTPtr)anAnswer); }
TTErr TTProtocol::ReceiveListenAnswer(TTSymbol from, TTAddress address, const TTValue& newValue) { TTValue v, none; TTErr err; TTValue dummy; if (address.getAttribute() == NO_ATTRIBUTE) address = address.appendAttribute(kTTSym_value); v.append(from); v.append(address); v.append((TTPtr)&newValue); err = mApplicationManager.send("ApplicationListenAnswer", v); if (err && mRunning) return SendListenAnswer(from, address, dummy, err); return kTTErrGeneric; }
TTErr TTProtocol::ReceiveListenRequest(TTSymbol from, TTAddress address, TTBoolean enable) { TTValue v, none; TTErr err; // listen an object or the namespace if (address.getAttribute() == NO_ATTRIBUTE) address = address.appendAttribute(kTTSym_value); v.append(mName); // the name of the protocol is needed for feed back notifications v.append(from); v.append(address); v.append(enable); err = mApplicationManager.send("ApplicationListen", v); if (err && mRunning) return SendListenAnswer(from, address, none, err); return kTTErrGeneric; }
TTErr removeInternals_data(TTPtr self, TTAddress address, TTAddress name) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue v; TTAddress dataAddress; TTErr err; err = x->internals->lookup(name, v); if (!err) { dataAddress = v[1]; JamomaDebug object_post((t_object*)x, "Remove internal %s object at : %s", name.c_str(), dataAddress.c_str()); MaxApplication.send("ObjectUnregister", dataAddress); x->internals->remove(name); } return kTTErrNone; }
TTErr TTAddressItem::find(TTAddress addressToFind, TTAddressItemPtr *returnedItem) { TTAddressItemPtr anItem = this; TTAddressItemPtr nextItem; TTList nameInstanceList; TTSymbol nameInstance(kTTSymEmpty); TTValue v; addressToFind.listNameInstance(nameInstanceList); if (nameInstanceList.isEmpty()) return kTTErrGeneric; for (nameInstanceList.begin(); nameInstanceList.end(); nameInstanceList.next()) { nameInstance = nameInstanceList.current()[0]; nextItem = anItem->getItem(nameInstance); if (!nextItem) return kTTErrValueNotFound; else anItem = nextItem; } if (anItem->options->isEmpty() && addressToFind.getAttribute() == NO_ATTRIBUTE) { *returnedItem = anItem; return kTTErrNone; } if (!anItem->options->findEquals(addressToFind.getAttribute(), v)) { *returnedItem = anItem; return kTTErrNone; } return kTTErrValueNotFound; }
TTErr TTProtocolListenAttributeCallback(const TTValue& baton, const TTValue& data) { TTObject aProtocol; TTSymbol anApplicationName; TTAddress anAddress; TTSymbol attribute; TTBoolean enable; // unpack baton aProtocol = baton[0]; anApplicationName = baton[1]; anAddress = baton[2]; // unpack data attribute = data[0]; enable = data[1]; // send a listen request if (TTProtocolPtr(aProtocol.instance())->mRunning) return TTProtocolPtr(aProtocol.instance())->SendListenRequest(anApplicationName, anAddress.appendAttribute(attribute), enable); else return kTTErrGeneric; }
TTErr TTProtocolSendMessageCallback(const TTValue& baton, const TTValue& data) { TTValuePtr value; TTObject aProtocol; TTSymbol anApplicationName; TTAddress anAddress; TTSymbol message; // unpack baton aProtocol = baton[0]; anApplicationName = baton[1]; anAddress = baton[2]; // unpack data message = data[0]; value = TTValuePtr((TTPtr)data[1]); // send a set request if (TTProtocolPtr(aProtocol.instance())->mRunning) return TTProtocolPtr(aProtocol.instance())->SendSetRequest(anApplicationName, anAddress.appendAttribute(message), *value); else return kTTErrGeneric; }
TTErr TTProtocolDirectoryCallback(const TTValue& baton, const TTValue& data) { TTObject aProtocol; TTSymbol anApplicationName; TTAddress anAddress; TTNodePtr aNode; TTUInt8 flag; TTObject anObserver; TTValue v; // unpack baton aProtocol = baton[0]; anApplicationName = baton[1]; // unpack data (anAddress, aNode, flag, anObserver) anAddress = data[0]; aNode = TTNodePtr((TTPtr)data[1]); flag = data[2]; anObserver = data[3]; if (flag == kAddressCreated) { if (aNode->getObject().valid()) v.append(aNode->getObject().name()); else v.append(kTTSym_none); } else if (flag == kAddressDestroyed) { v.append(TTSymbol("delete")); } if (TTProtocolPtr(aProtocol.instance())->mRunning) return TTProtocolPtr(aProtocol.instance())->SendListenAnswer(anApplicationName, anAddress.appendAttribute(TTSymbol("life")), v); else return kTTErrGeneric; }
int WebSocketAnswerManager::CheckDiscoverAnswer(TTSymbol from, TTAddress address, TTValue& value) { int state; TTValue v; TTString key; WebSocketAnswerPtr anAnswer; TTErr err; key = from.string(); key += address.string(); // Looking for a WebSocketDiscoverAnswer object at the given address err = mDiscoverAnswers->lookup(TTSymbol(key), v); if (!err) { anAnswer = WebSocketAnswerPtr((TTPtr)v[0]); // wait anAnswer->wait(); state = anAnswer->getState(); // if an answer is received if(state != NO_ANSWER) { // get the answer anAnswer->getAnswer(value); mDiscoverAnswers->remove(TTSymbol(key)); delete anAnswer; } return state; } else return REQUEST_NOT_SENT; }
void TTNodeLibTestMiscellaneous(int& errorCount, int& testAssertionCount) { TTTestLog("\n"); TTTestLog("Miscellaneous Tests"); // test convertUpperCasedName global method TTSymbol testSymbolA = "TestSymbolName"; TTSymbol testSymbolB = "testSymbolName"; TTSymbol testSymbolC = "testsymbolname"; TTAddress result; convertUpperCasedNameInAddress(testSymbolA, result); TTTestAssertion("convertUpperCasedName: Test passes if \"TestSymbolName\" is converted in \"test/symbol/name\"", result == TTAddress("test/symbol/name"), testAssertionCount, errorCount); convertUpperCasedNameInAddress(testSymbolB, result); TTTestAssertion("convertUpperCasedName: Test passes if \"testSymbolName\" is converted in \"test/symbol/name\"", result == TTAddress("test/symbol/name"), testAssertionCount, errorCount); convertUpperCasedNameInAddress(testSymbolC, result); TTTestAssertion("convertUpperCasedName: Test passes if \"testsymbolname\" is not converted", result == testSymbolC, testAssertionCount, errorCount); // test TTSymbol to TTAdress casting TTValue testValue = TTValue(TTSymbol("directory:/gran/parent/name.instance:attribute")); TTAddress testAddress; testAddress = testValue[0]; TTSymbol directory = testAddress.getDirectory(); TTAddress parent = testAddress.getParent(); TTSymbol name = testAddress.getName(); TTSymbol instance = testAddress.getInstance(); TTSymbol attribute = testAddress.getAttribute(); TTAddressType type = testAddress.getType(); TTBoolean t1 = directory == TTSymbol("directory"); TTBoolean t2 = parent == TTAddress("/gran/parent"); TTBoolean t3 = name == TTSymbol("name"); TTBoolean t4 = instance == TTSymbol("instance"); TTBoolean t5 = attribute == TTSymbol("attribute"); TTBoolean t6 = type == kAddressAbsolute; TTTestAssertion("TTValue::get : Test2 fails if a TTSymbol contained into a value is not casted into a TTAddress during a get method", directory == TTSymbol("directory") && parent == TTAddress("/gran/parent") && name == TTSymbol("name") && instance == TTSymbol("instance") && attribute == TTSymbol("attribute") && type == kAddressAbsolute, testAssertionCount, errorCount); // test TTSymbol for TTHash access when a key is stored using a TTAddress TTHash testTable; TTAddress keyAddress = TTAddress("testKeyAddress"); TTValue keyValue; TTErr err; testTable.append(keyAddress, keyValue); // store a value into the table using "testKeyAddress" address testValue = TTValue(TTSymbol("testKeyAddress")); // store a "testKeyAddress" symbol into a value testAddress = testValue[0]; // get it as an address err = testTable.lookup(testAddress, keyValue); // use the address to lookup the table TTTestAssertion("TTHash::lookup : Test fails if a TTSymbol cannot be used as storage key for TTHash table when the lookup key is a TTAddress", err == kTTErrNone, testAssertionCount, errorCount); // The test below fails but it have been added only to check the opposite operation. // For instant we don't need this test to pass so it is commented out until we need this feature. /* test TTAddress for TTHash access when a key is stored using a TTSymbol TTSymbol keySymbol = TTSymbol("testKeySymbol"); TTSymbol testSymbol; testTable.append(keySymbol, keyValue); // store a value into the table using "testKeySymbol" symbol testValue = TTValue(TTAddress("testKeySymbol")); // store a "testKeySymbol" address into a value testSymbol = testValue[0]; // get it as an symbol err = testTable.lookup(testSymbol, keyValue); // use the symbol to lookup the table TTTestAssertion("TTHash::lookup : Test fails if a TTAddress cannot be used as storage key for TTHash table when the lookup key is a TTSymbol", err == kTTErrNone, testAssertionCount, errorCount); */ }
void wrappedModularClass_unregister(WrappedModularInstancePtr x) { TTValue keys, v; TTSymbol name; TTAddress objectAddress; TTErr err; #ifndef ARRAY_EXTERNAL x->subscriberObject = TTObject(); // check the wrappedObject is still valid because it could have been released in spec->_free method if (x->wrappedObject.valid()) { // don't release the local application if (!(x->wrappedObject.instance() == accessApplicationLocal)) { if (x->wrappedObject.instance()->getReferenceCount() > 1) object_error((t_object*)x, "there are still unreleased reference of the wrappedObject (refcount = %d)", x->wrappedObject.instance()->getReferenceCount() - 1); // this line should release the last instance of the wrapped object // otherwise there is something wrong x->wrappedObject = TTObject(); } } #endif if (!x->internals->isEmpty()) { err = x->internals->getKeys(keys); if (!err) { x->iterateInternals = YES; for (int i = 0; i < (TTInt32) keys.size(); i++) { name = keys[i]; err = x->internals->lookup(name, v); if (!err) { TTObject o = v[0]; if (o.name() == kTTSym_Sender || o.name() == kTTSym_Receiver || o.name() == kTTSym_Viewer) o.set(kTTSym_address, kTTAdrsEmpty); // absolute registration case : remove the address if (v.size() == 2) { objectAddress = v[1]; JamomaDebug object_post((t_object*)x, "Remove internal %s object at : %s", name.c_str(), objectAddress.c_str()); MaxApplication.send("ObjectUnregister", objectAddress); } } } x->iterateInternals = NO; } x->internals->clear(); } }