Max 5 API Reference
00001 /* 00002 jit.max.c 00003 00004 Copyright 2001-2005 - Cycling '74 00005 Joshua Kit Clayton jkc@cycling74.com 00006 00007 */ 00008 #include "jit.common.h" 00009 #include "jit.class.h" 00010 #include "ext_obex.h" 00011 00012 #define JIT_USURP_FLAGS_LOW 0x00000001 00013 #define JIT_USURP_FLAGS_MAX 0x00000002 00014 00015 char *get_data_from_macho_fptr(UInt32 *mfp); 00016 char *get_data_from_macho_fptr(UInt32 *mfp) 00017 { 00018 char *p=0; 00019 static long mv=0; 00020 00021 if (!mv) { 00022 mv = maxversion(); 00023 } 00024 00025 // maxversion hack for improper maxversion reporting in maxmsp 4.6beta 00026 if (((mv>=0x0460)||(mv<0x0300)) && (mfp[0]&0xFFFF0000)==0x3D800000) 00027 p = (char *)(((mfp[0]<<16)&0xFFFF0000) | (mfp[1]&0xFFFF)); 00028 else 00029 p = (char *)mfp; 00030 00031 return p; 00032 } 00033 00034 #if TARGET_RT_MAC_MACHO || defined(WIN_VERSION) 00035 #define FCHECK(x) (x) 00036 #else 00037 #define FCHECK(x) ((method)get_data_from_macho_fptr((UInt32 *)x)) 00038 #endif 00039 00040 /** 00041 * @defgroup maxwrapmod Max Wrapper Module 00042 @ingroup jitter 00043 */ 00044 00045 00046 //re: proxies - 00047 //need to add the concept of recording inlet number to usurp + defer methods 00048 //this might mean having to allocate additional memory for the defer methods 00049 00050 typedef struct _jit_usurp 00051 { 00052 t_jit_object ob; //needs to be an object for linklist 00053 void *parent; 00054 method m; 00055 t_symbol *sym; 00056 long flags; 00057 void *qelem; 00058 long argc; 00059 t_atom *argv; 00060 } t_jit_usurp; 00061 00062 typedef struct _max_jit_classex 00063 { 00064 long oboffset; //instance byte offset to the obex struct. 00065 t_jit_linklist *attrlist; 00066 t_jit_linklist *adornmentlist; 00067 } t_max_jit_classex; 00068 00069 typedef struct _max_jit_obex 00070 { 00071 void *jitob; 00072 void *usurplist; 00073 void *proxylist; 00074 long inletnumber; //for proxies 00075 void *dumpout; 00076 void *adornmentlist; 00077 t_box *b; // containing box 00078 } t_max_jit_obex; 00079 00080 static long _max_jit_queuestate=0; 00081 00082 long max_jit_queuestate(long state); 00083 long max_jit_getqueuestate(void); 00084 00085 void max_jit_init(void); 00086 void jit_usurp_init(void); 00087 void *jit_usurp_new(void *parent, method m, t_symbol *s, long flags); 00088 void jit_usurp_free(t_jit_usurp *x); 00089 void jit_usurp_method(t_jit_usurp *u, t_symbol *s, short argc, t_atom *argv); 00090 long jit_usurp_symcompare(t_jit_usurp *x, t_symbol *name); 00091 void max_jit_usurp_qfn(void *x); 00092 long max_jit_obex_attr_usercanset(void *x, t_symbol *s); 00093 void *max_jit_obex_attr_method_direct(void *x, t_symbol *s, long ac, t_atom *av); 00094 void max_jit_attrindex(void *x, t_symbol *s, long argc, t_atom *argv); 00095 00096 long jit_attr_symcompare(void *x, t_symbol *name); 00097 long jit_object_attr_usercanset(void *x,t_symbol *s); 00098 void max_jit_defer_method_doit(void *x, t_symbol *s, short argc, t_atom *argv); 00099 void max_jit_object_state_dump(void *x); 00100 void max_jit_object_summary(void *x, t_symbol *s); 00101 void max_jit_object_quickref(void *x, long *numitems, t_symbol **items); 00102 00103 void max_jit_obex_box_set(void *x, void *b); 00104 t_box *max_jit_obex_box_get(void *x); 00105 00106 static void *_jit_usurp_class; 00107 00108 //proxy compatibility 00109 #define proxy_compat_getinlet(x,id) ((fp_proxy_getinlet)?(long)fp_proxy_getinlet(x):(id)) 00110 #define proxy_compat_init (fp_proxy_getinlet = (method)gensym("__proxy_getinlet__")->s_thing) 00111 method fp_proxy_getinlet=0; 00112 00113 // for new max obex/pattr comptibility 00114 void *max_jit_obex_attr_getobject(void *x, t_symbol *s); 00115 void *max_jit_obex_attr_gettarget(void *x, t_symbol *s); 00116 long max_jit_obex_attr_getnames(void *x, long *argc, t_symbol ***argv); 00117 00118 static t_symbol *ps_usercanset,*ps_usercanget,*ps_importattrs,*ps_exportattrs,*ps_exportsummary; 00119 static t_symbol *ps_attr_modified,*ps__Box,*ps_dumpout; 00120 static t_symbol *ps_int,*ps_float; 00121 static t_symbol *ps_attrindex,*ps_getmethodtype,*ps_attributes,*ps_objectname; 00122 static t_symbol *ps_matrixinputcount,*ps_matrixinput,*ps_inmode; 00123 static t_symbol *ps_gettypes,*ps_matrixoutputcount,*ps_matrixoutput; 00124 static t_symbol *ps_array,*ps_message; 00125 static t_symbol *_max_jit_ignorelist[256]; 00126 static long _max_jit_ignorecount = 0; 00127 00128 #if TARGET_RT_MAC_MACHO 00129 extern long initialize(); 00130 #endif 00131 00132 void jit_max_init(void) 00133 { 00134 ps_usercanset = gensym("usercanset"); 00135 ps_usercanget = gensym("usercanget"); 00136 ps_importattrs = gensym("importattrs"); 00137 ps_exportattrs = gensym("exportattrs"); 00138 ps_exportsummary = gensym("exportsummary"); 00139 00140 ps_attr_modified = gensym("attr_modified"); 00141 ps__Box = gensym("#B"); 00142 ps_dumpout = gensym("dumpout"); 00143 ps_int = gensym("int"); 00144 ps_float = gensym("float"); 00145 00146 ps_attrindex = gensym("attrindex"); 00147 ps_getmethodtype = gensym("getmethodtype"); 00148 ps_attributes = gensym("attributes"); 00149 ps_objectname = gensym("objectname"); 00150 ps_matrixinputcount = gensym("matrixinputcount"); 00151 ps_matrixinput = gensym("matrixinput"); 00152 ps_inmode = gensym("inmode"); 00153 00154 ps_gettypes = gensym("gettypes"); 00155 ps_matrixoutputcount = gensym("matrixoutputcount"); 00156 ps_matrixoutput = gensym("matrixoutput"); 00157 00158 ps_array = gensym("array"); 00159 ps_message = gensym("message"); 00160 00161 _max_jit_ignorecount = 0; 00162 _max_jit_ignorelist[_max_jit_ignorecount++] = ps_importattrs; 00163 _max_jit_ignorelist[_max_jit_ignorecount++] = ps_exportattrs; 00164 _max_jit_ignorelist[_max_jit_ignorecount++] = ps_exportsummary; 00165 00166 jit_usurp_init(); 00167 proxy_compat_init; 00168 } 00169 00170 void jit_usurp_init(void) 00171 { 00172 _jit_usurp_class = jit_class_new("jit_usurp",(method)jit_usurp_new,(method)jit_usurp_free, 00173 sizeof(t_jit_usurp),A_CANT,0L); 00174 00175 if (!_jit_usurp_class) post("couldn't allocate memory for class jit_usurp"); 00176 00177 jit_class_addmethod(_jit_usurp_class, (method)jit_usurp_method, "usurp_method", A_CANT, 0L); 00178 jit_class_register(_jit_usurp_class); 00179 } 00180 00181 void *jit_usurp_new(void *parent, method m, t_symbol *s, long flags) 00182 { 00183 t_jit_usurp *x; 00184 00185 if (x=(t_jit_usurp *)jit_object_alloc(_jit_usurp_class)) { 00186 x->parent = parent; 00187 x->m = m; 00188 x->sym = s; 00189 x->flags = flags; 00190 x->qelem = qelem_new(x,(method)max_jit_usurp_qfn); 00191 x->argc = 0; 00192 x->argv = NULL; 00193 } 00194 00195 return x; 00196 } 00197 00198 void jit_usurp_free(t_jit_usurp *x) 00199 { 00200 if (x) { 00201 if (x->qelem) qelem_free(x->qelem); 00202 if (x->argc&&x->argv) jit_freebytes(x->argv,sizeof(t_atom)*x->argc); 00203 } 00204 } 00205 00206 void jit_usurp_method(t_jit_usurp *u, t_symbol *s, short argc, t_atom *argv) 00207 { 00208 if (u) { 00209 long i; 00210 00211 //copy args, replacing 00212 jit_global_critical_enter(); 00213 if (argc&&argv) { 00214 if ((argc==u->argc)&&u->argv) { //use existing memory 00215 for (i=0;i<argc;i++) { 00216 u->argv[i] = argv[i]; 00217 } 00218 } else { 00219 if (u->argc&&u->argv) 00220 jit_freebytes(u->argv,sizeof(t_atom)*u->argc); 00221 if (u->argv=jit_getbytes(sizeof(t_atom)*argc)) { 00222 u->argc = argc; 00223 for (i=0;i<argc;i++) { 00224 u->argv[i] = argv[i]; 00225 } 00226 } else { 00227 u->argc = 0; 00228 } 00229 } 00230 } else { 00231 if (u->argc&&u->argv) 00232 jit_freebytes(u->argv,sizeof(t_atom)*u->argc); 00233 u->argc = 0; 00234 u->argv = NULL; 00235 } 00236 00237 if (max_jit_getqueuestate()==0) { 00238 if (u->flags&JIT_USURP_FLAGS_LOW) qelem_set(u->qelem); 00239 else qelem_front(u->qelem); 00240 jit_global_critical_exit(); 00241 } else { 00242 jit_global_critical_exit(); 00243 max_jit_usurp_qfn(u); 00244 //qelem_unset(u->qelem); moved into usurp_qfn 00245 } 00246 } 00247 return; 00248 } 00249 00250 long jit_usurp_symcompare(t_jit_usurp *x, t_symbol *name) 00251 { 00252 return (name&&(x->sym==name)); 00253 } 00254 00255 #pragma mark - 00256 // -------------------------------------------------------------------------------- 00257 // 00258 00259 long max_jit_queuestate(long state) 00260 { 00261 long rv=_max_jit_queuestate; 00262 00263 _max_jit_queuestate = (state!=0); 00264 00265 return rv; 00266 } 00267 00268 long max_jit_getqueuestate(void) 00269 { 00270 static char *p_max_preempt = NULL; 00271 00272 if (p_max_preempt == NULL) 00273 { 00274 t_object *max = gensym("max")->s_thing; 00275 t_class *mclass = object_class(max); 00276 t_object *attr = class_attr_get(mclass,gensym("overdrive")); 00277 p_max_preempt = (char *)object_attr_getobj(attr,gensym("optionpointer")); 00278 //post("p_max_preempt is %x, and set to %d",p_max_preempt,p_max_preempt?*p_max_preempt:0); 00279 } 00280 00281 // always return true if faking 00282 if (_max_jit_queuestate) return 1; 00283 00284 // move execution to the queue even if overdrive is off 00285 if (p_max_preempt&&(!(*p_max_preempt))) 00286 return !sched_isinpoll(); 00287 else 00288 return systhread_ismainthread(); 00289 } 00290 00291 #pragma mark - 00292 // -------------------------------------------------------------------------------- 00293 // 00294 00295 /** 00296 * Sets attribute value. 00297 * 00298 * @ingroup maxwrapmod 00299 * 00300 * @param x Max wrapper object pointer 00301 * @param s attribute name 00302 * @param ac atom count 00303 * @param av atom vector 00304 * 00305 */ 00306 void max_jit_attr_set(void *x, t_symbol *s, short ac, t_atom *av) 00307 { 00308 t_jit_object *o = max_jit_obex_jitob_get(x); 00309 t_box *b; 00310 void *attr; 00311 00312 jit_object_method(o,s,ac,av); 00313 if (attr = object_attr_get(o,s)) { 00314 object_notify(x, ps_attr_modified, attr); 00315 00316 /* 00317 // jb removed; this is redundant and already handled in object_notify() 00318 if ((b = max_jit_obex_box_get(x)) && ((void *)b != x)) { 00319 object_notify(b, ps_attr_modified, object_attr_get(o,s)); 00320 } 00321 */ 00322 } 00323 } 00324 00325 00326 /** 00327 * Retrieves attribute value. 00328 * 00329 * @ingroup maxwrapmod 00330 * 00331 * @param x Max wrapper object pointer 00332 * @param s attribute name 00333 * @param ac pointer atom count 00334 * @param av pointer atom vector 00335 * 00336 * @return t_jit_err error code 00337 * 00338 */ 00339 t_jit_err max_jit_attr_get(void *x, t_symbol *s, long *ac, t_atom **av) 00340 { 00341 t_jit_err err; 00342 char tmpstr[256]; 00343 00344 sprintf(tmpstr,"%s%s","get",s->s_name); //add get 00345 jit_object_method(max_jit_obex_jitob_get(x),gensym(tmpstr),ac,av); 00346 00347 return JIT_ERR_NONE; 00348 } 00349 00350 /** 00351 * Retrieves attribute value and sends out dump outlet. 00352 * 00353 * @ingroup maxwrapmod 00354 * 00355 * @param x Max wrapper object pointer 00356 * @param s attribute name 00357 * @param argc argument count (ignored) 00358 * @param argv argument vector (ignored) 00359 * 00360 */ 00361 void max_jit_attr_getdump(void *x, t_symbol *s, short argc, t_atom *argv) 00362 { 00363 long ac=0; 00364 t_atom *av=NULL; 00365 method f; 00366 t_jit_err err; 00367 00368 s = gensym(s->s_name+3); //strip get 00369 if ((err = max_jit_attr_get(x,s,&ac,&av))) { 00370 jit_error_code(x, err); 00371 } else { 00372 if (f=zgetfn(x,ps_dumpout)) 00373 (*f)(x,s,(short)ac,av); 00374 } 00375 freebytes(av,sizeof(t_atom)*ac); 00376 } 00377 00378 /** 00379 * Determines argument offset to first attribute argument. 00380 * 00381 * @ingroup maxwrapmod 00382 * 00383 * @param ac argument count 00384 * @param av argument vector 00385 * 00386 * @return argument offset 00387 * 00388 */ 00389 long max_jit_attr_args_offset(short ac, t_atom *av) 00390 { 00391 long i,offset=ac;//no args 00392 00393 if (av) { 00394 for (i=0;i<ac;i++) { 00395 if ((av[i].a_type==A_SYM)&&(av[i].a_w.w_sym->s_name[0]=='@')) { 00396 offset=i; 00397 goto out; 00398 } 00399 } 00400 } 00401 out: 00402 return offset; 00403 } 00404 00405 /** 00406 * Processes attribtue arguments. 00407 * 00408 * @ingroup maxwrapmod 00409 * 00410 * @param x Max wrapper object pointer 00411 * @param ac argument count 00412 * @param av argument vector 00413 * 00414 */ 00415 void max_jit_attr_args(void *x, short ac, t_atom *av) 00416 { 00417 t_symbol *s,*s2 = _jit_sym_nothing,*as; 00418 long i,j; 00419 void *o; 00420 00421 if (av) { //find first 00422 for (i=0;i<ac;i++) { 00423 if ((av[i].a_type==A_SYM)&&((s=av[i].a_w.w_sym)->s_name[0]=='@')) { 00424 s = gensym(s->s_name+1); 00425 i++; 00426 goto pikka; 00427 } 00428 } 00429 pikka: 00430 j = i; 00431 while (j<ac) { 00432 for (;j<ac;j++) { 00433 if ((av[j].a_type==A_SYM)&&((s2=av[j].a_w.w_sym)->s_name[0]=='@')) { 00434 s2 = gensym(s2->s_name+1); 00435 goto pakka; 00436 } 00437 } 00438 pakka: 00439 //try max object first, then jit object if it is a wrapper 00440 o=max_jit_obex_jitob_get(x); 00441 if (max_jit_obex_attr_usercanset(x,s)) { 00442 max_jit_obex_attr_method_direct(x,s,j-i,av+i); 00443 } else if (o&&jit_object_attr_usercanset(o,s)) { 00444 jit_object_method(o,s,j-i,av+i); 00445 } else if (o&&(as=jit_object_method_argsafe_get(o,s))) { 00446 object_method_typed(o,as,j-i,av+i,NULL); 00447 } else if (s==ps_attrindex) { 00448 max_jit_attrindex(x,s,j-i,av+i); 00449 } else { 00450 jit_object_error((t_object *)x,"%s: \"%s\" is not a valid attribute argument",ob_name(x),s->s_name); 00451 } 00452 00453 i = ++j; 00454 s = s2; 00455 } 00456 } 00457 } 00458 00459 #pragma mark - 00460 // -------------------------------------------------------------------------------- 00461 // 00462 00463 void max_jit_defer_method(void *x, t_symbol *s, short argc, t_atom *argv) 00464 { 00465 //x is a max object ptr 00466 defer(x,(method)max_jit_defer_method_doit,s,argc,argv); 00467 } 00468 00469 void max_jit_defer_low_method(void *x, t_symbol *s, short argc, t_atom *argv) 00470 { 00471 //x is a max object ptr 00472 if (max_jit_getqueuestate()==0) 00473 defer_low(x,(method)max_jit_defer_method_doit,s,argc,argv); 00474 else 00475 max_jit_defer_method_doit(x,s,argc,argv); 00476 } 00477 00478 void max_jit_defer_method_doit(void *x, t_symbol *s, short argc, t_atom *argv) 00479 { 00480 t_jit_object *o; 00481 00482 //x is a max object ptr 00483 if (x&&(o=max_jit_obex_jitob_get(x))) { 00484 jit_object_method(o,s,s,(long)argc,argv); 00485 } 00486 } 00487 00488 void max_jit_gimme_method(void *x, t_symbol *s, short argc, t_atom *argv) 00489 { 00490 t_jit_object *o; 00491 //x is a max object ptr 00492 //drat this is not as fast as it could be. won't be as fast for jit_vector 00493 //need to look into a different caching solution 00494 if (x&&(o=max_jit_obex_jitob_get(x))) { 00495 jit_object_method(o,s,s,(long)argc,argv); 00496 } 00497 } 00498 00499 void max_jit_typed_method(void *x, t_symbol *s, short argc, t_atom *argv) 00500 { 00501 t_jit_object *o; 00502 00503 //x is a max object ptr 00504 if (x&&(o=max_jit_obex_jitob_get(x))) { 00505 typedmess(o,s,argc,argv); 00506 } 00507 } 00508 00509 void max_jit_usurp_method(void *x, t_symbol *s, short argc, t_atom *argv) 00510 { 00511 t_jit_usurp *u=NULL; 00512 long i,savelock; 00513 extern char inISR; 00514 t_jit_linklist *usurplist; 00515 00516 //x is a max object ptr 00517 if (x&&(usurplist=max_jit_obex_usurplist_get(x))) { 00518 jit_linklist_findfirst(usurplist,(void **)&u,(t_cmpfn)jit_usurp_symcompare,s); 00519 if (u) { 00520 jit_usurp_method(u, s, argc, argv); 00521 } 00522 } 00523 return; 00524 } 00525 00526 void max_jit_usurp_qfn(void *x) 00527 { 00528 t_jit_usurp *u=x; 00529 long argc,savelock,i; 00530 t_atom *argv; 00531 00532 jit_global_critical_enter(); 00533 argc = u->argc; 00534 argv = u->argv; 00535 u->argc = 0; 00536 u->argv = NULL; 00537 //unset incase this was set in the instant between sched dequeue loops 00538 qelem_unset(u->qelem); 00539 jit_global_critical_exit(); 00540 if (u->flags&JIT_USURP_FLAGS_MAX) 00541 (*(u->m))(u->parent,u->sym,argc,argv); 00542 else 00543 (*(u->m))(max_jit_obex_jitob_get(u->parent),u->sym,argc,argv); 00544 00545 if (argc&&argv) 00546 jit_freebytes(argv,sizeof(t_atom)*argc); 00547 } 00548 00549 // could move to another place if needed anywhere else 00550 t_jit_err jit_class_attr_getnames(t_jit_class *x,long *symcount,t_symbol ***symarray); 00551 t_jit_err jit_class_attr_getnames(t_jit_class *x,long *symcount,t_symbol ***symarray) 00552 { 00553 t_jit_err err=JIT_ERR_GENERIC; 00554 if (x&&((t_jit_class *)x)->c_attributes) { 00555 if (!hashtab_getkeys((t_hashtab *)x->c_attributes,symcount,symarray)) 00556 err = JIT_ERR_NONE; 00557 } 00558 return err; 00559 } 00560 00561 void max_jit_class_attrlist2methods(void *x) 00562 { 00563 long i; 00564 void *o; 00565 method m; 00566 t_symbol *s; 00567 char tmpstr[256]; 00568 long type; 00569 long symcount=0; 00570 t_symbol **symarray=NULL; 00571 00572 //x is a t_jit_class ptr 00573 if (!x) 00574 return; 00575 00576 jit_class_attr_getnames(x,&symcount,&symarray); 00577 00578 if (symcount) { 00579 //symbolarray_sort(symcount,symarray); 00580 for (i=0;i<symcount;i++) { 00581 o=class_attr_get(x,symarray[i]); 00582 s = jit_object_method(o,_jit_sym_getname); 00583 if (jit_object_method(o,ps_usercanset)) { 00584 m = jit_object_method(o,_jit_sym_getmethod,_jit_sym_set); 00585 type = (long) jit_object_method(o,ps_getmethodtype,_jit_sym_set); 00586 switch (type) { 00587 case A_DEFER: 00588 max_addmethod_defer((method)max_jit_attr_set, s->s_name); 00589 break; 00590 case A_DEFER_LOW: 00591 max_addmethod_defer_low((method)max_jit_attr_set, s->s_name); 00592 break; 00593 case A_USURP: 00594 max_addmethod_usurp((method)max_jit_attr_set, s->s_name); 00595 break; 00596 case A_USURP_LOW: 00597 max_addmethod_usurp_low((method)max_jit_attr_set, s->s_name); 00598 break; 00599 case A_GIMME: 00600 addmess((method)max_jit_attr_set, s->s_name, A_GIMME, 0); 00601 break; 00602 } 00603 } 00604 if (jit_object_method(o,ps_usercanget)) { 00605 m = jit_object_method(o,_jit_sym_getmethod,_jit_sym_get); 00606 type = (long) jit_object_method(o,ps_getmethodtype,_jit_sym_get); 00607 sprintf(tmpstr,"%s%s","get",s->s_name); 00608 switch (type) { 00609 case A_DEFER: 00610 max_addmethod_defer((method)max_jit_attr_getdump, tmpstr); 00611 break; 00612 case A_DEFER_LOW: 00613 max_addmethod_defer_low((method)max_jit_attr_getdump, tmpstr); 00614 break; 00615 case A_USURP: 00616 max_addmethod_usurp((method)max_jit_attr_getdump, tmpstr); 00617 break; 00618 case A_USURP_LOW: 00619 max_addmethod_usurp_low((method)max_jit_attr_getdump, tmpstr); 00620 break; 00621 case A_GIMME: 00622 addmess((method)max_jit_attr_getdump, tmpstr, A_GIMME, 0); 00623 break; 00624 } 00625 } 00626 } 00627 if (symarray) 00628 freebytes((char *)symarray,symcount*sizeof(t_symbol *)); 00629 } 00630 } 00631 00632 void max_jit_class_addmethods(void *x) 00633 { 00634 t_messlist *m; 00635 t_symbol *s; 00636 long type,i,ignore; 00637 00638 //x is a t_jit_class ptr 00639 if (x) { 00640 m = (((t_jit_class *)x)->c_messlist)+1; 00641 while (m->m_sym){ 00642 ignore = FALSE; 00643 for (i=0;!ignore&&i<_max_jit_ignorecount;i++) { 00644 if (m->m_sym==_max_jit_ignorelist[i]) 00645 ignore = TRUE; 00646 } 00647 if (!ignore) { 00648 type = m->m_type[0]; 00649 switch (type) { 00650 case A_CANT: 00651 break; 00652 case A_DEFER: 00653 addmess((method)max_jit_defer_method, m->m_sym->s_name, A_GIMME, 0); 00654 break; 00655 case A_DEFER_LOW: 00656 addmess((method)max_jit_defer_low_method, m->m_sym->s_name, A_GIMME, 0); 00657 break; 00658 case A_USURP: 00659 addmess((method)max_jit_usurp_method, m->m_sym->s_name, A_GIMME, 0); 00660 break; 00661 case A_USURP_LOW: 00662 addmess((method)max_jit_usurp_method, m->m_sym->s_name, A_GIMME, 0); 00663 break; 00664 case A_GIMME: 00665 addmess((method)max_jit_gimme_method, m->m_sym->s_name, A_GIMME, 0); 00666 break; 00667 default: 00668 addmess((method)max_jit_typed_method, m->m_sym->s_name, A_GIMME, 0); 00669 break; 00670 } 00671 } 00672 m++; 00673 } 00674 max_jit_class_attrlist2methods(x); 00675 } 00676 } 00677 00678 /** 00679 * Adds standard Jitter methods, as well as public methods and attributes of the specified Jitter class. 00680 * This includes the following public methods: getattributes, getstate, summary, 00681 * importattrs, exportattrs; and the following private methods: dumpout, quickref, 00682 * attr_getnames, attr_get, attr_gettarget, and attrindex. 00683 * 00684 * @ingroup maxwrapmod 00685 * 00686 * @param mclass Max wrapper class pointer 00687 * @param jclass jitter class pointer 00688 * @param flags reserved for future use (currently ignored) 00689 * 00690 */ 00691 void max_jit_classex_standard_wrap(void *mclass, void *jclass, long flags) 00692 { 00693 if (jclass) 00694 max_jit_class_addmethods(jclass); 00695 max_addmethod_defer_low((method)max_jit_object_attr_dump, "getattributes"); 00696 max_addmethod_defer_low((method)max_jit_object_state_dump, "getstate"); 00697 max_addmethod_defer_low((method)max_jit_object_summary, "summary"); 00698 max_addmethod_defer_low((method)jit_object_importattrs, "importattrs"); 00699 max_addmethod_defer_low((method)jit_object_exportattrs, "exportattrs"); 00700 max_addmethod_defer_low((method)jit_object_exportsummary, "exportsummary"); 00701 00702 addmess((method)max_jit_obex_dumpout, "dumpout", A_CANT,0); 00703 addmess((method)max_jit_object_quickref, "quickref", A_CANT,0); 00704 addmess((method)max_jit_obex_attr_getnames, "attr_getnames", A_CANT,0); 00705 addmess((method)max_jit_obex_attr_getobject, "attr_get", A_CANT,0); 00706 addmess((method)max_jit_obex_attr_gettarget, "attr_gettarget", A_CANT,0); 00707 addmess((method)max_jit_attrindex, "attrindex", A_CANT,0); 00708 00709 } 00710 00711 void max_jit_attrindex(void *x, t_symbol *s, long argc, t_atom *argv) 00712 { 00713 t_atom *av=NULL,*av2=NULL; 00714 long i,ac=0; 00715 t_symbol *attrname=_jit_sym_nothing; 00716 long index=0; 00717 t_atom val; 00718 00719 jit_atom_arg_getsym(&attrname,0,argc,argv); 00720 jit_atom_arg_getlong(&index,1,argc,argv); 00721 if (argc>2) 00722 val = argv[2]; 00723 else 00724 jit_atom_setlong(&val,0); 00725 00726 if (max_jit_obex_attr_get(x,attrname,&ac,&av)) { 00727 if (max_jit_attr_get(x,attrname,&ac,&av)) 00728 goto out; 00729 } 00730 if (index>(ac-1)) { 00731 //allocate new args to increase size, padding with zeros? 00732 av2=jit_getbytes(sizeof(t_atom)*index+1); 00733 for (i=0;i<ac;i++) 00734 av2[i] = av[i]; 00735 for (;i<index+1;i++) 00736 jit_atom_setlong(av+i,0); 00737 if (ac&&av) 00738 jit_freebytes(av,sizeof(t_atom)*ac); 00739 ac = index+1; 00740 av = av2; 00741 } 00742 if (ac&&av) 00743 av[index] = val; 00744 typedmess(x,attrname,ac,av); 00745 out: 00746 if (ac&&av) 00747 jit_freebytes(av,sizeof(t_atom)*ac); 00748 } 00749 00750 //some functions for adding usurp stuff to max(not jit) objects(sort of a hack) 00751 void max_defer_method(void *x, t_symbol *s, long argc, t_atom *argv) 00752 { 00753 char tmpstr[256]; 00754 method m; 00755 00756 sprintf(tmpstr,"%s_defer",s->s_name); 00757 if (m=zgetfn(x,gensym(tmpstr))) defer(x,(method)m,s,argc,argv); 00758 // else jit_object_error((t_object *)x,"%s: defer method not present", ob_sym(x)->s_name); 00759 } 00760 00761 /** 00762 * Adds method to Max class that calls defer rather than the method directly. 00763 * To prevent sequencing problems which arize through the use of defer, rather than defer_low, 00764 * you should instead use the max_addmethod_defer_low function. 00765 * 00766 * @ingroup maxwrapmod 00767 * 00768 * @param m method (function pointer) 00769 * @param s method name 00770 * 00771 */ 00772 void max_addmethod_defer(method m, char *s) 00773 { 00774 char tmpstr[256]; 00775 00776 sprintf(tmpstr,"%s_defer",s); 00777 addmess((method)max_defer_method, s, A_GIMME, 0); 00778 addmess((method)m, tmpstr, A_CANT, 0); 00779 } 00780 00781 void max_defer_low_method(void *x, t_symbol *s, long argc, t_atom *argv) 00782 { 00783 char tmpstr[256]; 00784 method m; 00785 00786 sprintf(tmpstr,"%s_defer",s->s_name); 00787 if (m=zgetfn(x,gensym(tmpstr))) { 00788 if (max_jit_getqueuestate()==0) 00789 defer_low(x,(method)m,s,argc,argv); 00790 else 00791 (*m)(x,s,argc,argv); 00792 } 00793 //else jit_object_error((t_object *)x,"%s: defer method not present", ob_sym(x)->s_name); 00794 } 00795 00796 /** 00797 * Adds method to Max class that calls defer_low rather than the method directly. 00798 * 00799 * @ingroup maxwrapmod 00800 * 00801 * @param m method (function pointer) 00802 * @param s method name 00803 * 00804 */ 00805 void max_addmethod_defer_low(method m, char *s) 00806 { 00807 char tmpstr[256]; 00808 00809 sprintf(tmpstr,"%s_defer",s); 00810 addmess((method)max_defer_low_method, s, A_GIMME, 0); 00811 addmess((method)m, tmpstr, A_CANT, 0); 00812 } 00813 00814 /** 00815 * Adds method to Max class that uses the usurp mechanism to execute method at low priority without backlog. 00816 * Equivalent to max_addmethod_usurp_low function. 00817 * 00818 * @ingroup maxwrapmod 00819 * 00820 * @param m method (function pointer) 00821 * @param s method name 00822 * 00823 */ 00824 void max_addmethod_usurp(method m, char *s) 00825 { 00826 char tmpstr[256]; 00827 00828 sprintf(tmpstr,"%s_usurp",s); 00829 addmess((method)max_jit_usurp_method, s, A_GIMME, 0); 00830 addmess((method)m, tmpstr, A_CANT, 0); 00831 } 00832 00833 /** 00834 * Adds method to Max class that uses the usurp mechanism to execute method at low priority without backlog. 00835 * 00836 * @ingroup maxwrapmod 00837 * 00838 * @param m method (function pointer) 00839 * @param s method name 00840 * 00841 */ 00842 void max_addmethod_usurp_low(method m, char *s) 00843 { 00844 char tmpstr[256]; 00845 00846 sprintf(tmpstr,"%s_usurp_low",s); 00847 addmess((method)max_jit_usurp_method, s, A_GIMME, 0); 00848 addmess((method)m, tmpstr, A_CANT, 0); 00849 } 00850 00851 void max_jit_object_attr_dump(void *x) 00852 { 00853 t_jit_linklist *attrlist; 00854 short size,i,j = 0; 00855 t_symbol *name; 00856 t_jit_object *o,*jitob; 00857 t_atom a[256]; 00858 method f; 00859 long symcount=0; 00860 t_symbol **symarray=NULL; 00861 00862 if (!x) 00863 return; 00864 00865 if (attrlist = max_jit_obex_attrlist_get(x)){ 00866 size = (long) jit_object_method(attrlist,_jit_sym_getsize); 00867 for (i=0;i<size;i++) { 00868 if (o=jit_object_method(attrlist,_jit_sym_getindex,i)) { 00869 00870 if (jit_object_method(o,ps_usercanset) || 00871 jit_object_method(o,ps_usercanget)) 00872 { 00873 if (name = jit_object_method(o,_jit_sym_getname)) { 00874 a[j].a_type = A_SYM; 00875 a[j].a_w.w_sym = name; 00876 j++; 00877 } 00878 } 00879 } 00880 } 00881 } 00882 jitob = max_jit_obex_jitob_get(x); 00883 if (jitob&&!object_attr_getnames(jitob,&symcount,&symarray)) 00884 { 00885 symbolarray_sort(symcount,symarray); 00886 for (i=0;i<symcount;i++) { 00887 if (o=object_attr_get(jitob,symarray[i])) { 00888 if (jit_object_method(o,ps_usercanset) || 00889 jit_object_method(o,ps_usercanget)) 00890 { 00891 if (name = jit_object_method(o,_jit_sym_getname)) { 00892 a[j].a_type = A_SYM; 00893 a[j].a_w.w_sym = name; 00894 j++; 00895 } 00896 } 00897 } 00898 } 00899 } 00900 if (symarray) 00901 freebytes((char *)symarray,symcount*sizeof(t_symbol *)); 00902 00903 max_jit_obex_dumpout(x, ps_attributes, j, a); 00904 } 00905 00906 void max_jit_object_state_dump(void *x) 00907 { 00908 t_jit_linklist *attrlist; 00909 short size,i; 00910 t_symbol *name; 00911 t_jit_object *o,*jitob; 00912 t_atom *av = NULL; 00913 long ac = 0; 00914 long symcount=0; 00915 t_symbol **symarray=NULL; 00916 00917 if (attrlist = max_jit_obex_attrlist_get(x)){ 00918 size = (long) jit_object_method(attrlist,_jit_sym_getsize); 00919 for (i=0;i<size;i++) { 00920 if (o=jit_object_method(attrlist,_jit_sym_getindex,i)) { 00921 00922 if (jit_object_method(o,ps_usercanget)) { 00923 if (name = jit_object_method(o,_jit_sym_getname)) { 00924 max_jit_obex_attr_get(x,name,&ac,&av); 00925 max_jit_obex_dumpout(x,name,ac,av); 00926 freebytes(av,sizeof(t_atom)*ac); 00927 ac=0;av=NULL; 00928 } 00929 } 00930 } 00931 } 00932 } 00933 jitob = max_jit_obex_jitob_get(x); 00934 if (jitob&&!object_attr_getnames(jitob,&symcount,&symarray)) 00935 { 00936 symbolarray_sort(symcount,symarray); 00937 for (i=0;i<symcount;i++) { 00938 if (o=object_attr_get(jitob,symarray[i])) { 00939 if (jit_object_method(o,ps_usercanget)) { 00940 if (name = jit_object_method(o,_jit_sym_getname)) { 00941 max_jit_attr_get(x,name,&ac,&av); 00942 max_jit_obex_dumpout(x,name,ac,av); 00943 freebytes(av,sizeof(t_atom)*ac); 00944 ac=0;av=NULL; 00945 } 00946 } 00947 } 00948 } 00949 } 00950 if (symarray) 00951 freebytes((char *)symarray,symcount*sizeof(t_symbol *)); 00952 } 00953 00954 t_symbol *jit2maxtype(t_symbol *s); 00955 t_symbol *jit2maxtype(t_symbol *s) 00956 { 00957 if (s==_jit_sym_char) { 00958 return ps_int; 00959 } else if (s==_jit_sym_long) { 00960 return ps_int; 00961 } else if (s==_jit_sym_float32) { 00962 return ps_float; 00963 } else if (s==_jit_sym_float64) { 00964 return ps_float; 00965 } else { 00966 return s; 00967 } 00968 } 00969 00970 long max_jit_method_is_attr(void *x, t_symbol *s) 00971 { 00972 t_jit_linklist *attrlist; 00973 t_jit_object *attr,*o; 00974 00975 if (x) { 00976 if ((s->s_name[0]=='g')&& 00977 (s->s_name[1]=='e')&& 00978 (s->s_name[2]=='t')) 00979 { 00980 s = gensym(s->s_name+3); //strip get 00981 if (attrlist=max_jit_obex_attrlist_get(x)) { 00982 jit_linklist_findfirst(attrlist,(void **)&attr,(t_cmpfn)jit_attr_symcompare,s); 00983 if (attr) return TRUE; 00984 } 00985 if ((o=max_jit_obex_jitob_get(x))&&(attr=jit_object_attr_get(o,s))) { 00986 return TRUE; 00987 } 00988 } else { 00989 if (attrlist=max_jit_obex_attrlist_get(x)) { 00990 jit_linklist_findfirst(attrlist,(void **)&attr,(t_cmpfn)jit_attr_symcompare,s); 00991 if (attr) return TRUE; 00992 } 00993 if ((o=max_jit_obex_jitob_get(x))&&(attr=jit_object_attr_get(o,s))) { 00994 return TRUE; 00995 } 00996 } 00997 } 00998 return FALSE; 00999 } 01000 01001 void max_jit_object_summary(void *x, t_symbol *s) 01002 { 01003 t_jit_linklist *attrlist; 01004 short size,i,j; 01005 t_symbol *tmpsym; 01006 t_jit_object *o,*jitob; 01007 t_atom a[256],*av; 01008 long ac,ac2=0; 01009 t_jit_class *jclass; 01010 t_messlist *mess; 01011 void *mop,*ioproc; 01012 long inputcount,outputcount; 01013 long symcount=0; 01014 t_symbol **symarray=NULL; 01015 01016 //object name 01017 ac = 2; 01018 jit_atom_setsym(a,ps_objectname); 01019 jit_atom_setsym(a+1,ob_sym(x)); 01020 max_jit_obex_dumpout(x,s,ac,a); 01021 01022 jclass = jit_object_class(max_jit_obex_jitob_get(x)); 01023 01024 //mop info 01025 if (jclass&&(mop=jit_class_adornment_get(jclass,_jit_sym_jit_mop))) { 01026 ac = 2; 01027 jit_atom_setsym(a,ps_matrixinputcount); 01028 jit_atom_setlong(a+1,inputcount=jit_attr_getlong(mop,_jit_sym_inputcount)); 01029 max_jit_obex_dumpout(x,s,ac,a); 01030 if (inputcount>=2) { 01031 for (i=2;i<=inputcount;i++) { 01032 if (o=jit_object_method(mop,_jit_sym_getinput,i)) { 01033 ac = 11; 01034 jit_atom_setsym(a,ps_matrixinput); 01035 jit_atom_setsym(a+1,jit_attr_getsym(o,_jit_sym_ioname)); 01036 jit_atom_setsym(a+2,_jit_sym_planelink); 01037 jit_atom_setlong(a+3,jit_attr_getlong(o,_jit_sym_planelink)); 01038 jit_atom_setsym(a+4,_jit_sym_typelink); 01039 jit_atom_setlong(a+5,jit_attr_getlong(o,_jit_sym_typelink)); 01040 jit_atom_setsym(a+6,_jit_sym_dimlink); 01041 jit_atom_setlong(a+7,jit_attr_getlong(o,_jit_sym_dimlink)); 01042 jit_atom_setsym(a+8,ps_inmode); 01043 ioproc = jit_object_method(o,_jit_sym_getioproc); 01044 tmpsym = jit_mop_ioproc_tosym(ioproc); 01045 jit_atom_setsym(a+9,tmpsym); 01046 jit_atom_setsym(a+10,_jit_sym_types); 01047 jit_object_method(o,ps_gettypes,&ac2,&av); 01048 for (j=0;j<ac2;j++) { 01049 *(a+11+j) = av[j]; 01050 } 01051 ac += ac2; 01052 max_jit_obex_dumpout(x,s,ac,a); 01053 freebytes(av,sizeof(t_atom)*ac2); 01054 ac2=0;av=NULL; 01055 } 01056 } 01057 } 01058 ac = 2; 01059 jit_atom_setsym(a,ps_matrixoutputcount); 01060 jit_atom_setlong(a+1,outputcount=jit_attr_getlong(mop,_jit_sym_outputcount)); 01061 max_jit_obex_dumpout(x,s,ac,a); 01062 if (outputcount>=1) { 01063 for (i=1;i<=outputcount;i++) { 01064 if (o=jit_object_method(mop,_jit_sym_getoutput,i)) { 01065 ac = 9; 01066 jit_atom_setsym(a,ps_matrixoutput); 01067 jit_atom_setsym(a+1,jit_attr_getsym(o,_jit_sym_ioname)); 01068 jit_atom_setsym(a+2,_jit_sym_planelink); 01069 jit_atom_setlong(a+3,jit_attr_getlong(o,_jit_sym_planelink)); 01070 jit_atom_setsym(a+4,_jit_sym_typelink); 01071 jit_atom_setlong(a+5,jit_attr_getlong(o,_jit_sym_typelink)); 01072 jit_atom_setsym(a+6,_jit_sym_dimlink); 01073 jit_atom_setlong(a+7,jit_attr_getlong(o,_jit_sym_dimlink)); 01074 jit_object_method(o,ps_gettypes,&ac2,&av); 01075 jit_atom_setsym(a+8,_jit_sym_types); 01076 for (j=0;j<ac2;j++) { 01077 *(a+9+j) = av[j]; 01078 } 01079 ac += ac2; 01080 max_jit_obex_dumpout(x,s,ac,a); 01081 freebytes(av,sizeof(t_atom)*ac2); 01082 ac2=0;av=NULL; 01083 } 01084 } 01085 } 01086 } 01087 01088 //attributes: 01089 //max object 01090 if (attrlist = max_jit_obex_attrlist_get(x)){ 01091 size = (long) jit_object_method(attrlist,_jit_sym_getsize); 01092 for (i=0;i<size;i++) { 01093 if (o=jit_object_method(attrlist,_jit_sym_getindex,i)) { 01094 if ((long)jit_object_method(o,ps_usercanget)|| 01095 (long)jit_object_method(o,ps_usercanset)) 01096 { 01097 ac = 7; 01098 jit_atom_setsym(a,_jit_sym_jit_attribute); 01099 jit_atom_setsym(a+1,jit_object_method(o,_jit_sym_getname)); 01100 jit_atom_setsym(a+2,_jit_sym_get); 01101 jit_atom_setlong(a+3,(long)jit_object_method(o,ps_usercanget)); 01102 jit_atom_setsym(a+4,_jit_sym_set); 01103 jit_atom_setlong(a+5,(long)jit_object_method(o,ps_usercanset)); 01104 jit_atom_setsym(a+6,jit2maxtype(jit_object_method(o,_jit_sym_gettype))); 01105 if (jit_object_classname(o)==_jit_sym_jit_attr_offset_array) { 01106 jit_atom_setsym(a+7,ps_array); 01107 jit_atom_setlong(a+8,(long)jit_object_method(o,_jit_sym_getsize)); 01108 ac = 9; 01109 } 01110 max_jit_obex_dumpout(x,s,ac,a); 01111 } 01112 } 01113 } 01114 } 01115 //jit object 01116 jitob = max_jit_obex_jitob_get(x); 01117 if (jitob&&!object_attr_getnames(jitob,&symcount,&symarray)) 01118 { 01119 symbolarray_sort(symcount,symarray); 01120 for (i=0;i<symcount;i++) { 01121 if (o=object_attr_get(jitob,symarray[i])) { 01122 if ((long)jit_object_method(o,ps_usercanget)|| 01123 (long)jit_object_method(o,ps_usercanset)) 01124 { 01125 ac = 7; 01126 jit_atom_setsym(a,_jit_sym_jit_attribute); 01127 jit_atom_setsym(a+1,jit_object_method(o,_jit_sym_getname)); 01128 jit_atom_setsym(a+2,_jit_sym_get); 01129 jit_atom_setlong(a+3,(long)jit_object_method(o,ps_usercanget)); 01130 jit_atom_setsym(a+4,_jit_sym_set); 01131 jit_atom_setlong(a+5,(long)jit_object_method(o,ps_usercanset)); 01132 jit_atom_setsym(a+6,jit2maxtype(jit_object_method(o,_jit_sym_gettype))); 01133 if (jit_object_classname(o)==_jit_sym_jit_attr_offset_array) { 01134 jit_atom_setsym(a+7,ps_array); 01135 jit_atom_setlong(a+8,(long)jit_object_method(o,_jit_sym_getsize)); 01136 ac = 9; 01137 } 01138 max_jit_obex_dumpout(x,s,ac,a); 01139 } 01140 } 01141 } 01142 } 01143 if (symarray) 01144 freebytes((char *)symarray,symcount*sizeof(t_symbol *)); 01145 01146 //methods 01147 //max object, but first check if attribute 01148 if (mess = ob_messlist(x)) { 01149 mess++; 01150 while (mess->m_sym) { 01151 if (!max_jit_method_is_attr(x,mess->m_sym)) { 01152 if (mess->m_type[0]!=A_CANT) { 01153 ac = 2; 01154 jit_atom_setsym(a,ps_message); 01155 jit_atom_setsym(a+1,mess->m_sym); 01156 max_jit_obex_dumpout(x,s,ac,a); 01157 } 01158 } 01159 mess++; 01160 } 01161 } 01162 } 01163 01164 01165 static char *messlist_argstring(char *types); 01166 static char *messlist_argstring(char *types) 01167 { 01168 static char args[100]; 01169 short out,i,comma; 01170 01171 if (types[0] == A_NOTHING) { 01172 args[0] = 0; 01173 return (args); 01174 } 01175 args[0] = '['; 01176 out = 1; 01177 for (i=0; types[i]; i++) { 01178 comma = 1; 01179 switch (types[i]) { 01180 case A_LONG: 01181 strcpy(args+out,"int"); 01182 break; 01183 case A_DEFLONG: 01184 strcpy(args+out,"int (0)"); 01185 break; 01186 case A_FLOAT: 01187 strcpy(args+out,"float"); 01188 break; 01189 case A_DEFFLOAT: 01190 strcpy(args+out,"float (0.0)"); 01191 break; 01192 case A_SYM: 01193 case A_DEFSYM: 01194 strcpy(args+out,"symbol"); 01195 break; 01196 case A_GIMME: 01197 strcpy(args+out,"variable"); 01198 break; 01199 default: 01200 comma = 0; 01201 break; 01202 } 01203 out = strlen(args); 01204 if (comma && types[i+1]) { 01205 strcpy(args+out,", "); 01206 out = strlen(args); 01207 } 01208 } 01209 args[out++] = ']'; 01210 args[out] = 0; 01211 return (args); 01212 } 01213 01214 long quickref_symcompare(t_symbol *s1,t_symbol *s2); 01215 long quickref_symcompare(t_symbol *s1,t_symbol *s2) 01216 { 01217 return strcmp(s1->s_name,s2->s_name)<=0; 01218 } 01219 01220 #define QUICKREF_MAXMENU 256 01221 #define QUICKREF_ATTR_VALUE 01222 01223 void max_jit_object_quickref(void *x, long *numitems, t_symbol **items) 01224 { 01225 t_jit_linklist *attrlist; 01226 long size,i,j,canget,canset; 01227 t_symbol *namesym,*typesym; 01228 t_jit_object *o,*jitob; 01229 char s[256],s2[256]; 01230 t_jit_class *jclass; 01231 t_messlist *mess; 01232 t_jit_object *sortlist=NULL; 01233 t_symbol *ps_assist=gensym("assist"); 01234 t_symbol *ps_preset=gensym("preset"); 01235 t_symbol *ps_usercanset=gensym("usercanset"); 01236 t_symbol *ps_usercanget=gensym("usercanget"); 01237 long symcount=0; 01238 t_symbol **symarray=NULL; 01239 01240 jitob = max_jit_obex_jitob_get(x); 01241 jclass = jit_object_class(jitob); 01242 sortlist = jit_object_new(_jit_sym_jit_linklist); 01243 01244 //attributes: 01245 //max object 01246 if (attrlist = max_jit_obex_attrlist_get(x)){ 01247 size = (long) jit_object_method(attrlist,_jit_sym_getsize); 01248 for (i=0;i<size;i++) { 01249 if (o=jit_object_method(attrlist,_jit_sym_getindex,i)) { 01250 canget = (long)jit_object_method(o,ps_usercanget); 01251 canset = (long)jit_object_method(o,ps_usercanset); 01252 if (canget||canset) 01253 { 01254 namesym = jit_object_method(o,_jit_sym_getname); 01255 typesym = jit_object_method(o,_jit_sym_gettype); 01256 sprintf(s," %s [%s",namesym->s_name, typesym->s_name); 01257 if (jit_object_classname(o)==_jit_sym_jit_attr_offset_array) { 01258 sprintf(s2," array[%d]]",(long)jit_object_method(o,_jit_sym_getsize)); 01259 strcat(s,s2); 01260 } else { 01261 strcat(s,"]"); 01262 } 01263 #ifdef QUICKREF_ATTR_VALUE 01264 if (canget) 01265 { 01266 long ac=0,k; 01267 t_atom *av=NULL; 01268 01269 max_jit_obex_attr_get(x,namesym,&ac,&av); 01270 if ((typesym==_jit_sym_long)||(typesym==_jit_sym_char)) { 01271 sprintf(s2," (val ="); 01272 strcat(s,s2); 01273 for (k=0;k<MIN(ac,4);k++) { 01274 sprintf(s2, " %d", jit_atom_getlong(av+k)); 01275 strcat(s,s2); 01276 } 01277 if (ac>4) 01278 strcat(s," ...)"); 01279 else 01280 strcat(s,")"); 01281 } else if ((typesym==_jit_sym_float32)||(typesym==_jit_sym_float64)) { 01282 sprintf(s2," (val ="); 01283 strcat(s,s2); 01284 for (k=0;k<MIN(ac,4);k++) { 01285 sprintf(s2, " %.2f", jit_atom_getfloat(av+k)); 01286 strcat(s,s2); 01287 } 01288 if (ac>4) 01289 strcat(s," ...)"); 01290 else 01291 strcat(s,")"); 01292 } else if (typesym==_jit_sym_symbol) { 01293 t_symbol *tmpsym; 01294 sprintf(s2," (val ="); 01295 strcat(s,s2); 01296 tmpsym = jit_atom_getsym(av); 01297 if (tmpsym==_jit_sym_nothing) 01298 sprintf(s2," <none>"); 01299 else 01300 sprintf(s2," %s",tmpsym->s_name); 01301 strcat(s,s2); 01302 if (ac>1) 01303 strcat(s," ...)"); 01304 else 01305 strcat(s,")"); 01306 } 01307 freebytes(av,sizeof(t_atom)*ac); 01308 } 01309 #endif 01310 if (!(canget&&canset)) { 01311 if (canset) 01312 strcat(s," (set)"); 01313 else 01314 strcat(s," (get)"); 01315 } 01316 jit_object_method(sortlist,_jit_sym_append,gensym(s)); //hack, this is a symbol not an object 01317 } 01318 } 01319 } 01320 } 01321 //jit object 01322 if (jitob&&!object_attr_getnames(jitob,&symcount,&symarray)) 01323 { 01324 symbolarray_sort(symcount,symarray); 01325 for (i=0;i<symcount;i++) { 01326 if (o=object_attr_get(jitob,symarray[i])) { 01327 canget = (long)jit_object_method(o,ps_usercanget); 01328 canset = (long)jit_object_method(o,ps_usercanset); 01329 if (canget||canset) 01330 { 01331 namesym = jit_object_method(o,_jit_sym_getname); 01332 typesym = jit_object_method(o,_jit_sym_gettype); 01333 sprintf(s," %s [%s",namesym->s_name, typesym->s_name); 01334 if (jit_object_classname(o)==_jit_sym_jit_attr_offset_array) { 01335 sprintf(s2," array[%d]]",(long)jit_object_method(o,_jit_sym_getsize)); 01336 strcat(s,s2); 01337 } else { 01338 strcat(s,"]"); 01339 } 01340 #ifdef QUICKREF_ATTR_VALUE 01341 if (canget) 01342 { 01343 long ac=0,k; 01344 t_atom *av=NULL; 01345 char getstr[128]; 01346 01347 sprintf(getstr,"get%s",namesym->s_name); 01348 01349 jit_object_method(jitob,gensym(getstr),&ac,&av); 01350 if ((typesym==_jit_sym_long)||(typesym==_jit_sym_char)) { 01351 sprintf(s2," (val ="); 01352 strcat(s,s2); 01353 for (k=0;k<MIN(ac,4);k++) { 01354 sprintf(s2, " %d", jit_atom_getlong(av+k)); 01355 strcat(s,s2); 01356 } 01357 if (ac>4) 01358 strcat(s," ...)"); 01359 else 01360 strcat(s,")"); 01361 } else if ((typesym==_jit_sym_float32)||(typesym==_jit_sym_float64)) { 01362 sprintf(s2," (val ="); 01363 strcat(s,s2); 01364 for (k=0;k<MIN(ac,4);k++) { 01365 sprintf(s2, " %.2f", jit_atom_getfloat(av+k)); 01366 strcat(s,s2); 01367 } 01368 if (ac>4) 01369 strcat(s," ...)"); 01370 else 01371 strcat(s,")"); 01372 } else if (typesym==_jit_sym_symbol) { 01373 t_symbol *tmpsym; 01374 sprintf(s2," (val ="); 01375 strcat(s,s2); 01376 tmpsym = jit_atom_getsym(av); 01377 if (tmpsym==_jit_sym_nothing) 01378 sprintf(s2," <none>"); 01379 else 01380 sprintf(s2," %s",tmpsym->s_name); 01381 strcat(s,s2); 01382 if (ac>1) 01383 strcat(s," ...)"); 01384 else 01385 strcat(s,")"); 01386 } 01387 freebytes(av,sizeof(t_atom)*ac); 01388 } 01389 #endif 01390 if (!(canget&&canset)) { 01391 if (canset) 01392 strcat(s," (set)"); 01393 else 01394 strcat(s," (get)"); 01395 } 01396 jit_object_method(sortlist,_jit_sym_append,gensym(s)); //hack, this is a symbol not an object 01397 } 01398 } 01399 } 01400 } 01401 if (symarray) 01402 freebytes((char *)symarray,symcount*sizeof(t_symbol *)); 01403 01404 items[0] = _jit_sym_nothing; //separator 01405 items[1] = gensym("Attributes:"); 01406 j=2; 01407 jit_object_method(sortlist,_jit_sym_sort,quickref_symcompare); 01408 size = (long) jit_object_method(sortlist,_jit_sym_getsize); 01409 for (i=0;(i<size)&&(j<QUICKREF_MAXMENU);i++,j++) 01410 items[j] = jit_object_method(sortlist,_jit_sym_getindex,i); 01411 jit_object_method(sortlist,_jit_sym_chuck); 01412 01413 //methods 01414 //max object, but first check if attribute 01415 //all public jit methods are exposed by max object 01416 sortlist = jit_object_new(_jit_sym_jit_linklist); 01417 if (mess = ob_messlist(x)) { 01418 mess++; 01419 while (mess->m_sym) { 01420 if (!max_jit_method_is_attr(x,mess->m_sym)) { 01421 if ((mess->m_type[0]!=A_CANT)&&(mess->m_sym!=ps_assist)&&(mess->m_sym!=ps_preset)) 01422 { 01423 //later on show method argument types 01424 sprintf(s," %s ",mess->m_sym->s_name); 01425 sprintf(s2,"%s%s",s,messlist_argstring(mess->m_type)); 01426 jit_object_method(sortlist,_jit_sym_append,gensym(s2)); //hack, this is a symbol not an object 01427 } 01428 } 01429 mess++; 01430 } 01431 } 01432 if (j<QUICKREF_MAXMENU-1) { 01433 items[j] = _jit_sym_nothing; //separator 01434 j++; 01435 items[j] = gensym("Messages:"); 01436 j++; 01437 } 01438 01439 jit_object_method(sortlist,_jit_sym_sort,quickref_symcompare); 01440 size = (long) jit_object_method(sortlist,_jit_sym_getsize); 01441 for (i=0;(i<size)&&(j<QUICKREF_MAXMENU);i++,j++) 01442 items[j] = jit_object_method(sortlist,_jit_sym_getindex,i); 01443 jit_object_method(sortlist,_jit_sym_chuck); 01444 01445 *numitems = j; 01446 } 01447 01448 t_jit_linklist *jit_usurplist_build(void *parent, t_symbol *classname) 01449 { 01450 t_jit_linklist *x=NULL; 01451 t_jit_class *c; 01452 t_messlist *m; 01453 t_jit_usurp *u; 01454 long type; 01455 char tmpstr[256]; 01456 01457 01458 //first deal with max object usurp methods(this handles attributes) 01459 if (!parent) goto out; 01460 if (!(m=((t_max_object *)parent)->o_messlist)) goto out; 01461 while (m->m_sym){ 01462 if ((FCHECK(m->m_fun)==(method)max_jit_usurp_method)&&(m[1].m_type[0]==A_CANT)){ 01463 sprintf(tmpstr,"%s_usurp",m->m_sym->s_name); 01464 if (m[1].m_sym==gensym(tmpstr)) { 01465 if (!x) { if (!(x = jit_linklist_new())) goto out; } 01466 if (!(u=jit_usurp_new(parent,FCHECK(m[1].m_fun),m->m_sym,JIT_USURP_FLAGS_MAX))) goto out; //out of mem 01467 jit_linklist_append(x,u); 01468 } else { 01469 sprintf(tmpstr+strlen(tmpstr),"_low"); 01470 if (m[1].m_sym==gensym(tmpstr)) { 01471 if (!x) { if (!(x = jit_linklist_new())) goto out; } 01472 if (!(u=jit_usurp_new(parent,FCHECK(m[1].m_fun),m->m_sym,JIT_USURP_FLAGS_MAX|JIT_USURP_FLAGS_LOW))) goto out; //out of mem 01473 jit_linklist_append(x,u); 01474 } 01475 } 01476 } 01477 m++; 01478 } 01479 //now add jit object usurp methods 01480 if (c=jit_class_findbyname(classname)) { 01481 m = (((t_jit_class *)c)->c_messlist)+1; 01482 while (m->m_sym){ 01483 type = m->m_type[0]; 01484 switch (type) { 01485 case A_USURP: 01486 if (!x) { if (!(x = jit_linklist_new())) goto out; } 01487 if (!(u=jit_usurp_new(parent,FCHECK(m->m_fun),m->m_sym,0))) goto out; //out of mem 01488 jit_linklist_append(x,u); 01489 break; 01490 case A_USURP_LOW: 01491 if (!x) { if (!(x = jit_linklist_new())) goto out; } 01492 if (!(u=jit_usurp_new(parent,FCHECK(m->m_fun),m->m_sym,JIT_USURP_FLAGS_LOW))) goto out; //out of mem 01493 jit_linklist_append(x,u); 01494 break; 01495 } 01496 m++; 01497 } 01498 } 01499 out: 01500 return x; 01501 } 01502 01503 #pragma mark - 01504 // -------------------------------------------------------------------------------- 01505 // max_jit_classex functions 01506 01507 /** 01508 * Allocates and initializes special t_max_jit_classex data, used by the Max wrapper class. 01509 * 01510 * @ingroup maxwrapmod 01511 * 01512 * @param oboffset object struct byte offset to obex pointer 01513 * 01514 * @return pointer to t_max_jit_classex data (opaque) 01515 * 01516 */ 01517 void *max_jit_classex_setup(long oboffset) 01518 { 01519 t_max_jit_classex *x; 01520 01521 #if TARGET_RT_MAC_MACHO 01522 initialize(); 01523 #endif 01524 if (x=(t_max_jit_classex *)jit_getbytes(sizeof(t_max_jit_classex))) { 01525 x->oboffset = oboffset; 01526 x->attrlist = NULL; 01527 x->adornmentlist = NULL; 01528 addmess((method)x, "max_jit_classex", A_CANT,0); 01529 } 01530 01531 return x; 01532 } 01533 01534 /** 01535 * Adds an attribute to the Max wrapper class. 01536 * 01537 * @ingroup maxwrapmod 01538 * 01539 * @param x pointer to t_max_jit_classex data (opaque) 01540 * @param attr attribute object pointer 01541 * 01542 * @return t_jit_err error code 01543 * 01544 */ 01545 t_jit_err max_jit_classex_addattr(void *x, void *attr) 01546 { 01547 t_symbol *s; 01548 method *m; 01549 long type; 01550 char tmpstr[256]; 01551 01552 if (x&&attr) { 01553 if (!((t_max_jit_classex *)x)->attrlist) { 01554 if (!(((t_max_jit_classex *)x)->attrlist=jit_linklist_new())){ 01555 return JIT_ERR_OUT_OF_MEM; 01556 } 01557 } 01558 jit_linklist_append(((t_max_jit_classex *)x)->attrlist,attr); 01559 //add the method to the messlist 01560 s = jit_object_method(attr,_jit_sym_getname); 01561 if (jit_object_method(attr,ps_usercanset)) { 01562 m = jit_object_method(attr,_jit_sym_getmethod,_jit_sym_set); 01563 type = (long) jit_object_method(attr,ps_getmethodtype,_jit_sym_set); 01564 switch (type) { 01565 case A_DEFER: 01566 max_addmethod_defer((method)max_jit_obex_attr_set, s->s_name); 01567 break; 01568 case A_DEFER_LOW: 01569 max_addmethod_defer_low((method)max_jit_obex_attr_set, s->s_name); 01570 break; 01571 case A_USURP: 01572 max_addmethod_usurp((method)max_jit_obex_attr_set, s->s_name); 01573 break; 01574 case A_USURP_LOW: 01575 max_addmethod_usurp_low((method)max_jit_obex_attr_set, s->s_name); 01576 break; 01577 case A_GIMME: 01578 addmess((method)max_jit_obex_attr_set, s->s_name, A_GIMME, 0); 01579 break; 01580 } 01581 } 01582 if (jit_object_method(attr,ps_usercanget)) { 01583 m = jit_object_method(attr,_jit_sym_getmethod,_jit_sym_get); 01584 type = (long) jit_object_method(attr,ps_getmethodtype,_jit_sym_get); 01585 sprintf(tmpstr,"%s%s","get",s->s_name); 01586 switch (type) { 01587 case A_DEFER: 01588 max_addmethod_defer((method)max_jit_obex_attr_getdump, tmpstr); 01589 break; 01590 case A_DEFER_LOW: 01591 max_addmethod_defer_low((method)max_jit_obex_attr_getdump, tmpstr); 01592 break; 01593 case A_USURP: 01594 max_addmethod_usurp((method)max_jit_obex_attr_getdump, tmpstr); 01595 break; 01596 case A_USURP_LOW: 01597 max_addmethod_usurp_low((method)max_jit_obex_attr_getdump, tmpstr); 01598 break; 01599 case A_GIMME: 01600 addmess((method)max_jit_obex_attr_getdump, tmpstr, A_GIMME, 0); 01601 break; 01602 } 01603 } 01604 01605 return JIT_ERR_NONE; 01606 } 01607 return JIT_ERR_INVALID_PTR; 01608 } 01609 01610 t_max_jit_classex *max_jit_classex_get(void *x) 01611 { 01612 t_messlist *m=NULL; 01613 if (x) { 01614 if (!(m=((t_max_object *)x)->o_messlist)) goto out; 01615 while (m->m_sym){ 01616 if ((m->m_sym==_jit_sym_max_jit_classex)){ 01617 #ifdef WIN_VERSION 01618 return (t_max_jit_classex *)m->m_fun; 01619 #else 01620 // temporary, only here for Jitter 1.5.7 with MaxMSP 4.6 (NOT SAFE IN CFM) 01621 return (t_max_jit_classex *)FCHECK((UInt32 *)m->m_fun); 01622 #endif 01623 } 01624 m++; 01625 } 01626 } 01627 out: 01628 return NULL; 01629 } 01630 01631 #pragma mark - 01632 // -------------------------------------------------------------------------------- 01633 // max_jit_obex functions 01634 01635 /** 01636 * Allocates an initializes a new Max wrapper object instance. 01637 * This is used in place of the newobject function. 01638 * 01639 * @ingroup maxwrapmod 01640 * 01641 * @param mc Max class pointer 01642 * @param classname Jitter class name to wrap 01643 * 01644 * @return pointer to new Max wrapper object instance 01645 * 01646 */ 01647 void *max_jit_obex_new(void *mc, t_symbol *classname) 01648 { 01649 void *x; 01650 t_class *c; 01651 01652 if (x=newobject(mc)) { 01653 // HACK for oldschool objects to have attributes 01654 c = object_class(x); 01655 c->c_flags &= ~CLASS_FLAG_NOATTRIBUTES; 01656 c->c_flags |= CLASS_FLAG_OWNATTRIBUTES; 01657 max_jit_obex_set(x,jit_getbytes(sizeof(t_max_jit_obex))); 01658 max_jit_obex_jitob_set(x,NULL); 01659 max_jit_obex_usurplist_set(x,jit_usurplist_build(x,classname)); 01660 max_jit_obex_proxylist_set(x,NULL); 01661 max_jit_obex_inletnumber_set(x,0); 01662 max_jit_obex_dumpout_set(x,NULL); 01663 max_jit_obex_adornmentlist_set(x,NULL); 01664 max_jit_obex_box_set(x, ps__Box->s_thing); 01665 } 01666 return x; 01667 } 01668 01669 /** 01670 * Frees additional resources for the Max wrapper object instance. 01671 * 01672 * @ingroup maxwrapmod 01673 * 01674 * @param x Max wrapper object pointer 01675 * 01676 */ 01677 void max_jit_obex_free(void *x) 01678 { 01679 void *p; 01680 t_max_jit_obex *obex; 01681 01682 if (x) { 01683 if (p=max_jit_obex_usurplist_get(x)) 01684 jit_object_free(p); 01685 if (p=max_jit_obex_proxylist_get(x)) 01686 jit_object_free(p); 01687 if (p=max_jit_obex_adornmentlist_get(x)) 01688 jit_object_free(p); 01689 if (obex=max_jit_obex_get(x)) 01690 jit_freebytes(obex,sizeof(t_max_jit_obex)); 01691 //should we also free the jitob automatically? 01692 } 01693 } 01694 01695 // for new max obex/pattr comptibility 01696 void *max_jit_obex_attr_getobject(void *x, t_symbol *s) 01697 { 01698 t_jit_linklist *attrlist; 01699 void *attr=NULL; 01700 01701 if (attrlist=max_jit_obex_attrlist_get(x)) { 01702 jit_linklist_findfirst(attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 01703 if (attr) 01704 return attr; 01705 } 01706 if (attr=jit_object_attr_get(max_jit_obex_jitob_get(x),s)) { 01707 return attr; 01708 } 01709 01710 return attr; 01711 } 01712 01713 01714 // for new max obex/pattr comptibility 01715 void *max_jit_obex_attr_gettarget(void *x, t_symbol *s) 01716 { 01717 t_jit_linklist *attrlist; 01718 void *attr=NULL; 01719 01720 if (attrlist=max_jit_obex_attrlist_get(x)) { 01721 jit_linklist_findfirst(attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 01722 if (attr) 01723 return x; 01724 } 01725 if (attr=jit_object_attr_get(max_jit_obex_jitob_get(x),s)) { 01726 return max_jit_obex_jitob_get(x); 01727 } 01728 return attr; 01729 } 01730 01731 // for new max obex/pattr comptibility 01732 long max_jit_obex_attr_getnames(void *x, long *argc, t_symbol ***argv) 01733 { 01734 void *attrlist,*jitob; 01735 long i,j,mac=0,jac=0; 01736 t_symbol **jav=NULL; 01737 01738 *argc = 0; 01739 *argv = NULL; 01740 if (attrlist=max_jit_obex_attrlist_get(x)) { 01741 mac = jit_linklist_getsize(attrlist); 01742 } 01743 jitob = max_jit_obex_jitob_get(x); 01744 if (jitob) { 01745 object_attr_getnames(jitob, &jac, &jav); 01746 } 01747 *argc = mac+jac; 01748 if (*argc) { 01749 *argv = (t_symbol **)getbytes((*argc)*sizeof(t_symbol *)); 01750 for (i=0;i<mac;i++) 01751 (*argv)[i] = jit_object_method(jit_linklist_getindex(attrlist,i),_jit_sym_getname); 01752 for (j=0;j<jac;i++,j++) 01753 (*argv)[i] = jav[j]; 01754 } 01755 if (jac&&jav) 01756 freebytes(jav,jac*sizeof(t_symbol *)); 01757 01758 return 0; 01759 } 01760 01761 void *max_jit_obex_attrlist_get(void *x) 01762 { 01763 t_max_jit_classex *c=NULL; 01764 if (x) { 01765 if (c=max_jit_classex_get(x)) 01766 return c->attrlist; 01767 } 01768 return NULL; 01769 } 01770 01771 /** 01772 * Sets an attribute of the Max wrapper or the wrapped Jitter object. 01773 * 01774 * @ingroup maxwrapmod 01775 * 01776 * @param x Max wrapper object pointer 01777 * @param s attribute name 01778 * @param ac atom count 01779 * @param av atom vector 01780 * 01781 * @return t_jit_error error code 01782 * 01783 */ 01784 t_jit_err max_jit_obex_attr_set(void *x, t_symbol *s, long ac, t_atom *av) 01785 { 01786 t_jit_linklist *attrlist; 01787 void *attr; 01788 method m=NULL; 01789 t_box *b; 01790 t_jit_err rv; 01791 01792 if (x&&(attrlist=max_jit_obex_attrlist_get(x))) { 01793 jit_linklist_findfirst(attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 01794 if (attr) m = jit_object_method(attr,_jit_sym_getmethod,_jit_sym_set); 01795 if (m) rv = (t_jit_err)((*m)(x,attr,ac,av)); 01796 object_notify(x,ps_attr_modified,attr); 01797 if ((b = max_jit_obex_box_get(x)) && ((void *)b != x)) { 01798 object_notify(b, ps_attr_modified, attr); 01799 } 01800 return rv; 01801 } 01802 01803 return JIT_ERR_GENERIC; 01804 } 01805 01806 /** 01807 * Retrienves an attribute of the Max wrapper or the wrapped Jitter object. 01808 * 01809 * @ingroup maxwrapmod 01810 * 01811 * @param x Max wrapper object pointer 01812 * @param s attribute name 01813 * @param ac pointer to atom count 01814 * @param av pointer to atom vector 01815 * 01816 * @return t_jit_error error code 01817 * 01818 */ 01819 t_jit_err max_jit_obex_attr_get(void *x, t_symbol *s, long *ac, t_atom **av) 01820 { 01821 t_jit_linklist *attrlist; 01822 void *attr; 01823 method m=NULL; 01824 01825 if (x&&(attrlist=max_jit_obex_attrlist_get(x))) { 01826 jit_linklist_findfirst(attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 01827 if (attr) m = jit_object_method(attr,_jit_sym_getmethod,_jit_sym_get); 01828 if (m) 01829 return (t_jit_err)((*m)(x,attr,ac,av)); 01830 return JIT_ERR_NONE; 01831 } 01832 01833 return JIT_ERR_GENERIC; 01834 } 01835 01836 void max_jit_obex_attr_getdump(void *x, t_symbol *s, short argc, t_atom *argv) 01837 { 01838 long ac=0; 01839 t_atom *av=NULL; 01840 method f; 01841 t_jit_err err; 01842 01843 s = gensym(s->s_name+3); //strip get 01844 if ((err = max_jit_obex_attr_get(x,s,&ac,&av)) != JIT_ERR_NONE) { 01845 jit_error_code(x, err); 01846 } else { 01847 if (f=zgetfn(x,ps_dumpout)) 01848 (*f)(x,s,(short)ac,av); 01849 } 01850 freebytes(av,sizeof(t_atom)*ac); 01851 } 01852 01853 t_jit_err max_jit_obex_set(void *x, void *p) 01854 { 01855 t_max_jit_classex *c=NULL; 01856 if (x) { 01857 if (c=max_jit_classex_get(x)) 01858 *((t_max_jit_obex **)(((char *)x)+(c->oboffset))) = p; 01859 return JIT_ERR_NONE; 01860 } 01861 return JIT_ERR_GENERIC; 01862 } 01863 01864 void *max_jit_obex_get(void *x) 01865 { 01866 t_max_jit_classex *c=NULL; 01867 if (x) { 01868 if (c=max_jit_classex_get(x)) 01869 return *((t_max_jit_obex **)(((char *)x)+(c->oboffset))); 01870 } 01871 return NULL; 01872 } 01873 01874 /** 01875 * Retrieves the wrapped Jitter object from a Max wrapper object. 01876 * 01877 * @ingroup maxwrapmod 01878 * 01879 * @param x Max wrapper object pointer 01880 * 01881 * @return Jitter object pointer 01882 * 01883 */ 01884 void *max_jit_obex_jitob_get(void *x) 01885 { 01886 t_max_jit_obex *obex; 01887 if (obex=max_jit_obex_get(x)) 01888 return obex->jitob; 01889 else 01890 return NULL; 01891 } 01892 01893 /** 01894 * Sets the wrapped Jitter object for a Max wrapper object. 01895 * 01896 * @ingroup maxwrapmod 01897 * 01898 * @param x Max wrapper object pointer 01899 * @param jitob Jitter object pointer 01900 * 01901 */ 01902 void max_jit_obex_jitob_set(void *x, void *jitob) 01903 { 01904 t_max_jit_obex *obex; 01905 static t_symbol *ps_maxwrapper=NULL; 01906 01907 if (!ps_maxwrapper) 01908 ps_maxwrapper = gensym("maxwrapper"); 01909 01910 if (obex=max_jit_obex_get(x)) { 01911 if (jitob) 01912 object_obex_storeflags(jitob,ps_maxwrapper,(t_object *)x,OBJ_FLAG_REF); 01913 obex->jitob=jitob; 01914 } 01915 } 01916 01917 void *max_jit_obex_usurplist_get(void *x) 01918 { 01919 t_max_jit_obex *obex; 01920 if (obex=max_jit_obex_get(x)) 01921 return obex->usurplist; 01922 else 01923 return NULL; 01924 } 01925 01926 void max_jit_obex_usurplist_set(void *x, void *usurplist) 01927 { 01928 t_max_jit_obex *obex; 01929 if (obex=max_jit_obex_get(x)) 01930 obex->usurplist=usurplist; 01931 } 01932 01933 void *max_jit_obex_proxylist_get(void *x) 01934 { 01935 t_max_jit_obex *obex; 01936 if (obex=max_jit_obex_get(x)) 01937 return obex->proxylist; 01938 else 01939 return NULL; 01940 } 01941 01942 void max_jit_obex_proxylist_set(void *x, void *proxylist) 01943 { 01944 t_max_jit_obex *obex; 01945 if (obex=max_jit_obex_get(x)) 01946 obex->proxylist=proxylist; 01947 } 01948 01949 /** 01950 * Retrieves the current inlet number used by inlet proxies. 01951 * 01952 * @ingroup maxwrapmod 01953 * 01954 * @param x Max wrapper object pointer 01955 * 01956 * @return current inlet index 01957 * 01958 */ 01959 long max_jit_obex_inletnumber_get(void *x) 01960 { 01961 return proxy_getinlet(x); 01962 } 01963 01964 /** 01965 * Sets the current inlet number used by inlet proxies. 01966 * 01967 * @warning Typically not used outside jitlib. 01968 * 01969 * @ingroup maxwrapmod 01970 * 01971 * @param x Max wrapper object pointer 01972 * @param inletnumber inlet index 01973 * 01974 */ 01975 void max_jit_obex_inletnumber_set(void *x, long inletnumber) 01976 { 01977 t_max_jit_obex *obex; 01978 if (obex=max_jit_obex_get(x)) 01979 obex->inletnumber=inletnumber; 01980 } 01981 01982 /** 01983 * Creates a new proxy inlet. 01984 * 01985 * @ingroup maxwrapmod 01986 * 01987 * @param x Max wrapper object pointer 01988 * @param c inlet index 01989 * 01990 * @return t_jit_err error code 01991 * 01992 */ 01993 t_jit_err max_jit_obex_proxy_new(void *x, long c) 01994 { 01995 t_max_jit_obex *obex; 01996 void *proxy; 01997 if (obex=max_jit_obex_get(x)) { 01998 if (!obex->proxylist) { 01999 if (!(obex->proxylist=jit_linklist_new())) 02000 return JIT_ERR_OUT_OF_MEM; 02001 } 02002 if (proxy=proxy_new(x,c,&obex->inletnumber)) { 02003 jit_linklist_append(obex->proxylist,proxy); 02004 return JIT_ERR_NONE; 02005 } else { 02006 return JIT_ERR_OUT_OF_MEM; 02007 } 02008 } else { 02009 return JIT_ERR_GENERIC; 02010 } 02011 } 02012 02013 /** 02014 * Sets the Max wrapper object's dump outlet's outlet pointer. 02015 * 02016 * @ingroup maxwrapmod 02017 * 02018 * @param x Max wrapper object pointer 02019 * @param outlet dump outlet pointer 02020 * 02021 */ 02022 void max_jit_obex_dumpout_set(void *x, void *outlet) 02023 { 02024 t_max_jit_obex *obex; 02025 if (obex=max_jit_obex_get(x)) 02026 obex->dumpout=outlet; 02027 } 02028 02029 /** 02030 * Retrieves the Max wrapper object's dump outlet's outlet pointer. 02031 * 02032 * @ingroup maxwrapmod 02033 * 02034 * @param x Max wrapper object pointer 02035 * 02036 * @return dump outlet pointer 02037 * 02038 */ 02039 void *max_jit_obex_dumpout_get(void *x) 02040 { 02041 t_max_jit_obex *obex; 02042 if (obex=max_jit_obex_get(x)) 02043 return obex->dumpout; 02044 else 02045 return NULL; 02046 } 02047 02048 /** 02049 * Sends a message and arguments out the dump outlet. 02050 * This message is equivalent to calling outlet_anything 02051 * with the outlet returned by max_jit_obex_dumpout_get. 02052 * 02053 * @ingroup maxwrapmod 02054 * 02055 * @param x Max wrapper object pointer 02056 * @param s message symbol 02057 * @param argc argument count 02058 * @param argv argument vector 02059 * 02060 */ 02061 void max_jit_obex_dumpout(void *x, t_symbol *s, short argc, t_atom *argv) 02062 { 02063 t_max_jit_obex *obex; 02064 02065 if ((obex=max_jit_obex_get(x))&&obex->dumpout) { 02066 outlet_anything(obex->dumpout,s,argc,argv); 02067 } 02068 } 02069 02070 void *max_jit_obex_adornmentlist_get(void *x) 02071 { 02072 t_max_jit_obex *obex; 02073 if (obex=max_jit_obex_get(x)) 02074 return obex->adornmentlist; 02075 else 02076 return NULL; 02077 } 02078 02079 void max_jit_obex_adornmentlist_set(void *x, void *adornmentlist) 02080 { 02081 t_max_jit_obex *obex; 02082 if (obex=max_jit_obex_get(x)) 02083 obex->adornmentlist=adornmentlist; 02084 } 02085 02086 /** 02087 * Retrieves Max wrapper object adornment specified by class name. 02088 * Typcially used for accessing the jit_mop adornment for MOP Max 02089 * wrapper objects. 02090 * 02091 * @ingroup maxwrapmod 02092 * 02093 * @param x Max wrapper object pointer 02094 * @param classname adornment classname 02095 * 02096 * @return adornment pointer 02097 * 02098 */ 02099 void *max_jit_obex_adornment_get(void *x, t_symbol *classname) 02100 { 02101 t_max_jit_obex *obex; 02102 void *adornment=NULL; 02103 02104 if ((obex=max_jit_obex_get(x)) && obex->adornmentlist) { 02105 jit_object_method(obex->adornmentlist,_jit_sym_findfirst,&adornment,jit_object_classname_compare,classname); 02106 } 02107 02108 return adornment; 02109 } 02110 02111 void max_jit_obex_box_set(void *x, void *b) 02112 { 02113 t_max_jit_obex *obex; 02114 if (obex=max_jit_obex_get(x)) 02115 obex->b=b; 02116 } 02117 02118 t_box *max_jit_obex_box_get(void *x) 02119 { 02120 t_max_jit_obex *obex; 02121 if (obex=max_jit_obex_get(x)) 02122 return obex->b; 02123 else 02124 return NULL; 02125 } 02126 02127 t_jit_err max_jit_obex_addadornment(void *x,void *adornment) 02128 { 02129 t_max_jit_obex *obex; 02130 02131 if ((obex=max_jit_obex_get(x))&&adornment) { 02132 if (!obex->adornmentlist) { 02133 if (!(obex->adornmentlist=jit_object_new(_jit_sym_jit_linklist))) 02134 return JIT_ERR_OUT_OF_MEM; 02135 } 02136 02137 jit_object_method(obex->adornmentlist,_jit_sym_append,adornment); 02138 return JIT_ERR_NONE; 02139 } else { 02140 return JIT_ERR_GENERIC; 02141 } 02142 } 02143 02144 long max_jit_obex_attr_usercanset(void *x, t_symbol *s) 02145 { 02146 void *attr=NULL; 02147 t_max_jit_classex *c; 02148 02149 if (c=max_jit_classex_get(x)) { 02150 if (c->attrlist) { 02151 jit_linklist_findfirst(c->attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 02152 if (attr) return (long)jit_object_method(attr,ps_usercanset); 02153 } 02154 } 02155 02156 return FALSE; 02157 } 02158 02159 void *max_jit_obex_attr_method_direct(void *x, t_symbol *s, long ac, t_atom *av) 02160 { 02161 void *attr=NULL; 02162 method m; 02163 t_max_jit_classex *c; 02164 02165 if (c=max_jit_classex_get(x)) { 02166 if (c->attrlist) { 02167 jit_linklist_findfirst(c->attrlist,&attr,(t_cmpfn)jit_attr_symcompare,s); 02168 if (attr) { 02169 if (m=(method)jit_object_method(attr,_jit_sym_getmethod,_jit_sym_set)) 02170 (*m)(x,attr,ac,av); 02171 } 02172 } 02173 } 02174 return NULL; 02175 } 02176 02177 // no dumpout 02178 /** 02179 * Calls gimmeback methods and frees any return value. 02180 * 02181 * @ingroup maxwrapmod 02182 * 02183 * @param x Max wrapper object pointer 02184 * @param s method name 02185 * @param ac argument count 02186 * @param av argument vector 02187 * 02188 */ 02189 void max_jit_obex_gimmeback(void *x, t_symbol *s, long ac, t_atom *av) 02190 { 02191 t_atom rv; 02192 t_atom *rav=NULL; 02193 long rac=0; 02194 02195 object_method_typed(max_jit_obex_jitob_get(x),s,ac,av,&rv); 02196 if (rv.a_type == A_NOTHING) return; 02197 if (rv.a_type==A_OBJ) { 02198 if (rac&&rav) 02199 freebytes(rav,rac*sizeof(t_atom)); 02200 if(rv.a_w.w_obj) 02201 freeobject(rv.a_w.w_obj); 02202 } 02203 } 02204 02205 /** 02206 * Calls gimmeback methods and outputs any return value through the Max wrapper class' dump outlet. 02207 * 02208 * @ingroup maxwrapmod 02209 * 02210 * @param x Max wrapper object pointer 02211 * @param s method name 02212 * @param ac argument count 02213 * @param av argument vector 02214 * 02215 */ 02216 void max_jit_obex_gimmeback_dumpout(void *x, t_symbol *s, long ac, t_atom *av) 02217 { 02218 t_atom rv; 02219 t_atom *rav=NULL; 02220 long rac=0; 02221 02222 object_method_typed(max_jit_obex_jitob_get(x),s,ac,av,&rv); 02223 if (rv.a_type == A_NOTHING) return; 02224 if (rv.a_type==A_OBJ) { 02225 object_getvalueof(rv.a_w.w_obj,&rac,&rav); 02226 } else { 02227 rac = 1; 02228 rav = &rv; 02229 } 02230 if (s&&s->s_name[0]=='g'&&s->s_name[1]=='e'&&s->s_name[2]=='t') 02231 s = gensym(s->s_name+3); 02232 max_jit_obex_dumpout(x,s,rac,rav); 02233 if (rv.a_type==A_OBJ) { 02234 if (rac&&rav) 02235 freebytes(rav,rac*sizeof(t_atom)); 02236 if(rv.a_w.w_obj) 02237 freeobject(rv.a_w.w_obj); 02238 } 02239 }
Copyright © 2008, Cycling '74