TTErr convertUpperCasedNameInAddress(TTSymbol upperCasedName, TTAddress& convertedInAddress) { TTUInt32 upperCasedNameSize = strlen(upperCasedName.c_str()); TTCString upperCasedNameCString = new char[upperCasedNameSize+1]; TTUInt32 nbUpperCase = 0; TTUInt32 i; TTCString convertedNameCString = NULL; TTUInt32 convertedNameSize = 0; strncpy(upperCasedNameCString, upperCasedName.c_str(), upperCasedNameSize+1); // "ExampleName" to "example/name" // "anyOtherExample" to "any/other/example" if ((upperCasedNameCString[0] > 64 && upperCasedNameCString[0] < 91) || (upperCasedNameCString[0] > 96 && upperCasedNameCString[0] < 123)) { // count how many upper-case letter there are in the TTName after the first letter for (i=1; i<upperCasedNameSize; i++) { if (upperCasedNameCString[i] > 64 && upperCasedNameCString[i] < 91) nbUpperCase++; } // prepare the convertedName convertedNameSize = upperCasedNameSize + nbUpperCase; convertedNameCString = new char[convertedNameSize+1]; // convert first letter to lower-case if needed if (upperCasedNameCString[0] > 64 && upperCasedNameCString[0] < 91) convertedNameCString[0] = upperCasedNameCString[0] + 32; else convertedNameCString[0] = upperCasedNameCString[0]; // copy each letter while checking upper-case letter to replace them by a / + lower-case letter nbUpperCase = 0; for (i=1; i<upperCasedNameSize; i++) { if (upperCasedNameCString[i] > 64 && upperCasedNameCString[i] < 91) { convertedNameCString[i + nbUpperCase] = '/'; convertedNameCString[i + nbUpperCase + 1] = upperCasedNameCString[i] + 32; nbUpperCase++; } else convertedNameCString[i + nbUpperCase] = upperCasedNameCString[i]; } // ends the CString with a NULL letter convertedNameCString[convertedNameSize] = 0; convertedInAddress = TTAddress(convertedNameCString); delete convertedNameCString; convertedNameCString = NULL; } else convertedInAddress = TTAddress(upperCasedName); delete upperCasedNameCString; upperCasedNameCString = NULL; return kTTErrNone; }
// C Callback from any Graph Source objects we are observing void UnpackGraphCallback(UnpackPtr self, TTValue& arg) { TTDictionaryPtr aDictionary = NULL; TTValue v; long ac; t_atom* ap; TTBoolean firstItemASymbol = NO; TTSymbol firstItem; //arg.get(0, (TTPtr*)(&aDictionary)); aDictionary = (TTDictionaryPtr)(TTPtr)arg[0]; aDictionary->getValue(v); ac = v.size(); if (ac) { ap = new t_atom[ac]; for (int i=0; i<ac; i++) { if (v[i].type() == kTypeInt8 || v[i].type() == kTypeUInt8 || v[i].type() == kTypeInt16 || v[i].type() == kTypeUInt16 || v[i].type() == kTypeInt32 || v[i].type() == kTypeUInt32 || v[i].type() == kTypeInt64 || v[i].type() == kTypeUInt64) { TTInt32 ival; ival = v[i]; atom_setlong(ap+i, ival); } else if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64) { atom_setfloat(ap+i, v[i]); } else if (v[i].type() == kTypeSymbol) { TTSymbol s; s = v[i]; atom_setsym(ap+i, gensym((char*)s.c_str())); if (i==0) { firstItemASymbol = YES; firstItem = s; } } } if (firstItemASymbol) outlet_anything(self->graphOutlets[0], gensym((char*)firstItem.c_str()), ac-1, ap+1); else if (ac == 1) outlet_float(self->graphOutlets[0], atom_getfloat(ap)); else outlet_anything(self->graphOutlets[0], _sym_list, ac, ap); delete ap; } }
MaxErr OpGetOperand(OpPtr self, ObjectPtr attr, AtomCount* argc, AtomPtr* argv) { TTValue v; self->audioGraphObject->getUnitGenerator()->getAttributeValue(TT("operand"), v); *argc = v.getSize(); if (!(*argv)) // otherwise use memory passed in *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * v.getSize()); for (int i=0; i<v.getSize(); i++) { if(v.getType(i) == kTypeFloat32 || v.getType(i) == kTypeFloat64){ TTFloat64 value; v.get(i, value); atom_setfloat(*argv+i, value); } else if(v.getType(i) == kTypeSymbol){ TTSymbol value; v.get(i, value); atom_setsym(*argv+i, gensym((char*)value.c_str())); } else{ // assume int TTInt32 value; v.get(i, value); atom_setlong(*argv+i, value); } } return MAX_ERR_NONE; }
/* The attribute getter */ t_max_err MaxAudioGraphWrappedClass_attrGet(WrappedInstancePtr self, ObjectPtr attr, AtomCount* argc, AtomPtr* argv) { SymbolPtr attrName = (SymbolPtr)object_method(attr, _sym_getname); TTValue v; AtomCount i; TTSymbol ttAttrName(attrName->s_name); self->audioGraphObject->getUnitGenerator()->getAttributeValue(ttAttrName, v); *argc = v.getSize(); if (!(*argv)) // otherwise use memory passed in *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * v.getSize()); for (i=0; i<v.getSize(); i++) { if(v.getType(i) == kTypeFloat32 || v.getType(i) == kTypeFloat64){ TTFloat64 value; v.get(i, value); atom_setfloat(*argv+i, value); } else if(v.getType(i) == kTypeSymbol){ TTSymbol value; v.get(i, value); atom_setsym(*argv+i, gensym((char*)value.c_str())); } else{ // assume int TTInt32 value; v.get(i, value); atom_setlong(*argv+i, value); } } return MAX_ERR_NONE; }
int main(int argc, const char * argv[]) { std::cout << "BEGIN testing for AnalysisLib...\n"; // CUSTOMIZE TTLoadJamomaExtension_AnalysisLib(); // CUSTOMIZE TTValue classNames; // if the follow group tag is present within the thisTTClassTags definition, the class will be tested TTValue testClassesWithTheseTags(TT("dspAnalysisLib")); // CUSTOMIZE TTObject::GetRegisteredClassNamesForTags(classNames, testClassesWithTheseTags); for (int i=0; i<classNames.size(); i++) { TTSymbol name = classNames[i]; try { TTObject obj(name); std::cout << "TESTING " << name.string() << std::endl; obj.send("test"); } catch (...) { TTLogMessage("UnitTest Failure to instantiate object of class %s! \n", name.c_str()); continue; } } std::cout << "END testing of AnalysisLib!\n"; // CUSTOMIZE return 0; }
TTErr TTSvf::setMode(const TTValue& newValue) { TTSymbol newMode = newValue; if (newMode == TT("lowpass")) { setProcessMethod(processLowpass); setCalculateMethod(calculateLowpass); } else if (newMode == TT("highpass")) { setProcessMethod(processHighpass); setCalculateMethod(calculateHighpass); } else if (newMode == TT("bandpass")) { setProcessMethod(processBandpass); setCalculateMethod(calculateBandpass); } else if (newMode == TT("notch")) { setProcessMethod(processNotch); setCalculateMethod(calculateNotch); } else if (newMode == TT("peak")) { setProcessMethod(processPeak); setCalculateMethod(calculatePeak); } else { logError("bad mode specified for TTSvf: %s", newMode.c_str()); return kTTErrInvalidValue; } mMode = newMode; return kTTErrNone; }
TTErr makeInternals_explorer(TTPtr self, TTSymbol name, t_symbol *callbackMethod, TTObject& returnedExplorer, TTBoolean deferlow) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; TTValue v, args, baton; TTObject returnValueCallback; // check the internals do not exist yet if (!x->internals->lookup(name, v)) { returnedExplorer = v[0]; JamomaDebug object_post((t_object*)x, "makeInternals_explorer : \"%s\" internal already exists", name.c_str()); return kTTErrNone; } // prepare arguments 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); args.append((TTPtr)jamoma_explorer_default_filter_bank()); returnedExplorer = TTObject(kTTSym_Explorer, args); // default registration case : store object only (see in unregister method) x->internals->append(name, returnedExplorer); JamomaDebug object_post((t_object*)x, "makes internal \"%s\" explorer", name.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 wrappedClass_anything(TTPtr self, t_symbol* s, long argc, t_atom* argv) { WrappedInstancePtr x = (WrappedInstancePtr)self; TTSymbol ttName; TTValue v_in; TTValue v_out; // err = hashtab_lookup(x->wrappedClassDefinition->pdNamesToTTNames, s, (t_object**)&ttName); ttName = x->wrappedClassDefinition->pdNamesToTTNames[s->s_name]; if (ttName.string().empty()) { pd_error((t_object*)x, "no method found for %s", s->s_name); return; } if (argc && argv) { v_in.resize(argc); for (long i=0; i<argc; i++) { if (atom_gettype(argv+i) == A_LONG) v_in[i] = (TTInt32)atom_getlong(argv+i); else if (atom_gettype(argv+i) == A_FLOAT) v_in[i] = atom_getfloat(argv+i); else if (atom_gettype(argv+i) == A_SYM) v_in[i] = TT(atom_getsym(argv+i)->s_name); else pd_error((t_object*)x, "bad type for message arg"); } } x->wrappedObject->send(ttName, v_in, v_out); // process the returned value for the dumpout outlet { long ac = v_out.size(); if (ac) { t_atom* av = (t_atom*)malloc(sizeof(t_atom) * ac); for (long i=0; i<ac; i++) { if (v_out[0].type() == kTypeSymbol) { TTSymbol ttSym; ttSym = v_out[i]; atom_setsym(av+i, gensym((char*)ttSym.c_str())); } else if (v_out[0].type() == kTypeFloat32 || v_out[0].type() == kTypeFloat64) { TTFloat64 f = 0.0; f = v_out[i]; atom_setfloat(av+i, f); } else { TTInt32 l = 0; l = v_out[i]; atom_setfloat(av+i, l); } } outlet_anything(x->dumpOut, s, ac, av); free(av); } } }
t_max_err dataspace_setDataspace(t_dataspace *self, void *attr, long argc, t_atom *argv) { TTValue v; TTSymbol s; self->attr_dataspace = atom_getsym(argv); self->dataspace->setAttributeValue(TT("dataspace"), TT(self->attr_dataspace->s_name)); self->dataspace->getAttributeValue(TT("inputUnit"), v); v.get(0, s); self->attr_dataspace_active = gensym(s.c_str()); self->dataspace->getAttributeValue(TT("outputUnit"), v); v.get(0, s); self->attr_dataspace_native = gensym(s.c_str()); return MAX_ERR_NONE; }
TTErr DemoAppEventStatusChangedCallback(const TTValue& baton, const TTValue& value) { DemoApp* demoApp = (DemoApp*)TTPtr(baton[0]); TTObject event = value[0]; TTSymbol newStatus = value[1]; TTSymbol oldStatus = value[2]; // get the name of the event TTSymbol name; event.get("name", name); // print the event status TTLogMessage("%s status : %s \n", name.c_str(), newStatus.c_str()); return kTTErrNone; }
void wrappedClass_anything(WrappedInstancePtr self, t_symbol* s, long argc, t_atom* argv) { TTValue v; TTSymbol ttName; t_max_err err; err = hashtab_lookup(self->wrappedClassDefinition->maxNamesToTTNames, s, (t_object**)&ttName); if (err) { object_post(SELF, "no method found for %s", s->s_name); return; } if (argc && argv) { TTValue v; v.resize(argc); for (long i=0; i<argc; i++) { if (atom_gettype(argv+i) == A_LONG) v[i] = (TTInt32)atom_getlong(argv+i); else if (atom_gettype(argv+i) == A_FLOAT) v[i] = atom_getfloat(argv+i); else if (atom_gettype(argv+i) == A_SYM) v[i] = TT(atom_getsym(argv+i)->s_name); else object_error(SELF, "bad type for message arg"); } self->graphObject->mKernel.send(ttName, v, v); // FIXME: TEMPORARY HACK WHILE WE TRANSITION FROM 1-ARG MESSAGES to 2-ARG MESSAGES // process the returned value for the dumpout outlet { long ac = v.size(); if (ac) { t_atom* av = (t_atom*)malloc(sizeof(t_atom) * ac); for (long i=0; i<ac; i++) { if (v[i].type() == kTypeSymbol) { TTSymbol ttSym = v[i]; atom_setsym(av+i, gensym((char*)ttSym.c_str())); } else if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64) { TTFloat64 f = v[i]; atom_setfloat(av+i, f); } else { TTInt32 l = v[i]; atom_setfloat(av+i, l); } } object_obex_dumpout(self, s, ac, av); free(av); } } } else self->graphObject->mKernel.send(ttName); }
/* Method for "anything" messages */ void MaxAudioGraphWrappedClass_anything(WrappedInstancePtr self, SymbolPtr s, AtomCount argc, AtomPtr argv) { TTValue v_in; TTValue v_out; TTSymbol ttName(s->s_name); if (argc && argv) { v_in.setSize(argc); // Typechecking - we only want ints, floats and symbols for (AtomCount i=0; i<argc; i++) { if (atom_gettype(argv+i) == A_LONG) v_in.set(i, AtomGetInt(argv+i)); else if (atom_gettype(argv+i) == A_FLOAT) v_in.set(i, atom_getfloat(argv+i)); else if (atom_gettype(argv+i) == A_SYM) v_in.set(i, TT(atom_getsym(argv+i)->s_name)); else object_error(SELF, "bad type for message arg"); } } // Now that we know that the message is OK we send it on to the wrapped class self->audioGraphObject->getUnitGenerator()->sendMessage(ttName, v_in, v_out); // process the returned value for the dumpout outlet { AtomCount ac = v_out.getSize(); if (ac) { AtomPtr av = (AtomPtr)malloc(sizeof(Atom) * ac); for (AtomCount i=0; i<ac; i++) { if (v_out.getType() == kTypeSymbol){ TTSymbol ttSym; v_out.get(i, ttSym); atom_setsym(av+i, gensym((char*)ttSym.c_str())); } else if (v_out.getType() == kTypeFloat32 || v_out.getType() == kTypeFloat64) { TTFloat64 f = 0.0; v_out.get(i, f); atom_setfloat(av+i, f); } else { TTInt32 l = 0; v_out.get(i, l); atom_setfloat(av+i, l); } } object_obex_dumpout(self, s, ac, av); free(av); } } // } // else // self->audioGraphObject->getUnitGenerator()->sendMessage(ttName); }
TTObject::TTObject(const TTSymbol aClassName) : mObjectInstance(NULL) { TTErr err = ttEnvironment->createInstance(aClassName, &mObjectInstance, TTValue()); if (err) { TTLogError("TTObject -- error %i instantiating %s\n", err, aClassName.c_str()); throw TTException("object instantiation failed"); } }
MaxErr MidiOutGetDevice(MidiOutPtr self, void* attr, AtomCount* argc, AtomPtr* argv) { TTValue v; TTSymbol s; self->graphObject->mKernel->getAttributeValue(TT("device"), v); v.get(0, s); if (!s) return MAX_ERR_GENERIC; *argc = 1; if (!(*argv)) // otherwise use memory passed in *argv = (t_atom *)sysmem_newptr(sizeof(t_atom)); atom_setsym(*argv, gensym((char*)s.c_str())); return MAX_ERR_NONE; }
void TTSCORE_EXPORT TTExpressionParseFromValue(const TTValue& toParse, TTExpression& anExpression) { // if the expression is composed by one symbol if (toParse.size() == 1 && toParse[0].type() == kTypeSymbol) { TTSymbol s = toParse[0]; anExpression = TTExpression(s.c_str()); } else { // copy to protect the value TTValue v = toParse; v.toString(); anExpression = TTExpression(TTString(v[0])); } }
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; }
t_jit_err StencilGetEdges(StencilObjectPtr self, Ptr attr, AtomCount* ac, AtomPtr* av) { TTValue v; TTSymbol s; if (*ac && *av) { ; // memory passed-in, use it } else { *av = (AtomPtr)sysmem_newptr(sizeof(Atom)); } *ac = 1; self->stencilObject->getAttributeValue(TT("edges"), v); v.get(0, s); atom_setsym(*av, gensym(s.c_str())); return JIT_ERR_NONE; }
void dataspace_getUnits(t_dataspace *self) { t_atom a[2]; TTValue v; atom_setsym(a+0, gensym("clear")); object_obex_dumpout(self, gensym("UnitMenu"), 1, a); self->dataspace->sendMessage(TT("getAvailableUnits"), v, v); for (int i=0; i < v.getSize(); i++) { TTSymbol name; v.get(i, name); atom_setsym(a+0, gensym("append")); atom_setsym(a+1, gensym(name.c_str())); object_obex_dumpout(self, gensym("UnitMenu"), 2, a); } }
void MidiOutGetDeviceNames(MidiOutPtr self) { TTValue v; TTErr err; AtomCount ac; AtomPtr ap; TTSymbol name; err = self->graphObject->mKernel->sendMessage(TT("getAvailableDeviceNames"), kTTValNONE, v); if (!err) { ac = v.getSize(); ap = new Atom[ac]; for (AtomCount i=0; i<ac; i++) { v.get(i, name); atom_setsym(ap+i, gensym((char*)name.c_str())); } object_obex_dumpout(self, gensym("getAvailableDeviceNames"), ac, ap); delete ap; } }
t_max_err wrappedClass_attrGet(TTPtr self, t_object* attr, long* argc, t_atom** argv) { t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname); TTValue v; long i; WrappedInstancePtr x = (WrappedInstancePtr)self; TTPtr rawpointer = NULL; rawpointer = x->wrappedClassDefinition->pdNamesToTTNames[attrName->s_name]; // err = hashtab_lookup(x->wrappedClassDefinition->pdNamesToTTNames, attrName, (t_object**)&rawpointer); if (!rawpointer) return -2; // MAX_ERR_INVALID_PTR TTSymbol ttAttrName(rawpointer); x->wrappedObject->get(ttAttrName, v); *argc = v.size(); if (!(*argv)) // otherwise use memory passed in *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * v.size()); for (i=0; i<v.size(); i++) { if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64) { TTFloat64 value; value = v[i]; atom_setfloat(*argv+i, value); } else if (v[i].type() == kTypeSymbol) { TTSymbol value; value = v[i]; atom_setsym(*argv+i, gensym((char*)value.c_str())); } else { // assume int TTInt32 value; value = v[i]; atom_setlong(*argv+i, value); } } return 0; }
t_max_err wrappedClass_attrGet(WrappedInstancePtr self, t_object* attr, long* argc, t_atom** argv) { t_symbol* attrName = (t_symbol*)object_method(attr, _sym_getname); TTValue v; long i; TTPtr rawpointer; t_max_err err; err = hashtab_lookup(self->wrappedClassDefinition->maxNamesToTTNames, attrName, (t_object**)&rawpointer); if (err) return err; TTSymbol ttAttrName(rawpointer); self->graphObject->mKernel.get(ttAttrName, v); *argc = v.size(); if (!(*argv)) // otherwise use memory passed in *argv = (t_atom *)sysmem_newptr(sizeof(t_atom) * v.size()); for (i=0; i<v.size(); i++) { if (v[i].type() == kTypeFloat32 || v[i].type() == kTypeFloat64) { TTFloat64 value = v[i]; atom_setfloat(*argv+i, value); } else if (v[i].type() == kTypeSymbol) { TTSymbol value = v[i]; atom_setsym(*argv+i, gensym((char*)value.c_str())); } else { // assume int TTInt32 value = v[i]; atom_setlong(*argv+i, value); } } return MAX_ERR_NONE; }
TTErr TTObjectBase::registerMessage(const TTSymbol name, TTMethod method, TTMessageFlags flags) { TTMessagePtr newMessage = new TTMessage(name, method, flags); if (ttEnvironment->mDebugMessaging) logMessage("Registering Message '%s' with flags = %ld, message count for this object is now %ld\n", name.c_str(), kTTMessageDefaultFlags, messages->getSize()); messages->append(name, TTPtr(newMessage)); return kTTErrNone; }
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(); } }
TTErr wrapAsMaxAudioGraph(TTSymbol ttClassName, char* maxClassName, MaxAudioGraphWrappedClassPtr* c, MaxAudioGraphWrappedClassOptionsPtr options) { TTObject* o = NULL; TTValue v; TTUInt16 numChannels = 1; MaxAudioGraphWrappedClassPtr wrappedMaxClass = NULL; TTSymbol name; TTCString nameCString = NULL; SymbolPtr nameMaxSymbol = NULL; TTUInt32 nameSize = 0; common_symbols_init(); TTAudioGraphInit(); if (!wrappedMaxClasses) wrappedMaxClasses = hashtab_new(0); wrappedMaxClass = new MaxAudioGraphWrappedClass; wrappedMaxClass->maxClassName = gensym(maxClassName); wrappedMaxClass->maxClass = class_new( maxClassName, (method)MaxAudioGraphWrappedClass_new, (method)MaxAudioGraphWrappedClass_free, sizeof(WrappedInstance), (method)0L, A_GIMME, 0); wrappedMaxClass->ttClassName = ttClassName; wrappedMaxClass->validityCheck = NULL; wrappedMaxClass->validityCheckArgument = NULL; wrappedMaxClass->options = options; // Create a temporary instance of the class so that we can query it. TTObjectInstantiate(ttClassName, &o, numChannels); o->getMessageNames(v); for (TTUInt16 i=0; i<v.getSize(); i++) { v.get(i, name); nameSize = strlen(name.c_str()); nameCString = new char[nameSize+1]; strncpy_zero(nameCString, name.c_str(), nameSize+1); nameMaxSymbol = gensym(nameCString); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphWrappedClass_anything, nameCString, A_GIMME, 0); delete nameCString; nameCString = NULL; } o->getAttributeNames(v); for (TTUInt16 i=0; i<v.getSize(); i++) { TTAttributePtr attr = NULL; SymbolPtr maxType = _sym_long; TTValue isGenerator = kTTBoolNo; v.get(i, name); nameSize = strlen(name.c_str()); nameCString = new char[nameSize+1]; strncpy_zero(nameCString, name.c_str(), nameSize+1); nameMaxSymbol = gensym(nameCString); if (name == TT("maxNumChannels")) continue; // don't expose these attributes to Max users if (name == TT("bypass")) { if (wrappedMaxClass->options && !wrappedMaxClass->options->lookup(TT("generator"), isGenerator)) continue; // generators don't have inputs, and so don't really provide a bypass } o->findAttribute(name, &attr); if (attr->type == kTypeFloat32) maxType = _sym_float32; else if (attr->type == kTypeFloat64) maxType = _sym_float64; else if (attr->type == kTypeSymbol || attr->type == kTypeString) maxType = _sym_symbol; class_addattr(wrappedMaxClass->maxClass, attr_offset_new(nameCString, maxType, 0, (method)MaxAudioGraphWrappedClass_attrGet, (method)MaxAudioGraphWrappedClass_attrSet, 0)); // Add display styles for the Max 5 inspector if (attr->type == kTypeBoolean) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)name.c_str(), 0, (char*)"onoff"); if (name == TT("fontFace")) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)"fontFace", 0, (char*)"font"); delete nameCString; nameCString = NULL; } TTObjectRelease(&o); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphReset, "audio.reset", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphSetup, "audio.setup", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphConnect, "audio.connect", A_OBJ, A_LONG, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphDrop, "audio.drop", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphObject, "audio.object", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphConnect, "graph.connect", A_OBJ, A_LONG, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphDrop, "graph.drop", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphObject, "graph.object", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)object_obex_dumpout, "dumpout", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxAudioGraphWrappedClass_assist, "assist", A_CANT, 0L); class_addmethod(wrappedMaxClass->maxClass, (method)stdinletinfo, "inletinfo", A_CANT, 0); if (wrappedMaxClass->options) { TTValue userCanSetNumChannels = kTTBoolNo; TTErr err = wrappedMaxClass->options->lookup(TT("userCanSetNumChannels"), userCanSetNumChannels); if (!err && userCanSetNumChannels == kTTBoolYes) class_addattr(wrappedMaxClass->maxClass, attr_offset_new("numChannels", _sym_long, 0, (method)MaxAudioGraphWrappedClass_attrGetNumChannels, (method)MaxAudioGraphWrappedClass_attrSetNumChannels, 0)); } class_register(_sym_box, wrappedMaxClass->maxClass); if (c) *c = wrappedMaxClass; hashtab_store(wrappedMaxClasses, wrappedMaxClass->maxClassName, ObjectPtr(wrappedMaxClass)); 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_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 wrapTTModularClassAsMaxClass(TTSymbol& ttblueClassName, const char* maxClassName, WrappedClassPtr* c, ModularSpec* specificities) { TTObject o; TTValue v, args; WrappedClass* wrappedMaxClass = NULL; TTSymbol TTName; t_symbol *MaxName = NULL; TTUInt16 i; jamoma_init(); common_symbols_init(); if (!wrappedMaxClasses) wrappedMaxClasses = hashtab_new(0); wrappedMaxClass = new WrappedClass; wrappedMaxClass->maxClassName = gensym(maxClassName); wrappedMaxClass->maxClass = class_new( maxClassName, (method)wrappedModularClass_new, (method)wrappedModularClass_free, sizeof(WrappedModularInstance), (method)0L, A_GIMME, 0); wrappedMaxClass->ttblueClassName = ttblueClassName; wrappedMaxClass->validityCheck = NULL; wrappedMaxClass->validityCheckArgument = NULL; wrappedMaxClass->options = NULL; wrappedMaxClass->maxNamesToTTNames = hashtab_new(0); wrappedMaxClass->specificities = specificities; #ifdef AUDIO_EXTERNAL // Setup our class to work with MSP class_dspinit(wrappedMaxClass->maxClass); #endif // Create a temporary instance of the class so that we can query it. o = TTObject(ttblueClassName); // Register Messages as Max method o.messages(v); for (i = 0; i < v.size(); i++) { TTName = v[i]; if (TTName == TTSymbol("test") || TTName == TTSymbol("getProcessingBenchmark") || TTName == TTSymbol("resetBenchmarking")) continue; else if ((MaxName = jamoma_TTName_To_MaxName(TTName))) { hashtab_store(wrappedMaxClass->maxNamesToTTNames, MaxName, (t_object*)(TTName.rawpointer())); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_anything, MaxName->s_name, A_GIMME, 0); } } // Register Attributes as Max attr o.attributes(v); for (i = 0; i < v.size(); i++) { TTAttributePtr attr = NULL; t_symbol *maxType = _sym_atom; TTName = v[i]; #ifdef AUDIO_EXTERNAL // the enable word is already used by a message declared in the dsp_init method if (TTName == TTSymbol("enable")) continue; #endif // we want to hide service attribute for Max external if (TTName == TTSymbol("service")) continue; if ((MaxName = jamoma_TTName_To_MaxName(TTName))) { if (TTName == kTTSym_bypass && wrappedMaxClass->maxClassName != gensym("j.in") && wrappedMaxClass->maxClassName != gensym("j.in~")) continue; o.instance()->findAttribute(TTName, &attr); if (attr->type == kTypeFloat32) maxType = _sym_float32; else if (attr->type == kTypeFloat64) maxType = _sym_float64; else if (attr->type == kTypeSymbol || attr->type == kTypeString) maxType = _sym_symbol; else if (attr->type == kTypeLocalValue) maxType = _sym_atom; hashtab_store(wrappedMaxClass->maxNamesToTTNames, MaxName, (t_object*)(TTName.rawpointer())); class_addattr(wrappedMaxClass->maxClass, attr_offset_new(MaxName->s_name, maxType, 0, (method)wrappedModularClass_attrGet, (method)wrappedModularClass_attrSet, 0)); // Add display styles for the Max 5 inspector if (attr->type == kTypeBoolean) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)TTName.c_str(), 0, "onoff"); if (TTName == TTSymbol("fontFace")) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, "fontFace", 0, "font"); } } // standalone support: class_addmethod(wrappedMaxClass->maxClass, (method)jamoma_fileusage, "fileusage", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)stdinletinfo, "inletinfo", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_notify, "notify", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_shareContextNode, "share_context_node", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_anything, "anything", A_GIMME, 0); // Register specific methods and do specific things if (specificities) { if (specificities->_wrap) specificities->_wrap(wrappedMaxClass); } class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_dump, "dump", A_GIMME, 0); #ifdef ARRAY_EXTERNAL class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_ArraySelect, "array/select", A_GIMME,0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedModularClass_ArrayResize, "array/resize", A_LONG,0); CLASS_ATTR_SYM(wrappedMaxClass->maxClass, "format", 0, WrappedModularInstance, arrayAttrFormat); CLASS_ATTR_ACCESSORS(wrappedMaxClass->maxClass, "format", wrappedModularClass_FormatGet, wrappedModularClass_FormatSet); CLASS_ATTR_ENUM(wrappedMaxClass->maxClass, "format", 0, "single array"); #endif class_register(_sym_box, wrappedMaxClass->maxClass); if (c) *c = wrappedMaxClass; hashtab_store(wrappedMaxClasses, wrappedMaxClass->maxClassName, (t_object*)(wrappedMaxClass)); return kTTErrNone; }
TTErr wrapTTClassAsPdClass(TTSymbol ttblueClassName, const char* pdClassName, WrappedClassPtr* c, WrappedClassOptionsPtr options) { TTObject o(ttblueClassName, 1); // Create a temporary instance of the class so that we can query it. TTValue v; WrappedClass* wrappedPdClass = NULL; TTSymbol name; TTCString nameCString = NULL; t_symbol* namePdSymbol = NULL; TTUInt32 nameSize = 0; TTDSPInit(); wrappedPdClass = new WrappedClass; wrappedPdClass->pdClassName = gensym((char*)pdClassName); wrappedPdClass->pdClass = eclass_new( (char*)pdClassName, (method)wrappedClass_new, (method)wrappedClass_free, sizeof(WrappedInstance), CLASS_NOINLET, A_GIMME, 0); wrappedPdClass->ttblueClassName = ttblueClassName; wrappedPdClass->validityCheck = NULL; wrappedPdClass->validityCheckArgument = NULL; wrappedPdClass->options = options; if (!o.valid()) { error("Jamoma ClassWrapper failed to load %s", ttblueClassName.c_str()); return kTTErrAllocFailed; } o.messages(v); for (TTUInt16 i=0; i<v.size(); i++) { name = v[i]; //nameSize = name->getString().length(); // TODO -- this crash on Windows... nameSize = strlen(name.c_str()); nameCString = new char[nameSize+1]; strncpy(nameCString, name.c_str(), nameSize+1); namePdSymbol = gensym(nameCString); wrappedPdClass->pdNamesToTTNames[namePdSymbol->s_name] = (t_object*)name.rawpointer(); eclass_addmethod((t_eclass*)wrappedPdClass->pdClass, (method)wrappedClass_anything, nameCString, A_GIMME, 0); delete[] nameCString; nameCString = NULL; } o.attributes(v); for (TTUInt16 i=0; i<v.size(); i++) { TTAttributePtr attr = NULL; name = v[i]; //nameSize = name->getString().length(); // TODO -- this crash on Windows... nameSize = strlen(name.c_str()); nameCString = new char[nameSize+1]; strncpy(nameCString, name.c_str(), nameSize+1); namePdSymbol = gensym(nameCString); if (name == TT("maxNumChannels")) continue; // don't expose these attributes to Pd users if (name == TT("bypass")) { if (wrappedPdClass->options && !wrappedPdClass->options->lookup(TT("generator"), v)) continue; // generators don't have inputs, and so don't really provide a bypass } o.instance()->findAttribute(name, &attr); wrappedPdClass->pdNamesToTTNames[namePdSymbol->s_name] = (t_object*)name.rawpointer(); if (attr->type == kTypeFloat32) CLASS_ATTR_FLOAT(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr); else if (attr->type == kTypeFloat64) CLASS_ATTR_DOUBLE(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr); else if (attr->type == kTypeSymbol || attr->type == kTypeString) CLASS_ATTR_SYMBOL(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr); else CLASS_ATTR_LONG(wrappedPdClass->pdClass,nameCString,0,t_eclass,c_attr); //class_addattr(wrappedPdClass->pdClass, attr_offset_new(nameCString, pdType, 0, (method)wrappedClass_attrGet, (method)wrappedClass_attrSet, 0)); /* // Add display styles for the Max 5 inspector if (attr->type == kTypeBoolean) CLASS_ATTR_STYLE(wrappedPdClass->pdClass, (char*)name.c_str(), 0, (char*)"onoff"); if (name == TT("fontFace")) CLASS_ATTR_STYLE(wrappedPdClass->pdClass, (char*)"fontFace", 0, (char*)"font"); */ delete[] nameCString; nameCString = NULL; } eclass_addmethod(wrappedPdClass->pdClass, (method)wrappedClass_dsp64, "dsp64", A_CANT, 0L); eclass_addmethod(wrappedPdClass->pdClass, (method)object_obex_dumpout, "dumpout", A_CANT, 0); eclass_addmethod(wrappedPdClass->pdClass, (method)wrappedClass_assist, "assist", A_CANT, 0L); // eclass_addmethod(wrappedPdClass->pdClass, (method)stdinletinfo, "inletinfo", A_CANT, 0); eclass_dspinit(wrappedPdClass->pdClass); eclass_register(CLASS_BOX, wrappedPdClass->pdClass); if (c) *c = wrappedPdClass; wrappedPdClasses[wrappedPdClass->pdClassName->s_name] = (t_object*)wrappedPdClass; return kTTErrNone; }