ObjectPtr jamoma_new(SymbolPtr s, AtomCount argc, AtomPtr argv) { int attrstart = attr_args_offset(argc, argv); int i = 0; int channelCount = 2; SymbolPtr className = gensym("gain"); MaxAudioGraphWrappedClassPtr classWrapper = NULL; char maxClassName[256]; if (!attrstart) { error("must specify a jamoma class as the first argument"); return NULL; } while (attrstart--) { if (atom_gettype(argv+i) == A_LONG) channelCount = atom_getlong(argv+i); else if (atom_gettype(argv+i) == A_SYM) className = atom_getsym(argv+i); i++; } snprintf(maxClassName, 256, "j.%s=", className->s_name); if (!s_jamoma_class_hash) s_jamoma_class_hash = hashtab_new(0); hashtab_lookup(s_jamoma_class_hash, className, (t_object**)&classWrapper); if (!classWrapper) { wrapAsMaxAudioGraph(className->s_name, maxClassName, &classWrapper); hashtab_store(s_jamoma_class_hash, className, ObjectPtr(classWrapper)); } return MaxAudioGraphWrappedClass_new(gensym(maxClassName), argc-1, argv+1); }
void *sheep_new(t_symbol *s, long argc, t_atom *argv) { t_sheep *x = NULL; t_object *jp = NULL; if (x = (t_sheep *)object_alloc(sheep_class)) { jp = (t_object *)gensym("#P")->s_thing; if (jp) { t_hashtab *ht; // look in the jpatcher's obex for an object called "sheephash" object_obex_lookup(jp, gensym("sheephash"), (t_object **)&ht); if (!ht) { // it's not there? create it. ht = hashtab_new(0); // objects stored in the obex will be freed when the obex's owner is freed // in this case, when the patcher object is freed. so we don't need to // manage the memory associated with the "sheephash". object_obex_store(jp, gensym("sheephash"), (t_object *)ht); } // cache the registered name so we can remove self from hashtab x = object_register(CLASS_BOX, x->myobjname = symbol_unique(), x); // store self in the hashtab. IMPORTANT: set the OBJ_FLAG_REF flag so that the // hashtab knows not to free us when it is freed. hashtab_storeflags(ht, x->myobjname, (t_object *)x, OBJ_FLAG_REF); } } return (x); }
t_class *omax_class_new(char *name, method ctor, method dtor, size_t structsize, size_t osc_ob_offset, method fullpacket_method) { method fp; if(fullpacket_method){ fp = fullpacket_method; }else{ fp = (method)omax_FullPacket; } t_class *c = class_new(name, ctor, dtor, structsize, 0L, A_GIMME, 0); t_hashtab *ht = hashtab_new(0); omax_class_makeHashtabName(name)->s_thing = (t_object *)ht; hashtab_store(ht, gensym("cnmat_internal_osc_ob_offset"), (t_object *)osc_ob_offset); class_addmethod(c, fp, "FullPacket", A_LONG, A_LONG, 0); //class_addmethod(c, (method)omax_tellmeeverything, "tellmeeverything", 0); //OMAX_ADDMETHOD(c, (method)omax_tellmeeverything, "tellmeeverything", 0); //OMAX_ADDMETHOD(c, (method)omax_probe, "probe", 0); OMAX_ADDMETHOD_OSCNAME(c, (method)omax_schemaList, "oscschemalist", "/osc/schema/list", 0); OMAX_ADDMETHOD_OSCNAME(c, (method)omax_object_ioReport, "oscioreport", "/osc/io/report", A_GIMME, 0); class_addmethod(c, (method)omax_notify, "notify", A_CANT, 0); ps_oscschemalist = gensym("/osc/schema/list"); ps_oscioreport = gensym("/osc/io/report"); return c; }
void *howbigisyourp_new(t_symbol *s, long argc, t_atom *argv) { t_howbigisyourp *x = NULL; if ((x = (t_howbigisyourp *)object_alloc(howbigisyourp_class))) { x->subpatchername = gensym(""); x->out = outlet_new(x, NULL); x->hash = hashtab_new(0); hashtab_flags(x->hash, OBJ_FLAG_DATA); } return (x); }
void *dbviewer_new(t_symbol *s, short argc, t_atom *argv) { t_dbviewer *x; long flags; t_dictionary *d = NULL; if (!(d=object_dictionaryarg(argc, argv))) return NULL; x = (t_dbviewer*)object_alloc(s_dbviewer_class); if(x){ flags = 0 | JBOX_DRAWFIRSTIN | JBOX_NODRAWBOX | JBOX_DRAWINLAST // | JBOX_TRANSPARENT // | JBOX_NOGROW // | JBOX_GROWY | JBOX_GROWBOTH // | JBOX_IGNORELOCKCLICK | JBOX_HILITE // | JBOX_BACKGROUND // | JBOX_NOFLOATINSPECTOR // | JBOX_TEXTFIELD ; jbox_new(&x->d_box, flags, argc, argv); x->d_box.b_firstin = (t_object*)x; object_obex_store((void *)x, _sym_dumpout, (t_object*)outlet_new(x, NULL)); x->d_columns = hashtab_new(13); hashtab_flags(x->d_columns, OBJ_FLAG_DATA); x->d_query = _sym_nothing; dbviewer_initdataview(x); attr_dictionary_process(x, d); jbox_ready(&x->d_box); // object_notify(x->d_view, ps_dbview_update, NULL); } return(x); }
void *ar_new(t_symbol *name, long size){ t_ar *x; if(x = (t_ar *)object_alloc(ar_class)){ t_hashtab *ht; t_linklist *ll; x->outlets[3] = outlet_new(x, NULL); x->outlets[2] = outlet_new(x, NULL); x->outlets[1] = outlet_new(x, NULL); x->outlets[0] = outlet_new(x, NULL); if(strlen(name->s_name) > 0){ x->name = name; x->iname_ht = ar_make_iname(name, _sym_hashtab); x->iname_ll = ar_make_iname(name, _sym_linklist); ar_inc_refcount(x->name); if(ht = (t_hashtab *)(name->s_thing)){ }else{ ht = (t_hashtab *)hashtab_new(size); x->iname_ht->s_thing = (t_object *)ht; ll = (t_linklist *)linklist_new(); x->iname_ll->s_thing = (t_object *)ll; } }else{ x->name = ar_make_def_name(); x->iname_ht = ar_make_iname(x->name, _sym_hashtab); x->iname_ll = ar_make_iname(x->name, _sym_linklist); ar_inc_refcount(x->name); /* x->name = _sym_emptytext; x->iname_ht = _sym_emptytext; x->iname_ll = _sym_emptytext; */ } srand(makeseed()); return x; } return NULL; }
void ar_array(t_ar *x, t_symbol *name){ t_symbol *iname_ht = ar_make_iname(name, _sym_hashtab); t_hashtab *incoming_ht = (t_hashtab *)(iname_ht->s_thing); t_hashtab *ht; t_linklist *ll; t_symbol **keys = NULL; long numKeys = 0; long i; hashtab_getkeys(incoming_ht, &numKeys, &keys); if(!(ht = (t_hashtab *)x->iname_ht->s_thing) || !(ll = (t_linklist *)x->iname_ll->s_thing)){ ht = hashtab_new(AR_DEFAULT_SLOTS); ll = linklist_new(); x->iname_ht->s_thing = (void *)ht; x->iname_ll->s_thing = (void *)ll; } ar_freeall(ht, ll); for(i = 0; i < numKeys; i++){ t_atombuf *ab1, *ab2; hashtab_lookup(incoming_ht, keys[i], (t_object **)(&ab1)); ab2 = (t_atombuf *)atombuf_new(ab1->a_argc, ab1->a_argv); hashtab_store(ht, keys[i], (t_object *)ab2); linklist_append(ll, keys[i]); } }
void *cc_new(t_symbol *msg, short argc, t_atom *argv){ t_cc *x; if(x = (t_cc *)object_alloc(cc_class)){ #if defined(CC_JBOX) t_dictionary *d = NULL; long boxflags; if(!(d = object_dictionaryarg(argc, argv))){ return NULL; } boxflags = 0 | JBOX_DRAWFIRSTIN //| JBOX_NODRAWBOX | JBOX_DRAWINLAST //| JBOX_TRANSPARENT // | JBOX_NOGROW //| JBOX_GROWY | JBOX_GROWBOTH // | JBOX_HILITE | JBOX_BACKGROUND | JBOX_DRAWBACKGROUND // | JBOX_NOFLOATINSPECTOR // | JBOX_MOUSEDRAGDELTA // | JBOX_TEXTFIELD ; jbox_new((t_jbox *)x, boxflags, argc, argv); #if defined(CC_MSP) x->ob.z_box.b_firstin = (void *)x; #else x->ob.b_firstin = (void *)x; #endif #endif x->ht = (t_hashtab *)hashtab_new(0); hashtab_flags(x->ht, OBJ_FLAG_DATA); x->ok_to_compile = 1; x->compiling = 0; x->have_valid_filename = 0; x->build_path_is_tmp = 1; x->ed = NULL; x->code_buf_len = BUFSIZE; x->code_buf = (char *)calloc(BUFSIZE, sizeof(char)); x->cfile_path = (char *)calloc(MAX_FILENAME_CHARS, sizeof(char)); x->build_path = (char *)calloc(MAX_FILENAME_CHARS, sizeof(char)); x->basename = (char *)calloc(MAX_FILENAME_CHARS, sizeof(char)); x->cfile_fullpath = (char *)calloc(MAX_PATH_CHARS, sizeof(char)); x->ofile_fullpath = (char *)calloc(MAX_PATH_CHARS, sizeof(char)); x->dfile_fullpath = (char *)calloc(MAX_PATH_CHARS, sizeof(char)); x->logfile_fullpath = (char *)calloc(MAX_PATH_CHARS, sizeof(char)); x->path_to_maxsdk = gensym(""); x->user_obj = (char *)calloc(OBJSIZE, sizeof(char)); x->verbose = 0; long ic = (long)(ps_cc_instance_count->s_thing); ic += 1; ps_cc_instance_count->s_thing = (void *)ic; #if defined(CC_MSP) && defined(CC_JBOX) sprintf(x->basename, "cc_jbox~_%ld", (long)ps_cc_instance_count->s_thing); #elif defined(CC_MSP) sprintf(x->basename, "cc~_%ld", (long)ps_cc_instance_count->s_thing); #elif defined(CC_JBOX) sprintf(x->basename, "cc_jbox_%ld", (long)ps_cc_instance_count->s_thing); #else sprintf(x->basename, "cc_%ld", (long)ps_cc_instance_count->s_thing); #endif short tmpdir; sprintf(x->build_path, "/private/var/tmp"); char fn[512]; path_frompathname(x->build_path, &tmpdir, fn); x->build_path_id = tmpdir; //sprintf(x->cfile_fullpath, "%s/%s.c", x->build_path, x->basename); sprintf(x->ofile_fullpath, "%s/%s.o", x->build_path, x->basename); sprintf(x->dfile_fullpath, "%s/%s.dylib", x->build_path, x->basename); sprintf(x->logfile_fullpath, "%s/%s.log", x->build_path, x->basename); x->code_len = cc_write_template(x, x->code_buf); x->function_names = (t_symbol **)calloc(128, sizeof(t_symbol *)); x->ninlets = 1; x->noutlets = 1; x->def_cflags = (char *)calloc(4096, sizeof(char)); x->def_ldflags = (char *)calloc(4096, sizeof(char)); char *sdk = x->path_to_maxsdk->s_name; #if defined(CC_MSP) sprintf(x->def_cflags, CFLAGS, sdk, sdk, sdk, sdk, sdk); sprintf(x->def_ldflags, LDFLAGS, sdk, sdk); #else sprintf(x->def_cflags, CFLAGS, sdk, sdk, sdk); sprintf(x->def_ldflags, LDFLAGS, sdk); #endif x->user_cflags = gensym(""); x->user_ldflags = gensym(""); #ifdef CC_JBOX x->user_paint = NULL; #endif #if !defined(CC_JBOX) attr_args_process(x, argc, argv); #else attr_dictionary_process(x, d); #endif int i; #if defined(CC_MSP) #if defined(CC_JBOX) dsp_setupjbox((t_pxjbox *)x, x->nsiginlets); #else dsp_setup((t_pxobject *)x, x->nsiginlets); #endif for(i = 0; i < x->nsigoutlets; i++){ outlet_new((t_object *)x, "signal"); } x->svin = (t_float **)calloc(x->nsiginlets, sizeof(t_float *)); x->svout = (t_float **)calloc(x->nsigoutlets, sizeof(t_float *)); #endif x->proxies = (void **)calloc(x->ninlets - 1, sizeof(void *)); for(i = 0; i < x->ninlets - 1; i++){ x->proxies[0] = proxy_new((t_object *)x, x->ninlets - (i + 1), &(x->inlet)); } #if !defined(CC_MSP) x->outlets = (void **)calloc(x->noutlets, sizeof(void *)); for(i = x->noutlets - 1; i >= 0; i--){ x->outlets[i] = outlet_new((t_object *)x, NULL); } #endif x->handle = NULL; object_attach_byptr_register(x, x, CLASS_BOX); #ifdef CC_JBOX jbox_ready((t_jbox *)x); #endif return x; } return NULL; }
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; } }
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 wrapAsMaxAudioGraph(TTSymbolPtr ttClassName, char* maxClassName, WrappedClassPtr* c, WrappedClassOptionsPtr options) { TTObject* o = NULL; TTValue v; TTUInt16 numChannels = 1; WrappedClass* wrappedMaxClass = NULL; common_symbols_init(); TTAudioGraphInit(); if(!wrappedMaxClasses) wrappedMaxClasses = hashtab_new(0); wrappedMaxClass = new WrappedClass; wrappedMaxClass->maxClassName = gensym(maxClassName); wrappedMaxClass->maxClass = class_new( maxClassName, (method)wrappedClass_new, (method)wrappedClass_free, sizeof(WrappedInstance), (method)0L, A_GIMME, 0); wrappedMaxClass->ttClassName = ttClassName; wrappedMaxClass->validityCheck = NULL; wrappedMaxClass->validityCheckArgument = NULL; wrappedMaxClass->options = options; wrappedMaxClass->maxAttrNamesToTTAttrNames = hashtab_new(0); // 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++){ TTSymbolPtr name = NULL; v.get(i, &name); if(name == TT("updateMaxNumChannels") || name == TT("updateSr")) continue; // don't expose these attributes to Max users class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_anything, (char*)name->getCString(), A_GIMME, 0); } o->getAttributeNames(v); for (TTUInt16 i=0; i<v.getSize(); i++) { TTSymbolPtr name = NULL; TTAttributePtr attr = NULL; SymbolPtr maxType = _sym_long; TTCString nameCString = NULL; SymbolPtr nameMaxSymbol = NULL; TTUInt32 nameSize = 0; v.get(i, &name); if(name == TT("maxNumChannels") || name == TT("processInPlace")) continue; // don't expose these attributes to Max users 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; // convert first letter to lower-case if it isn't already nameSize = name->getString().length(); nameCString = new char[nameSize+1]; strncpy_zero(nameCString, name->getCString(), nameSize+1); if (nameCString[0]>64 && nameCString[0]<91) nameCString[0] += 32; nameMaxSymbol = gensym(nameCString); hashtab_store(wrappedMaxClass->maxAttrNamesToTTAttrNames, nameMaxSymbol, ObjectPtr(name)); class_addattr(wrappedMaxClass->maxClass, attr_offset_new(nameCString, maxType, 0, (method)wrappedClass_attrGet, (method)wrappedClass_attrSet, NULL)); // Add display styles for the Max 5 inspector if (attr->type == kTypeBoolean) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)name->getCString(), 0, "onoff"); if (name == TT("fontFace")) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, "fontFace", 0, "font"); } 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)object_obex_dumpout, "dumpout", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_assist, "assist", A_CANT, 0L); class_addmethod(wrappedMaxClass->maxClass, (method)stdinletinfo, "inletinfo", A_CANT, 0); class_register(_sym_box, wrappedMaxClass->maxClass); if (c) *c = wrappedMaxClass; hashtab_store(wrappedMaxClasses, wrappedMaxClass->maxClassName, ObjectPtr(wrappedMaxClass)); return kTTErrNone; }
TTErr wrapAsMaxGraph(TTSymbol& ttClassName, char* maxClassName, WrappedClassPtr* c, WrappedClassOptionsPtr options) { TTObjectBasePtr o = NULL; TTValue v; TTUInt16 numChannels = 1; WrappedClass* wrappedMaxClass = NULL; TTSymbol name; TTCString nameCString = NULL; t_symbol* nameMaxSymbol = NULL; TTUInt32 nameSize = 0; common_symbols_init(); TTGraphInit(); if (!wrappedMaxClasses) wrappedMaxClasses = hashtab_new(0); wrappedMaxClass = new WrappedClass; wrappedMaxClass->maxClassName = gensym(maxClassName); wrappedMaxClass->maxClass = class_new( maxClassName, (method)wrappedClass_new, (method)wrappedClass_free, sizeof(WrappedInstance), (method)0L, A_GIMME, 0); wrappedMaxClass->ttClassName = ttClassName; wrappedMaxClass->validityCheck = NULL; wrappedMaxClass->validityCheckArgument = NULL; wrappedMaxClass->options = options; wrappedMaxClass->maxNamesToTTNames = hashtab_new(0); // Create a temporary instance of the class so that we can query it. TTObjectBaseInstantiate(ttClassName, &o, numChannels); o->getMessageNames(v); for (TTUInt16 i=0; i<v.size(); i++) { name = v[i]; nameSize = strlen(name.c_str()); nameCString = new char[nameSize+1]; strncpy_zero(nameCString, name.c_str(), nameSize+1); nameMaxSymbol = gensym(nameCString); hashtab_store(wrappedMaxClass->maxNamesToTTNames, nameMaxSymbol, (t_object*)name.rawpointer()); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_anything, nameCString, A_GIMME, 0); delete nameCString; nameCString = NULL; } o->getAttributeNames(v); for (TTUInt16 i=0; i<v.size(); i++) { TTAttributePtr attr = NULL; t_symbol* maxType = _sym_long; name = v[i]; 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"), v)) 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; hashtab_store(wrappedMaxClass->maxNamesToTTNames, nameMaxSymbol, (t_object*)name.rawpointer()); class_addattr(wrappedMaxClass->maxClass, attr_offset_new(nameCString, maxType, 0, (method)wrappedClass_attrGet, (method)wrappedClass_attrSet, 0)); // Add display styles for the Max 5 inspector if (attr->type == kTypeBoolean) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, (char*)name.c_str(), 0, "onoff"); if (name == TT("fontFace")) CLASS_ATTR_STYLE(wrappedMaxClass->maxClass, "fontFace", 0, "font"); delete nameCString; nameCString = NULL; } TTObjectBaseRelease(&o); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphReset, "graph.reset", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphSetup, "graph.setup", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)MaxGraphConnect, "graph.connect", A_OBJ, A_LONG, 0); class_addmethod(wrappedMaxClass->maxClass, (method)object_obex_dumpout, "dumpout", A_CANT, 0); class_addmethod(wrappedMaxClass->maxClass, (method)wrappedClass_assist, "assist", A_CANT, 0L); class_addmethod(wrappedMaxClass->maxClass, (method)stdinletinfo, "inletinfo", A_CANT, 0); class_register(_sym_box, wrappedMaxClass->maxClass); if (c) *c = wrappedMaxClass; hashtab_store(wrappedMaxClasses, wrappedMaxClass->maxClassName, (t_object*)wrappedMaxClass); return kTTErrNone; }
// do a depth-first or breadth-first search in state space up to specified depth // bfs: boolean flag if to do a breadth-first seach (depth_max is ignored in this case) // buffer_len: size of state buffer // hash_entries, hash_retries: parameters of hash table to finf duplicate states // graph_out: if != NULL state graph will be output to this tream in graphviz dot format // print_hex: if to print states in hex // ini_state: state to start simulation at (or NULL to use default) void search (nipsvm_bytecode_t *bytecode, int bfs, unsigned int depth_max, unsigned long buffer_len, unsigned long hash_entries, unsigned long hash_retries, FILE *graph_out, int print_hex, nipsvm_state_t *ini_state) // extern { char *p_buffer, *p_buf; t_hashtab hashtab; unsigned long buf_len; nipsvm_state_t *state; st_search_context ctx; struct timeval time_start, time_end, time_diff; double us_state; // allocate buffer for states p_buffer = (char *)malloc( buffer_len ); if( p_buffer == NULL ) rt_err( "out of memory (state buffer for search)" ); p_buf = p_buffer; buf_len = buffer_len; // allocate hash table hashtab = hashtab_new( hash_entries, hash_retries ); if( hashtab == NULL ) rt_err( "out of memory (hash table)" ); // tell user to wait if( bfs ) printf( "doing breadth-first search, please wait...\n" ); else printf( "doing depth-first search up to depth %u, please wait...\n", depth_max ); // remember start time gettimeofday( &time_start, NULL ); // set up context for successor state generation nipsvm_init (&ctx.nipsvm, bytecode, &search_succ_cb, &search_err_cb); // get initial state if( ini_state == NULL ) { ini_state = nipsvm_initial_state (&ctx.nipsvm); } // insert initial state into table { size_t sz = nipsvm_state_size (ini_state); state = nipsvm_state_copy (sz, ini_state, &p_buf, &buf_len); hashtab_insert (hashtab, sz, ini_state); } // set up rest of context for search ctx.depth_max = depth_max; ctx.depth_reached = 0; ctx.state_cnt = 0; ctx.transition_cnt = 0; ctx.n_atomic_steps = 0; ctx.max_state_size = 0; ctx.p_buf = p_buf; ctx.buf_len = buf_len; ctx.hashtab = hashtab; ctx.error = 0; ctx.graph_out = graph_out; ctx.graph_out_pred = state; ctx.print_hex = print_hex; // start search if( bfs ) search_internal_bfs( state, &ctx ); else search_internal_dfs_to_depth( state, 0, &ctx ); nipsvm_finalize (&ctx.nipsvm); // update pointer and length of state buffer p_buf = ctx.p_buf; buf_len = ctx.buf_len; // remember end time gettimeofday( &time_end, NULL ); // get time difference time_diff.tv_usec = time_end.tv_usec - time_start.tv_usec; time_diff.tv_sec = time_end.tv_sec - time_start.tv_sec; if( time_diff.tv_usec < 0 ) { time_diff.tv_usec += 1000000; time_diff.tv_sec--; } // get time per state (in microseconds) us_state = ((double)time_diff.tv_sec * 1000000.0 + (double)time_diff.tv_usec) / (double)ctx.state_cnt; // print statistics table_statistics_t t_stats; table_statistics (hashtab, &t_stats); unsigned long used_buffer_space = buffer_len - buf_len; double table_fill_ratio = 100.0 * (double)t_stats.entries_used / (double)t_stats.entries_available; double state_memory_fill_ratio = 100.0 * (double)used_buffer_space / (double)buffer_len; printf( "\n" ); if( bfs ) printf( "breadth-first search %s:\n", ctx.error ? "aborted" : "completed" ); else printf( "depth-first search up to depth %u %s:\n", depth_max, ctx.error ? "aborted" : "completed" ); printf( " states visited: %lu\n", ctx.state_cnt ); printf( " transitions visited: %lu\n", ctx.transition_cnt ); printf( " atomic steps: %lu\n", ctx.n_atomic_steps ); printf( " maximum state size: %u\n", ctx.max_state_size ); if( ! bfs ) printf( " reached depth: %u\n", ctx.depth_reached ); printf( " total time: %lu.%06lu s\n" " time per state: %f us\n", time_diff.tv_sec, (unsigned long)time_diff.tv_usec, us_state ); printf( "\n" ); printf( "state memory statistics:\n" ); printf( " total: %0.2fMB\n", buffer_len / 1048576.0 ); printf( " used: %0.2fMB (%0.1f%%)\n", used_buffer_space / 1048576.0, state_memory_fill_ratio ); printf( "\n" ); printf( "state table statistics:\n" " memory usage: %0.2fMB\n", t_stats.memory_size / 1048576.0 ); printf( " buckets used/available: %lu/%lu (%0.1f%%)\n", t_stats.entries_used, t_stats.entries_available, table_fill_ratio ); printf( " max. no. of retries: %lu\n", t_stats.max_retries ); printf( " conflicts (resolved): %lu\n", t_stats.conflicts ); // free state buffer and hash table free( p_buffer ); hashtab_free( hashtab ); }
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; } }