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 TTData::rampSetup() { TTValue args; // 1. destroy the old ramp object if (mRamper.valid()) { mRamper = TTObject(); externalRampTime = 0; } // 2. create the new ramp object // For some types ramping doesn't make sense, so they will be set to none if (mType == kTTSym_none || mType == kTTSym_string || mType == kTTSym_generic) mRampDrive = kTTSym_none; else { // don't create ramper for external ramp drive if (mRampDrive == kTTSym_external || mRampDrive == kTTSym_none) return kTTErrNone; args.append((TTPtr)&TTDataRampCallback); args.append((TTPtr)this); // we have to store this as a pointer mRamper = TTObject("Ramp", args); mRamper.set("drive", mRampDrive); } #ifndef TT_NO_DSP // 3. reset the ramp function return setRampFunction(mRampFunction); #else return kTTErrNone; #endif }
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 init_free(t_init *x) { // release the receiver x->initReceiver.set(kTTSym_address, kTTAdrsEmpty); x->initReceiver = TTObject(); // release the subscriber x->subscriberObject = TTObject(); }
TTInputAudio :: TTInputAudio (const TTValue& arguments) : TTInput(arguments) { mTags = TTSymbol("audio"); mSignalIn = TTObject(kTTSym_audiosignal, 1); mSignalOut = TTObject(kTTSym_audiosignal, 1); mSignalZero = TTObject(kTTSym_audiosignal, 1); }
void DemoApp::SetupScore() { TTValue args, out; TTObject xmlHandler("XmlHandler"); TTLogMessage("\n*** Initialisation of Score environnement ***\n"); ///////////////////////////////////////////////////////////////////// // Init the Score library (passing the folder path where all the dylibs are) TTScoreInit("/usr/local/jamoma"); TTLogMessage("\n*** Reading of an interactive scenario file ***\n"); ///////////////////////////////////////////////////////////////////// // Create an empty Scenario mScenario = TTObject("Scenario"); // Read DemoScenario1.score file to fill mScenario xmlHandler.set("object", mScenario); xmlHandler.send("Read", "../DemoScenario.score", out); TTLogMessage("\n*** Prepare scenario observation ***\n"); ///////////////////////////////////////////////////////////////////// // Create a callback for the "EventStatusChanged" notification sent by each event mEventStatusChangedCallback = TTObject("callback"); mEventStatusChangedCallback.set("baton", TTPtr(this)); mEventStatusChangedCallback.set("function", TTPtr(&DemoAppEventStatusChangedCallback)); mEventStatusChangedCallback.set("notification", TTSymbol("EventStatusChanged")); // Get all events of the scenario and attach a callback to them TTValue timeEvents; mScenario.get("timeEvents", timeEvents); for (TTElementIter it = timeEvents.begin() ; it != timeEvents.end() ; it++) { TTObject event = TTElement(*it); event.registerObserverForNotifications(mEventStatusChangedCallback); } TTLogMessage("\n*** Start scenario execution ***\n"); ///////////////////////////////////////////////////////////////////// // Set the execution speed of the scenario mScenario.set("speed", 2.); // Start the scenario mScenario.send("Start"); // Poll Scenario information mPollingThread = new TTThread(TTThreadCallbackType(DemoAppScenarioPollingThread), this); }
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 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; }
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; }
TTErr MinuitSenderManager::send(TTSymbol applicationName, TTSymbol ip, TTUInt16 port, const TTValue& message) { TTValue last; // if nothing is being sent to an application if (mSending.findEquals(applicationName, last)) { // lock application mSending.append(applicationName); TTObject anOscSender; TTErr err = mSenders.lookup(applicationName, last); if (err) { anOscSender = TTObject("osc.send"); anOscSender.set("address", ip); anOscSender.set("port", port); TTValue cache(anOscSender, ip, port); mSenders.append(applicationName, cache); } else { anOscSender = last[0]; TTSymbol lastIp = last[1]; TTUInt16 lastPort = last[2]; if (lastIp == ip && lastPort == port) ; else { anOscSender.set("address", ip); anOscSender.set("port", port); TTValue cache(anOscSender, ip, port); mSenders.remove(applicationName); mSenders.append(applicationName, cache); } } err = anOscSender.send("send", message); // unlock application mSending.remove(applicationName); return kTTErrNone; } return kTTErrGeneric; }
void data_array_create(TTPtr self, TTObject& returnedData, TTSymbol service, TTUInt32 index) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; t_symbol *iAdrs; TTValue baton; returnedData = TTObject(kTTSym_Data, service); jamoma_edit_numeric_instance(x->arrayFormatInteger, &iAdrs, index); baton = TTValue(self, index, TTSymbol(iAdrs->s_name)); returnedData.set(kTTSym_baton, baton); returnedData.set(kTTSym_function, TTPtr(&data_array_return_value)); }
TTErr TTData::setDataspace(const TTValue& value) { TTErr err; TTValue v; TTValue n = value; // use new value to protect the attribute mDataspace = value; if (!mDataspaceConverter.valid()) { mDataspaceConverter = TTObject("dataspace"); mDataspaceInverseConverter = TTObject("dataspace"); } err = mDataspaceConverter.set("dataspace", mDataspace); mDataspaceInverseConverter.set("dataspace", mDataspace); if (err) { mDataspace = kTTSym_none; return err; } // If there is already a unit defined, then we try to use that err = mDataspaceConverter.set("outputUnit", mDataspaceUnit); mDataspaceInverseConverter.set("inputUnit", mDataspaceUnit); // Otherwise we use the default (neutral) unit. if (err) { mDataspaceConverter.get("outputUnit", v); mDataspaceUnit = v[0]; mDataspaceConverter.set("outputUnit", mDataspaceUnit); mDataspaceInverseConverter.set("inputUnit", mDataspaceUnit); } this->notifyObservers(kTTSym_dataspace, n); return kTTErrNone; }
void WrappedCueManagerClass_new(TTPtr self, long argc, t_atom *argv) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; t_symbol* name; TTValue v, args; TTObject aTextHandler; long attrstart = attr_args_offset(argc, argv); // support normal arguments // create the cue manager jamoma_cueManager_create((t_object*)x, x->wrappedObject); // read first argument to know if the cue binds a namespace if (attrstart && argv) { if (atom_gettype(argv) == A_SYM) { name = atom_getsym(argv); x->wrappedObject.set(kTTSym_namespace, TTSymbol(name->s_name)); } else object_error((t_object*)x, "argument not expected"); } // Make two outlets x->outlets = (TTHandle)sysmem_newptr(sizeof(TTPtr) * 1); x->outlets[line_out] = outlet_new(x, NULL); // anything outlet to output data // Prepare Internals hash to store TextHandler object x->internals = new TTHash(); // create internal TTTextHandler aTextHandler = TTObject(kTTSym_TextHandler); x->internals->append(kTTSym_TextHandler, aTextHandler); // Prepare extra data x->extra = (t_extra*)malloc(sizeof(t_extra)); EXTRA->toEdit = new TTObject(); *EXTRA->toEdit = x->wrappedObject; EXTRA->cueName = kTTSymEmpty; EXTRA->text = NULL; EXTRA->textEditor = NULL; // handle attribute args attr_args_process(x, argc, argv); }
t_max_err wrappedModularClass_notify(TTPtr self, t_symbol *s, t_symbol *msg, void *sender, void *data) { WrappedModularInstancePtr x = (WrappedModularInstancePtr)self; ModularSpec* spec = (ModularSpec*)x->wrappedClassDefinition->specificities; TTValue v; TTAddress contextAddress; #ifndef ARRAY_EXTERNAL t_object * context; if (x->subscriberObject.valid()) { x->subscriberObject.get("context", v); context = (t_object*)((TTPtr)v[0]); // if the patcher is deleted if (sender == context) { if (msg == _sym_free) { // delete the context node if it exists x->subscriberObject.get("contextAddress", v); contextAddress = v[0]; MaxApplication.send("ObjectUnregister", contextAddress); // delete x->subscriberObject = TTObject(); // no more notification object_detach_byptr((t_object*)x, context); } } } #endif if (spec->_notify) spec->_notify(self, s, msg, sender, data); return MAX_ERR_NONE; }
addMessageWithArguments(PatternDetach); // needed to be notified by events addMessageWithArguments(EventDateChanged); addMessageProperty(EventDateChanged, hidden, YES); // needed to be notified by scheduler speed change addMessageWithArguments(SchedulerSpeedChanged); addMessageProperty(SchedulerSpeedChanged, hidden, YES); TTObject thisObject(this); TTValue args; // create pattern start event args = TTValue(0, thisObject); mPatternStartEvent = TTObject(kTTSym_TimeEvent, args); mPatternStartEvent.set("name", TTSymbol("patternStart")); mPatternStartEvent.set("container", thisObject); // create pattern end event args = TTValue(1000, thisObject); mPatternEndEvent = TTObject(kTTSym_TimeEvent, args); mPatternEndEvent.set("name", TTSymbol("patternEnd")); mPatternEndEvent.set("container", thisObject); // create pattern condition args = TTValue(thisObject); mPatternCondition = TTObject("TimeCondition", args); mPatternCondition.set("name", TTSymbol("patternCondition")); mPatternCondition.set("container", thisObject);
void DemoApp::SetupModular() { TTValue args, v, out, none; TTAddress address; TTErr err; TTLogMessage("\n*** Initialisation of Modular environnement ***\n"); ///////////////////////////////////////////////////////////////////// // Init the Modular library (passing the folder path where all the dylibs are) TTModularInit("/usr/local/jamoma"); // Create an application manager mApplicationManager = TTObject("ApplicationManager"); TTLogMessage("\n*** Creation of mApplicationDemo application ***\n"); ///////////////////////////////////////////////////////////////////// // Create a local application called "demo" and get it back err = mApplicationManager.send("ApplicationInstantiateLocal", "demo", out); if (err) { TTLogError("Error : can't create demo application \n"); return; } else mApplicationDemo = out[0]; TTLogMessage("\n*** Creation of mApplicationDemo datas ***\n"); ///////////////////////////////////////////////////////////////////// // Create a parameter data and set its callback function and baton and some attributes mDataDemoParameter = TTObject("Data", "parameter"); // Setup the callback mechanism to get the value back args = TTValue(TTPtr(this), mDataDemoParameter); mDataDemoParameter.set("baton", args); mDataDemoParameter.set("function", TTPtr(&DemoAppDataReturnValueCallback)); // Setup the data attributes depending of its use inside the application mDataDemoParameter.set("type", "decimal"); mDataDemoParameter.set("rangeBounds", TTValue(0., 1.)); mDataDemoParameter.set("rangeClipmode", "low"); mDataDemoParameter.set("description", "any information relative to the state of the application"); // Register the parameter data into mApplicationDemo at an address args = TTValue("/myParameter", mDataDemoParameter); mApplicationDemo.send("ObjectRegister", args, out); // Create a message data and set its callback function and baton and some attributes mDataDemoMessage = TTObject("Data", "message"); // Setup the callback mechanism to get the value back args = TTValue(TTPtr(this), mDataDemoMessage); mDataDemoMessage.set("baton", args); mDataDemoMessage.set("function", TTPtr(&DemoAppDataReturnValueCallback)); // Setup the data attributes depending of its use inside the application mDataDemoMessage.set("type", "string"); mDataDemoMessage.set("description", "any information to provide to the application"); // Register the message data into mApplicationDemo at an address args = TTValue("/myMessage", mDataDemoMessage); mApplicationDemo.send("ObjectRegister", args, out); // Create a return data and set its callback function and baton and some attributes mDataDemoReturn = TTObject("Data", "return"); // Setup the callback mechanism to get the value back args = TTValue(TTPtr(this), mDataDemoReturn); mDataDemoReturn.set("baton", args); mDataDemoReturn.set("function", TTPtr(&DemoAppDataReturnValueCallback)); // Setup the data attributes depending of its use inside the application mDataDemoReturn.set("type", "integer"); mDataDemoReturn.set("defaultValue", 0); mDataDemoReturn.set("description", "any information the application returns back"); // Register the return data into mApplicationDemo at an address args = TTValue("/myReturn", mDataDemoReturn); mApplicationDemo.send("ObjectRegister", args, out); // Initialise the application and all datas inside (using defaultValue attribute) mApplicationDemo.send("Init"); }
void jamoma_init(void) { short outvol = 0; t_fourcc outtype, filetype = 'TEXT'; char name[MAX_PATH_CHARS], fullname[MAX_PATH_CHARS]; if (!initialized) { t_object *max = SymbolGen("max")->s_thing; TTString JamomaConfigurationFilePath; t_atom a[4]; TTValue v, out; TTErr err; if (maxversion() < 1798) { error("Jamoma %s | build %s can't run under Max version ealier than 7.0.6", JAMOMA_MAX_VERSION, JAMOMA_MAX_REV); return; } // Initialize the Modular library TTModularInit(); #ifdef TTSCORE_IMPORT // Initialize the Score framework TTScoreInit(); #endif // Prepare a symbol for Max application kTTSym_Max = TTSymbol("Max"); // Create an application manager MaxApplicationManager = TTObject("ApplicationManager"); // Create a local application called "Max" and get it back err = MaxApplicationManager.send("ApplicationInstantiateLocal", kTTSym_Max, out); if (err) { TTLogError("Error : can't create Jamoma application \n"); return; } else MaxApplication = out[0]; // check if the JamomaConfiguration.xml file exists strncpy_zero(name, "JamomaConfiguration.xml", MAX_PATH_CHARS); if (locatefile_extended(name, &outvol, &outtype, &filetype, 1)) return error("Jamoma not loaded : can't find %s", name); path_topathname(outvol, name, fullname); // MaxApplication have to read JamomaConfiguration.xml TTObject anXmlHandler(kTTSym_XmlHandler); anXmlHandler.set(kTTSym_object, MaxApplication); std::string path = fullname; #if ( __APPLE__ ) // remove drive name prefix size_t pos = path.find(":/"); path = path.substr(pos+1); v = TTSymbol(path); #else v = TTSymbol(fullname); #endif anXmlHandler.send(kTTSym_Read, v, out); // Initialize common symbols common_symbols_init(); jamomaSymbolsInit(); // Initialize common regex ttRegexForJmod = new TTRegex("(jmod.)"); ttRegexForJcom = new TTRegex("(j\\.)"); ttRegexForModel = new TTRegex("(.model)"); ttRegexForModule = new TTRegex("(.module)"); ttRegexForView = new TTRegex("(.view)"); ttRegexForMaxpat = new TTRegex("(.maxpat)"); ttRegexForMaxhelp = new TTRegex("(.maxhelp)"); ttRegexForBracket = new TTRegex("\\[(\\d|\\d\\d|\\d\\d\\d)\\]"); // parse until 999 ModelPatcherFormat = new TTString("%s.model.maxpat"); ModelPresetFormat = new TTString("%s.model.presets.txt"); ViewPresetFormat = new TTString("%s.view.presets.txt"); HelpPatcherFormat = new TTString("%s.model"); RefpageFormat = new TTString("%s.model"); DocumentationFormat = new TTString("%s.model.html"); // Create Required Global Instances hash_modules = (t_hashtab*)hashtab_new(0); // TODO: Use quittask_install() to set up a destructor for this to free it before Max exits // Add Jamoma Key Commands // J -- Jamoma: a new object box with "j." in it atom_setsym(a+0, SymbolGen("k")); atom_setsym(a+1, SymbolGen("patcher")); atom_setsym(a+2, SymbolGen("inserttextobj")); atom_setsym(a+3, SymbolGen("j.")); object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL); // // M -- Module: a new object box with ".model" in it // atom_setsym(a+0, SymbolGen("M")); // atom_setsym(a+1, SymbolGen("patcher")); // atom_setsym(a+2, SymbolGen("inserttextobj")); // atom_setsym(a+3, SymbolGen(".model")); // object_method_typed(max, SymbolGen("definecommand"), 4, a, NULL); // // // B -- BPatcher: a new module in a bpatcher // object_method_parse(max, SymbolGen("definecommand"), (char*)"B patcher inserttextobj \"bpatcher @name .module @args myModule\"", NULL); // // D -- Demo: a new module in a bpatcher, but with the args reverse which is handy for super-fast demos when you don't care about the OSC name // object_method_parse(max, SymbolGen("definecommand"), (char*)"D patcher inserttextobj \"bpatcher @name .module\"", NULL); // // X -- Continuous Mapper module // object_method_parse(max, SymbolGen("definecommand"), (char*)"X patcher insertobj bpatcher @name mapper.module.maxpat @args mapper", NULL); // now the jamoma object { t_symbol *jamomaSymbol = SymbolGen("jamoma"); jamoma_object_initclass(); jamomaSymbol->s_thing = jamoma_object_new(); } post("Jamoma %s | build %s", JAMOMA_MAX_VERSION, JAMOMA_MAX_REV ); initialized = true; } }
// Create void* allpassmod_new(t_symbol* s, long argc, t_atom* argv) { t_allpassmod* x = (t_allpassmod*)object_alloc(s_allpassmod_class); long attrstart = attr_args_offset(argc, argv); // support normal arguments TTString name = "/"; TTPtr context = TTPtr(x); TTValue none; object_obex_lookup(x, gensym("#P"), (t_object**)&context); if (attrstart) { if (atom_getsym(argv)->s_name[0] == '/') name += atom_getsym(argv)->s_name + 1; else name += atom_getsym(argv)->s_name; } else name += s->s_name; x->name = TTAddress(name); // need to cache so we can free // 1. Create the DSP objects x->allpass = TTAudioObject("allpass.1", 2); x->signalOut = TTObject(kTTSym_audiosignal, 2); x->signalIn = TTObject(kTTSym_audiosignal, 2); // 2. Create the "model" container { TTValue container_args; // TODO: (optional) pass address callback and value callback (these are both for the activity return mechanism) x->model = TTObject(kTTSym_Container, container_args); x->model.set(kTTSym_tags, kTTSym_model); TTValue registration_args(x->name, x->model, context); MaxApplication.send("ObjectRegister", registration_args, none); x->model.set("address", x->name); } // 3. Create the "clear" message { x->message_clear = TTObject(kTTSym_Data, kTTSym_message); x->message_clear.set(kTTSym_baton, TTPtr(x)); x->message_clear.set(kTTSym_function, TTPtr(allpassmod_parameter_clear_callback)); x->message_clear.set(kTTSym_type, kTTSym_none); x->message_clear.set(kTTSym_description, TTSymbol("Clear the filter history")); TTAddress address = x->name.appendAddress("/clear"); TTValue registration_args(address, x->message_clear, context); MaxApplication.send("ObjectRegister", registration_args, none); } // 4. Create the "gain" parameter (linear) { x->parameter_coefficient = TTObject(kTTSym_Data, kTTSym_parameter); x->parameter_coefficient.set(kTTSym_baton, TTPtr(x)); x->parameter_coefficient.set(kTTSym_function, TTPtr(allpassmod_parameter_coefficient_callback)); x->parameter_coefficient.set(kTTSym_type, kTTSym_decimal); x->parameter_coefficient.set(kTTSym_valueDefault, 0.7); x->parameter_coefficient.set(kTTSym_description, TTSymbol("Gain coefficient")); TTAddress address = x->name.appendAddress("/coefficient"); TTValue registration_args(address, x->parameter_coefficient, context); MaxApplication.send("ObjectRegister", registration_args, none); } // 5. Create the "delay" parameter (milliseconds) { x->parameter_delay = TTObject(kTTSym_Data, kTTSym_parameter); x->parameter_delay.set(kTTSym_baton, TTPtr(x)); x->parameter_delay.set(kTTSym_function, TTPtr(allpassmod_parameter_delay_callback)); x->parameter_delay.set(kTTSym_type, kTTSym_decimal); x->parameter_delay.set(kTTSym_valueDefault, 0.2); x->parameter_delay.set(kTTSym_description, TTSymbol("Delay time")); TTAddress address = x->name.appendAddress("/delay"); TTValue registration_args(address, x->parameter_delay, context); MaxApplication.send("ObjectRegister", registration_args, none); } // 6. Create the Input access points { // left input { x->in_left = TTObject("Input.audio"); TTAddress address = x->name.appendAddress("/in.left"); TTValue registration_args(address, x->in_left, context); MaxApplication.send("ObjectRegister", registration_args, none); } // right input { x->in_right = TTObject("Input.audio"); TTAddress address = x->name.appendAddress("/in.right"); TTValue registration_args(address, x->in_right, context); MaxApplication.send("ObjectRegister", registration_args, none); } } // 7. Create the Output access points { // left output { x->out_left = TTObject("Output.audio"); TTAddress address = x->name.appendAddress("/out.left"); TTValue registration_args(address, x->out_left, context); MaxApplication.send("ObjectRegister", registration_args, none); } // right output { x->out_right = TTObject("Output.audio"); TTAddress address = x->name.appendAddress("/out.right"); TTValue registration_args(address, x->out_right, context); MaxApplication.send("ObjectRegister", registration_args, none); } } // 8. Add the preset functions { x->preset = TTObject(kTTSym_PresetManager); x->preset.set("address", x->name); TTAddress address = x->name.appendAddress("/preset"); TTValue registration_args(address, x->preset, context); MaxApplication.send("ObjectRegister", registration_args, none); // load a preset file and recall the first preset { TTValue out; TTObject xmlHandler("XmlHandler"); // set the object attr of the above object to be the PresetManager xmlHandler.set("object", x->preset); // TODO : get the filepath as an argument TTSymbol path; xmlHandler.send("Read", path, out); // recall the first preset x->preset.send("Recall", 1, none); } } // 9. Initialize the module (set default values, etc) x->model.send("Init"); // 10. Do some final Max-specific stuff dsp_setup((t_pxobject*)x, 2); x->obj.z_misc = Z_NO_INPLACE; for (int i=0; i < 2; i++) outlet_new((t_pxobject*)x, "signal"); attr_args_process(x, argc, argv); return x; }
addMessageWithArguments(Recall); addMessageWithArguments(Output); // needed to be handled by a TTXmlHandler addMessageWithArguments(WriteAsXml); addMessageProperty(WriteAsXml, hidden, YES); addMessageWithArguments(ReadFromXml); addMessageProperty(ReadFromXml, hidden, YES); // needed to be handled by a TTTextHandler addMessageWithArguments(WriteAsText); addMessageProperty(WriteAsText, hidden, YES); addMessageWithArguments(ReadFromText); addMessageProperty(ReadFromText, hidden, YES); mScript = TTObject(kTTSym_Script, arguments); } TTPreset::~TTPreset() { ; } TTErr TTPreset::setAddress(const TTValue& value) { Clear(); mAddress = value[0]; mDirectory = accessApplicationDirectoryFrom(mAddress); if (mDirectory) {
addMessageWithArguments(EventConditionChanged); addMessageProperty(EventConditionChanged, hidden, YES); addMessageWithArguments(EventStatusChanged); addMessageProperty(EventStatusChanged, hidden, YES); // needed to be notified by the clock addMessageWithArguments(ClockRunningChanged); addMessageProperty(ClockRunningChanged, hidden, YES); // Creation of a clock based on the System clock plugin // Prepare callback argument to be notified of : // - the position TTValue args = TTValue((TTPtr)&TTTimeProcessClockCallback); args.append((TTPtr)this); // we have to store this as a pointer for Clock mClock = TTObject("system", args); if (!mClock.valid()) { logError("TimeProcess failed to load the System Clock"); } else { // observe the clock TTObject thisObject(this); mClock.registerObserverForNotifications(thisObject); } // generate a random name mName = mName.random();
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 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; }
addMessageWithArguments(Sample); addMessageWithArguments(ValueAt); // needed to be handled by a TTXmlHandler addMessageWithArguments(WriteAsXml); addMessageProperty(WriteAsXml, hidden, YES); addMessageWithArguments(ReadFromXml); addMessageProperty(ReadFromXml, hidden, YES); // needed to be handled by a TTTextHandler addMessageWithArguments(WriteAsText); addMessageProperty(WriteAsText, hidden, YES); addMessageWithArguments(ReadFromText); addMessageProperty(ReadFromText, hidden, YES); mFunction = TTObject("freehand", 1); // for 1 channel only } TTCurve::~TTCurve() { ; } TTErr TTCurve::getFunctionParameters(TTValue& value) { TTValue curveList; TTUInt32 i, j; if (mRecorded) { // return parameters from samples