// All messages being returned from the module should be funneled through this function! void hub_outlet_return(t_hub *x, t_symbol *msg, long argc, t_atom *argv) { outlet_anything(x->outlets[k_outlet_return], msg, argc, argv); if(x->osc_name == NULL) // it's possible for this method to be called before osc_name is valid return; // ... if(x->jcom_send){ char mess[256]; t_symbol *osc; strcpy(mess, x->osc_name->s_name); strcat(mess, msg->s_name); osc = gensym(mess); object_method_typed(x->jcom_send, osc, argc, argv, NULL); } }
void update_meters(t_out *x) { short i; t_atom a[2]; x->clock_is_set = 0; for(i=0; i < x->num_meter_objects; i++){ if(x->meter_object[i] && x->peakamp[i] != x->lastPeakamp[i]){ atom_setsym(&a[0], _sym_float); atom_setfloat(&a[1], x->peakamp[i]); object_method_typed(x->meter_object[i], jps_dispatched, 2, a, NULL); x->lastPeakamp[i] = x->peakamp[i]; x->peakamp[i] = 0; } } clock_delay(x->clock, kPollIntervalDefault); // restart the clock }
// FREEZE UI for all parameters void hub_ui_freeze(t_hub *x, t_symbol*, long argc, t_atom *argv) { subscriberList *subscriber = x->subscriber; // head of the linked list t_max_err err = MAX_ERR_NONE; // Change freeze status for all messages and parameters subscriberIterator i; t_subscriber* t; // Change freeze attribute for the gui // FIXME: This call is not working!!!! // this means that the ui menu does not always reflect the state correctly err = object_attr_setlong(x->gui_object, gensym("ui_is_frozen"), atom_getlong(argv)); critical_enter(0); for(i = subscriber->begin(); i != subscriber->end(); ++i) { t = *i; if(t->type == jps_subscribe_parameter) object_method_typed(t->object, jps_ui_slash_freeze, 1, argv, NULL); } critical_exit(0); }
void hub_free(t_hub *x) { subscriberIterator i; subscriberList *subscriber = x->subscriber; t_atom a[2]; object_free(x->preset_interface); jamoma_hub_remove(x->osc_name); atom_setsym(a, x->attr_name); atom_setsym(a+1, x->osc_name); object_method_typed(g_jcom_send_notifications, gensym("module.removed"), 2, a, NULL); critical_enter(0); for(i = subscriber->begin(); i != subscriber->end(); ++i) { // notify the subscriber that the hub is going away if(!NOGOOD((*i)->object)) object_method((*i)->object, jps_release); sysmem_freeptr(*i); } critical_exit(0); object_free(x->textEditor); if(x->textSize) free(x->text); hub_internals_destroy(x); hub_presets_clear(x, NULL, 0, NULL); qelem_free(x->init_qelem); if(x->jcom_send) object_free(x->jcom_send); if(x->jcom_receive) object_free(x->jcom_receive); x->subscriber->clear(); delete x->subscriber; delete x->preset; }
void HoaDecode_reconnect_outlet(t_HoaDecode *x) { t_object *patcher; t_object *decoder; t_object *object; t_object *line; t_max_err err; err = object_obex_lookup(x, gensym("#P"), (t_object **)&patcher); if (err != MAX_ERR_NONE) return; err = object_obex_lookup(x, gensym("#B"), (t_object **)&decoder); if (err != MAX_ERR_NONE) return; for (line = jpatcher_get_firstline(patcher); line; line = jpatchline_get_nextline(line)) { if (jpatchline_get_box1(line) == decoder) { object = jpatchline_get_box2(line); for(int i = 0; jbox_getinlet((t_jbox *)object, i) != NULL && i < x->f_AmbisonicsDecoder->getNumberOfOutputs(); i++) { t_atom msg[4]; t_atom rv; atom_setobj(msg, decoder); atom_setlong(msg + 1, i); atom_setobj(msg + 2, object); atom_setlong(msg + 3, i); object_method_typed(patcher , gensym("connect"), 4, msg, &rv); } } } }
void HoaDecode_disconnect_outlet(t_HoaDecode *x) { t_object *patcher; t_object *decoder; t_object *object; t_object *line; t_max_err err; err = object_obex_lookup(x, gensym("#P"), (t_object **)&patcher); if (err != MAX_ERR_NONE) return; err = object_obex_lookup(x, gensym("#B"), (t_object **)&decoder); if (err != MAX_ERR_NONE) return; for (line = jpatcher_get_firstline(patcher); line; line = jpatchline_get_nextline(line)) { if (jpatchline_get_box1(line) == decoder) { object = jpatchline_get_box2(line); if(jpatchline_get_inletnum(line) != 0 && jpatchline_get_outletnum(line) != 0) { t_atom msg[4]; t_atom rv; atom_setobj(msg, decoder); atom_setlong(msg + 1, jpatchline_get_outletnum(line)); atom_setobj(msg + 2, object); atom_setlong(msg + 3, jpatchline_get_inletnum(line)); object_method_typed(patcher , gensym("disconnect"), 4, msg, &rv); } } } }
void HoaDecode_send_angles(t_HoaDecode *x) { t_object *patcher; t_object *decoder; t_object *object; t_object *line; t_max_err err; err = object_obex_lookup(x, gensym("#P"), (t_object **)&patcher); if (err != MAX_ERR_NONE) return; err = object_obex_lookup(x, gensym("#B"), (t_object **)&decoder); if (err != MAX_ERR_NONE) return; for (line = jpatcher_get_firstline(patcher); line; line = jpatchline_get_nextline(line)) { if (jpatchline_get_box1(line) == decoder) { object = jpatchline_get_box2(line); t_symbol* classname = object_classname(jbox_get_object(object)); if(classname == gensym("hoa.meter~") || classname == gensym("hoa.gain~") || classname == gensym("hoa.vector~")) { long argc = x->f_AmbisonicsDecoder->getNumberOfOutputs(); t_atom *argv = new t_atom[argc]; for(int i = 0; i < argc; i++) atom_setfloat(argv+i, x->f_AmbisonicsDecoder->getLoudspeakerAngle(i)); object_method_typed(jbox_get_object(object), gensym("angles"), argc, argv, NULL); free(argv); } } } }
void hub_script(t_hub* x, SymbolPtr s, AtomCount ac, AtomPtr av) { object_method_typed(x->container, _sym_script, ac, av, NULL); }
// TODO: need a custom setter so that we can update the display of the module name in the ui t_max_err hub_attr_setname(t_hub* x, t_object* attr, long argc, t_atom* argv) { if(argc && argv){ char name[256]; unsigned short i; t_max_err err = MAX_ERR_NONE; char* nametest; t_atom a[2]; int instance = 0; TTBoolean nameConflict = false; t_symbol* nameOriginal; x->osc_name = atom_getsym(argv); // No arg is present -- try to invent something intelligent for a name if(x->osc_name == _sym_nothing){ // it's annoting when doing fast demos and such to have to see this, so it is now silent when doing this: // object_post((t_object*)x, "%s: this module was not given an osc name as an argument! making up something that will hopefully work.", x->attr_name->s_name); // Strip jmod. from the beginning of patch names, this happens if you drag a module from browser to bpatcher if(strncmp(x->attr_name->s_name, "jmod.", 5) == 0) x->osc_name = gensym(x->attr_name->s_name + 5); else x->osc_name = x->attr_name; } strcpy(name, x->osc_name->s_name); // the name is autoprepended with a / if(name[0] != '/'){ char newname[256]; strcpy(newname, "/"); strcat(newname, name); strcpy(name, newname); } // search for illegal characters as specified by the OSC standard and replace them for(i=0; i<strlen(name); i++){ /* TODO :This has to happen only when setting the OSC name from the module's file name if(name[i] == '.') name[i] = '_'; else */ if(name[i] == '[') name[i] = '.'; else if(name[i] == ']') name[i] = 0; } // if arg contains a slash then we must complain nametest = name + 1; if(strchr(nametest, '/')) object_error((t_object*)x, "%s: OSC NAME GIVEN TO MODULES MAY NOT CONTAIN A SLASH OTHER THAN THE LEADING SLASH!", x->attr_name->s_name); nameOriginal = gensym(name); again: x->osc_name = gensym(name); // update the ui object if(x->gui_object){ atom_setsym(&a[0], gensym("module_name")); atom_setsym(&a[1], x->osc_name); object_method_typed(x->gui_object, jps_dispatched, 2, a, NULL); } // Register with the framework, and making sure this name hasn't already been used... // TODO: is the framework making sure that this t_object is unique and hasn't already been registered? err = jamoma_hub_register(x->osc_name, (t_object *)x); if(err){ if(instance){ nametest = strrchr(name, '.'); if(nametest) *nametest = 0; } instance++; nametest = name; snprintf(name, 256, "%s.%i", name, instance); nameConflict = true; err = MAX_ERR_NONE; goto again; } if(nameConflict) object_post((t_object*)x, "Jamoma cannot create multiple modules with the same OSC identifier (%s). Using %s instead.", nameOriginal->s_name, name); // And send a notification to the environment atom_setsym(a, x->attr_name); atom_setsym(a+1, x->osc_name); object_method_typed(g_jcom_send_notifications, gensym("module.new"), 2, a, NULL); } return MAX_ERR_NONE; }
void hub_module_view_alg(t_hub *x, t_symbol*, long, t_atom*) { if(x->in_object != NULL) object_method_typed(x->in_object, jps_open, 0, 0L, NULL); // send "open" to jcom.in hub_outlet_return(x, jps_slash_module_view_internals, 0, 0L); // return from jcom.hub left outlet }
// SYMBOL INPUT void hub_symbol(t_hub *x, t_symbol *msg, long argc, t_atom *argv) { bool found = false; subscriberList *subscriber = x->subscriber; char input[MAX_STRING_LEN]; // our input string char *input2 = input; // pointer to our input string char *split; t_symbol *osc = NULL; t_symbol *name = msg; // default to the name being the message strcpy(input, msg->s_name); if(*input2 == '/') // leading slash means it's OSC... input2++; // remove the leading slash split = strchr(input2, ':'); // remove (and store) the param name if(split != NULL){ *split = NULL; // now input2 = param name; split = a message for the parameter object split += 2; // this will jump the pointer past the :/ to the actual name osc = gensym(split); } name = gensym(input2); subscriberIterator i; t_subscriber* t; critical_enter(0); if(name == jps_star){ // wildcard t_symbol* type; for(i = subscriber->begin(); i != subscriber->end(); ++i) { t = *i; type = t->type; if(type == jps_subscribe_parameter || type == jps_subscribe_message || type == jps_subscribe_return){ if(osc == NULL){ object_method_typed(t->object, jps_dispatched, argc, argv, NULL); } else{ object_method_typed(t->object, osc, argc, argv, NULL); } } } } else{ // search the linked list of params to find the right one for(i = subscriber->begin(); (i != subscriber->end()) && (found == false); ++i) { t = *i; if(t->name == name) { found = true; break; } } // dispatch to the correct jcom.param object if(found == true){ if(osc == NULL){ object_method_typed(t->object, jps_dispatched, argc, argv, NULL); } else object_method_typed(t->object, osc, argc, argv, NULL); } else{ // Check to see if it's a message we need to forward to jcom.out if(name == jps_slash_audio_meters_freeze || name == jps_audio_meters_freeze) { t_atom msg[2]; atom_setsym(msg, name); jcom_core_atom_copy(msg+1, argv); if(x->out_object != NULL) object_method_typed(x->out_object, jps_algorithm_message, 2, msg, NULL); } else if(!x->using_wildcard) { // if we got here through the use a remote message to modules named by a wildcard // then we need don't post annoying errors to the Max window if (x->editing) object_error((t_object*)x, "No message or parameter named %s (in %s module).", name->s_name, x->attr_name->s_name); else object_error((t_object*)x, "No message or parameter named %s (in %s module).", name->s_name, x->osc_name->s_name); } } } critical_exit(0); }
void hoa_gain_tometer(t_hoa_gain *x, t_symbol *s, long ac, t_atom *av) { if(ac && av) { t_object *patcher; t_object *gain; t_object *line; t_max_err err; t_atom rv; t_atom msg[4]; err = object_obex_lookup(x, hoa_sym_pound_P, (t_object **)&patcher); if (err != MAX_ERR_NONE) return; err = object_obex_lookup(x, hoa_sym_pound_B, (t_object **)&gain); if (err != MAX_ERR_NONE) return; vector<t_jbox *> boxes; for (line = jpatcher_get_firstline(patcher); line; line = jpatchline_get_nextline(line)) { if (jpatchline_get_box1(line) == gain) { t_jbox *box = (t_jbox*)jpatchline_get_box2(line); t_object *obj = jbox_get_object((t_object*)box); t_symbol* classname = object_classname(obj); if (find(boxes.begin(), boxes.end(), box) == boxes.end()) { if(classname == hoa_sym_hoa_2d_meter || classname == hoa_sym_hoa_2d_vector || classname == hoa_sym_hoa_gain) { object_method_typed(obj, s, ac, av, NULL); boxes.push_back(box); } else if(classname == hoa_sym_dac || (object_is_hoa(obj) && classname != hoa_sym_hoa_pi && classname != hoa_sym_hoa_pi_tilde)) { boxes.push_back(box); } } } } for(auto box : boxes) { // re-connect patchlines for(int i = 0; jbox_getinlet(box, i) != NULL && i < x->f_number_of_channels; i++) { atom_setobj(msg, gain); atom_setlong(msg + 1, i); atom_setobj(msg + 2, box); atom_setlong(msg + 3, i); object_method_typed(patcher , hoa_sym_connect, 4, msg, &rv); } } boxes.clear(); } }
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; } }
void hoa_dac_list(t_hoa_dac *x, t_symbol *s, long argc, t_atom *argv) { object_method_typed(x->f_dac, gensym("list"), argc, argv, NULL); }
void plug_setup_db(void) { t_atom a[4]; // This ugly hack not needed as of Max 5.1.7 // if (sDeferCount) { // sDeferCount--; // defer_low(sMaxObject, (method)plug_setup_db, NULL, 0, NULL); // return; // } // OBJECTS plug_alias_register("adc≈", "jcom.adc≈", "Audio", "Audio input"); plug_alias_register("adsr≈", "jcom.adsr≈", "Audio", "ADSR Envelope Generator"); plug_alias_register("audiounit≈", "jcom.audiounit≈", "Audio", "Host an AudioUnit plug-in"); plug_alias_register("dac≈", "jcom.dac≈", "Audio", "Audio output"); plug_alias_register("dcblocker≈", "jcom.dcblocker≈", "Audio", "Eliminate DC offsets"); plug_alias_register("degrade≈", "jcom.degrade≈", "Audio", "Distortion effect"); plug_alias_register("delay≈", "jcom.delay≈", "Audio", "Delay audio by a specified time"); plug_alias_register("fft≈", "jcom.fft≈", "Audio", "Convert a signal into the frequency domain"); plug_alias_register("filter≈", "jcom.filter≈", "Audio", "Swiss-Army knife of audio filters"); plug_alias_register("gain≈", "jcom.gain≈", "Audio", "Amplify or attenuate audio"); plug_alias_register("hilbert≈", "jcom.hilbert≈", "Audio", "Phase quadrature filter"); plug_alias_register("info≈", "jcom.info≈", "Audio", "Get properties of an audio signal"); plug_alias_register("join≈", "jcom.join≈", "Audio", "Join multiple signals together into a single signal"); plug_alias_register("limiter≈", "jcom.limiter≈", "Audio", "Lookahead dynamics processor"); plug_alias_register("matrix≈", "jcom.matrix≈", "Audio", "Mix and route channels within a signal"); plug_alias_register("matrixmixer≈", "jcom.matrixmixer≈", "Audio", "Mix and route multiple channels with each other"); plug_alias_register("noise≈", "jcom.noise≈", "Audio", "Generate various kinds of noise"); plug_alias_register("op≈", "jcom.op≈", "Audio", "Perform mathematical operations"); plug_alias_register("overdrive≈", "jcom.overdrive≈", "Audio", "Saturation effect"); plug_alias_register("pack≈", "jcom.pack≈", "Audio", "Bridge from MSP audio signals to Plugtastic"); plug_alias_register("phasor≈", "jcom.phasor≈", "Audio", "Oscillator ramping linearly from 0.0 to 1.0"); plug_alias_register("pulsesub≈", "jcom.pulsesub≈", "Audio", "Apply a cyclic ADSR envelope onto an input signal"); plug_alias_register("resample≈", "jcom.resample≈", "Audio", "Up/Downsample an audio signal"); plug_alias_register("sig≈", "jcom.sig≈", "Audio", "Create a signal from a constant value"); plug_alias_register("soundfile.player≈", "jcom.soundfile.player≈", "Audio", "Play a Soundfile"); plug_alias_register("soundfile.recorder≈", "jcom.soundfile.recorder≈", "Audio", "Record a Soundfile"); plug_alias_register("split≈", "jcom.split≈", "Audio", "Break a multichannel audio signal into smaller signals"); plug_alias_register("unpack≈", "jcom.unpack≈", "Audio", "Bridge from Plugtastic to MSP audio signals"); plug_alias_register("wavetable≈", "jcom.wavetable≈", "Audio", "Wavetable oscillator with several waveform options"); plug_alias_register("window≈", "jcom.window≈", "Audio", "Generate/Apply a window function for signal vector"); plug_alias_register("in≈", "plug.in≈", "Environment", "Audio input from the plug-in host environment"); plug_alias_register("out≈", "plug.out≈", "Environment", "Audio output to the plug-in host environment"); plug_alias_register("parameter#", "plug.parameter#", "Environment", "Define a parameter to be controlled in the host environment"); plug_alias_register("append#", "jcom.append#", "Control", "Add/Replace named data in a dictionary"); plug_alias_register("dataspace#", "jcom.dataspace#", "Control", "Convert values expressed in one unit into another unit."); plug_alias_register("iter#", "jcom.iter#", "Control", "Output all key/value sets from a dictionary to Max messages."); plug_alias_register("log#", "jcom.log#", "Control", "Print input to the Max window."); plug_alias_register("midi.in#", "jcom.midi.in#", "Control", "MIDI Input from a device, or from the plug-in host environment"); plug_alias_register("midi.out#", "jcom.midi.out#", "Control", "MIDI Output to a device"); plug_alias_register("midi.filter#", "jcom.midi.filter#", "Control", "Parse raw MIDI events"); plug_alias_register("midi.format#", "jcom.midi.format#", "Control", "Format dictionaries into raw MIDI events"); plug_alias_register("op#", "jcom.op#", "Control", "Perform mathematical operations on a dictionary"); plug_alias_register("pack#", "jcom.pack#", "Control", "Convert native Max data into a Plugtastic dictionary"); plug_alias_register("unpack#", "jcom.unpack#", "Control", "Convert a Plugtastic dictionary into native Max data"); // backwards compatibility //plug_alias_register("parameter!", "plug.parameter#", "Environment", "Define a parameter to be controlled in the host environment"); //plug_alias_register("append!", "jcom.append#", "Control", "Add/Replace named data in a dictionary"); //plug_alias_register("op!", "jcom.op#", "Control", "Perform mathematical operations on a dictionary"); //plug_alias_register("pack!", "jcom.pack#", "Control", "Convert native Max data into a Plugtastic dictionary"); //plug_alias_register("unpack!", "jcom.unpack#", "Control", "Convert a Plugtastic dictionary into native Max data"); // CLIPPINGS atom_setsym(a+1, _sym_clipping); atom_setsym(a+2, _sym_tag); atom_setsym(a+3, GENSYM("Plugtastic")); atom_setsym(a+0, GENSYM("plug.input")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.output")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.param")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+3, GENSYM("Environment")); atom_setsym(a+0, GENSYM("plug.input")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.output")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.param")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+2, _sym_description); atom_setsym(a+0, GENSYM("plug.input")); atom_setsym(a+3, GENSYM("Input stage for developing a plug-in")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.output")); atom_setsym(a+3, GENSYM("Output stage for developing a plug-in")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+0, GENSYM("plug.param")); atom_setsym(a+3, GENSYM("Expanded parameter with a number box")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); // EXAMPLES atom_setsym(a+1, _sym_patcher); atom_setsym(a+2, _sym_tag); atom_setsym(a+3, GENSYM("Plugtastic")); atom_setsym(a+0, GENSYM("My Plugtastic Adventure")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); atom_setsym(a+3, GENSYM("Example")); atom_setsym(a+0, GENSYM("My Plugtastic Adventure")); object_method_typed(sMaxObject, ps_db_addmetadata, 4, a, NULL); }
void jamoma_init(void) { if(!initialized){ t_object* max = gensym("max")->s_thing; t_symbol* meth = gensym("objectfile"); t_atom a[4]; if(maxversion() >= 0x0500) max5 = true; TTBlueInit(); common_symbols_init(); jamomaSymbolsInit(); receivemaster_initclass(); receive_initclass(); object_method(max, meth, gensym("jcom.receive"), gensym("jcom.loader"), gensym("jcom.receive")); object_method_sym(max, gensym("db.object_addinternal"), gensym("jcom.receive"), NULL); send_initclass(); object_method(max, meth, gensym("jcom.send"), gensym("jcom.loader"), gensym("jcom.send")); object_method_sym(max, gensym("db.object_addinternal"), gensym("jcom.send"), NULL); receive_tilde_initclass(); object_method(max, meth, gensym("jcom.receive~"), gensym("jcom.loader"), gensym("jcom.receive~")); object_method_sym(max, gensym("db.object_addinternal"), gensym("jcom.receive~"), NULL); send_tilde_initclass(); object_method(max, meth, gensym("jcom.send~"), gensym("jcom.loader"), gensym("jcom.send~")); object_method_sym(max, gensym("db.object_addinternal"), gensym("jcom.send~"), NULL); // Setup Class Aliases for TTBlue object_method(max, meth, gensym("jcom.limiter~"), gensym("tt.limiter~"), gensym("jcom.limiter~")); object_method(max, meth, gensym("jcom.saturation~"), gensym("tt.overdrive~"), gensym("jcom.saturation~")); // Create Required Global Instances // obj_jamoma_clock = (t_object*)object_new_typed(CLASS_NOBOX, gensym("jamoma.clock"), 0, NULL); // obj_jamoma_scheduler = (t_object*)object_new_typed(CLASS_NOBOX, gensym("jamoma.scheduler"), 0, NULL); hash_modules = (t_hashtab*)hashtab_new(0); // TODO: Use quittask_install() to set up a destructor for this to free it before Max exits // This tells Max 5.0.6 and higher that we want the patcher files to be saved such that they are sorted. // Having the saved this way makes our SVN diffs much more meaningful. object_method_long(max, gensym("sortpatcherdictonsave"), 1, NULL); // This tells Max 4.5.7 and higher to take any posts to the Max window and also make the // post to the system console, which greatly aids in debugging problems and crashes object_method_long(max, gensym("setmirrortoconsole"), 1, NULL); // Add Jamoma Key Commands: // J -- Jamoma: a new object box with "jcom." in it atom_setsym(a+0, gensym("J")); atom_setsym(a+1, gensym("patcher")); atom_setsym(a+2, gensym("inserttextobj")); atom_setsym(a+3, gensym("jcom.")); object_method_typed(max, gensym("definecommand"), 4, a, NULL); // M -- Module: a new object box with "jmod." in it atom_setsym(a+0, gensym("M")); atom_setsym(a+1, gensym("patcher")); atom_setsym(a+2, gensym("inserttextobj")); atom_setsym(a+3, gensym("jmod.")); object_method_typed(max, gensym("definecommand"), 4, a, NULL); // I -- Input: a new audio input module object_method_parse(max, gensym("definecommand"), "I patcher insertobj bpatcher @name jmod.input~.maxpat @args /input~", NULL); // O -- Output: a new audio output module object_method_parse(max, gensym("definecommand"), "O patcher insertobj bpatcher @name jmod.output~.maxpat @args /output~", NULL); // B -- BPatcher: a new module in a bpatcher object_method_parse(max, gensym("definecommand"), "B patcher inserttextobj \"bpatcher @name jmod. @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, gensym("definecommand"), "D patcher inserttextobj \"bpatcher @name jmod.\"", NULL); // Here bind the TTBlue environment object to the symbol "TTBlue" { t_symbol* TTBlueMaxSymbol = gensym("TTBlue"); TTBlueMaxSymbol->s_thing = 0; // Before we can do this we have to have a ttblue max class to receive the messages, duh... } // now the jamoma object { t_symbol* jamomaSymbol = gensym("jamoma"); jamoma_object_initclass(); jamomaSymbol->s_thing = jamoma_object_new(); } post("Jamoma %s - www.jamoma.org", JAMOMA_VERSION); initialized = true; } }