cyclone-0.1-alpha55/0000755000076500007650000000000011466617624012736 5ustar hanshanscyclone-0.1-alpha55/dumpsetups0000755000076500007650000000102211466617453015070 0ustar hanshans#!/bin/sh # LATER make this into a regular awk script DIR=`pwd` LIB=`basename $DIR` echo '// Do not edit this file, run "make" instead. /* Copyright (c) 2002-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ ' awk '/void .*_setup\(void\)$/&&!/'$LIB'/{print $0";"}' *.c echo "" echo 'void all'$LIB's_setup(void)' echo '{' awk -F '[ (]' '/void .*_setup\(void\)$/&&!/'$LIB'/{print " "$2"();"}' *.c echo '}' cyclone-0.1-alpha55/shared/0000755000076500007650000000000011466617453014204 5ustar hanshanscyclone-0.1-alpha55/shared/Makefile.objects0000644000076500007650000000000011466617453017262 0ustar hanshanscyclone-0.1-alpha55/shared/unstable/0000755000076500007650000000000011466617453016021 5ustar hanshanscyclone-0.1-alpha55/shared/unstable/fringe.c0000644000076500007650000000520311466617453017437 0ustar hanshans/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* Put here calls which are likely to (and should) make into Pd API some day. */ #include "m_pd.h" #include "g_canvas.h" #include "unstable/forky.h" #include "unstable/fringe.h" #ifdef KRZYSZCZ //#define FRINGE_DEBUG #endif static int gobj_getindex(t_glist *gl, t_gobj *ob) { t_gobj *ob1; int ndx; for (ob1 = gl->gl_list, ndx = 0; ob1 && ob1 != ob; ob1 = ob1->g_next) ndx++; return (ndx); } static void gobj_totail(t_glist *gl, t_gobj *ob) { if (ob->g_next) { t_gobj *ob1; if (ob == gl->gl_list) ob1 = gl->gl_list = ob->g_next; else { for (ob1 = gl->gl_list; ob1; ob1 = ob1->g_next) if (ob1->g_next == ob) break; if (!ob1) { bug("gobj_totail"); return; } ob1->g_next = ob->g_next; ob1 = ob1->g_next; } while (ob1->g_next) ob1 = ob1->g_next; ob1->g_next = ob; ob->g_next = 0; } } static void gobj_stowconnections(t_glist *gl, t_gobj *ob, t_binbuf *bb) { t_linetraverser lt; t_outconnect *oc; binbuf_clear(bb); linetraverser_start(<, gl); while (oc = linetraverser_next(<)) { if ((t_gobj *)lt.tr_ob == ob || (t_gobj *)lt.tr_ob2 == ob) binbuf_addv(bb, "ssiiii;", gensym("#X"), gensym("connect"), gobj_getindex(gl, (t_gobj *)lt.tr_ob), lt.tr_outno, gobj_getindex(gl, (t_gobj *)lt.tr_ob2), lt.tr_inno); } #ifdef FRINGE_DEBUG fprintf(stderr, "packed connections:\n"); binbuf_print(bb); #endif } static void gobj_restoreconnections(t_glist *gl, t_binbuf *bb) { #ifdef FRINGE_DEBUG fprintf(stderr, "restoring connections:\n"); binbuf_print(bb); #endif canvas_setcurrent(gl); binbuf_eval(bb, 0, 0, 0); canvas_unsetcurrent(gl); } void gobj_recreate(t_glist *gl, t_gobj *ob, t_binbuf *bb) { /* LATER revisit all gobj calls, and sort out the gop case */ t_text *newt; int xpix = ((t_text *)ob)->te_xpix, ypix = ((t_text *)ob)->te_ypix; t_binbuf *bb1 = binbuf_new(); int ac = binbuf_getnatom(bb); t_atom *av = binbuf_getvec(bb); canvas_setcurrent(gl); gobj_totail(gl, ob); gobj_stowconnections(gl, ob, bb1); glist_delete(gl, ob); if (newt = (t_text *)forky_newobject(av->a_w.w_symbol, ac - 1, av + 1)) { newt->te_binbuf = bb; newt->te_xpix = xpix; newt->te_ypix = ypix; newt->te_width = 0; newt->te_type = T_OBJECT; glist_add(gl, (t_gobj *)newt); gobj_restoreconnections(gl, bb1); } else bug("gobj_recreate"); binbuf_free(bb1); canvas_unsetcurrent(gl); } cyclone-0.1-alpha55/shared/unstable/forky.h0000644000076500007650000000175611466617453017335 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __FORKY_H__ #define __FORKY_H__ #ifdef PD_MINOR_VERSION #define FORKY_VERSION PD_MINOR_VERSION #elif defined(PD_VERSION) #define FORKY_VERSION 36 #else #define FORKY_VERSION 35 #endif #if FORKY_VERSION >= 37 #define FORKY_WIDGETPADDING #else #warning You are entering a back-compatibility mode. Delete this warning from forky.h to proceed. #define FORKY_WIDGETPADDING 0,0 #endif typedef void (*t_forkysavefn)(t_gobj *x, t_binbuf *bb); typedef void (*t_forkypropertiesfn)(t_gobj *x, t_glist *gl); t_pd *forky_newobject(t_symbol *s, int ac, t_atom *av); void forky_setsavefn(t_class *c, t_forkysavefn fn); void forky_setpropertiesfn(t_class *c, t_forkypropertiesfn fn); int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym); t_int forky_getbitmask(int ac, t_atom *av); #endif cyclone-0.1-alpha55/shared/unstable/Makefile.objects0000644000076500007650000000000011466617453021077 0ustar hanshanscyclone-0.1-alpha55/shared/unstable/fragile.c0000644000076500007650000002116711466617453017605 0ustar hanshans/* Copyright (c) 1997-2005 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* Put here bits and pieces likely to break with any new Pd version. */ #include #include "m_pd.h" #include "common/loud.h" #include "unstable/pd_imp.h" #include "unstable/fragile.h" /* this one rather belongs to fringe.c... */ t_symbol *fragile_class_getexterndir(t_class *c) { return (c->c_externdir); } int fragile_class_count(void) { return (pd_objectmaker->c_nmethod); } int fragile_class_getnames(t_atom *av, int maxnames) { int ac = pd_objectmaker->c_nmethod; t_methodentry *mp = pd_objectmaker->c_methods; if (ac > maxnames) ac = maxnames; else maxnames = ac; while (ac--) { SETSYMBOL(av, mp->me_name); mp++; av++; } return (maxnames); } /* Raising and voluntary mutation is a method of resolving name clashes. A raised class hides other equivocal candidates. A simpler method, raising and lowering, works only in global scope, because, currently, Pd has only one visibility stack. Until this is changed, abstraction scope will involve some kind of a hack for overriding global visibility stack. */ void fragile_class_raise(t_symbol *cname, t_newmethod thiscall) { t_methodentry *mp = pd_objectmaker->c_methods, *topmp = 0; int count = pd_objectmaker->c_nmethod; while (count--) { if (mp->me_name == cname) { if (mp->me_fun == (t_gotfn)thiscall) { if (topmp) { t_methodentry auxmp; /* no linkage there, but anyway... */ loud_warning(0, 0, "%s is raising itself...", cname->s_name); memcpy(&auxmp, mp, sizeof(t_methodentry)); memcpy(mp, topmp, sizeof(t_methodentry)); memcpy(topmp, &auxmp, sizeof(t_methodentry)); } return; } else if (!topmp) topmp = mp; } mp++; } loudbug_bug("fragile_class_raise"); } t_pd *fragile_class_mutate(t_symbol *cname, t_newmethod thiscall, int ac, t_atom *av) { t_newmethod fn; t_atomtype *argtypes; if (fn = fragile_class_getalien(cname, thiscall, &argtypes)) { t_pd *z; loud_warning(0, 0, "%s is mutating now...", cname->s_name); if (z = fragile_class_createobject(cname, fn, argtypes, ac, av)) { post("...succeeded"); return (z); } else post("...failed"); } return (0); } t_newmethod fragile_class_getalien(t_symbol *cname, t_newmethod thiscall, t_atomtype **argtypesp) { t_methodentry *mp = pd_objectmaker->c_methods; int count = pd_objectmaker->c_nmethod; while (count--) { if (mp->me_name == cname && mp->me_fun != (t_gotfn)thiscall) { *argtypesp = mp->me_arg; return ((t_newmethod)mp->me_fun); } mp++; } return (0); } /* A specialized copy of pd_typedmess() from m_class.c, somewhat simplified for readability. */ typedef t_pd *(*t_newgimme)(t_symbol *s, int ac, t_atom *av); typedef t_pd *(*t_new0)( t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new1)( t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new2)( t_symbol*, t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new3)( t_symbol*, t_symbol*, t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new4)( t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new5)( t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); typedef t_pd *(*t_new6)( t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_symbol*, t_floatarg, t_floatarg, t_floatarg, t_floatarg, t_floatarg); t_pd *fragile_class_createobject(t_symbol *cname, t_newmethod callthis, t_atomtype *argtypes, int ac, t_atom *av) { t_floatarg ff[MAXPDARG+1], *fp = ff; t_symbol *ss[MAXPDARG+1], **sp = ss; int nsymbols = 0; t_atomtype wanttype; if (*argtypes == A_GIMME) return ((*((t_newgimme)(callthis)))(cname, ac, av)); if (ac > MAXPDARG) ac = MAXPDARG; while (wanttype = *argtypes++) { switch (wanttype) { case A_POINTER: goto badarg; case A_FLOAT: if (!ac) goto badarg; case A_DEFFLOAT: if (!ac) *fp = 0; else { if (av->a_type == A_FLOAT) *fp = av->a_w.w_float; else goto badarg; ac--; av++; } fp++; break; case A_SYMBOL: if (!ac) goto badarg; case A_DEFSYM: if (!ac) *sp = &s_; else { if (av->a_type == A_SYMBOL) *sp = av->a_w.w_symbol; else if (av->a_type == A_FLOAT && av->a_w.w_float == 0) *sp = &s_; else goto badarg; ac--; av++; } nsymbols++; sp++; } } switch (nsymbols) { case 0: return ((*(t_new0)(callthis)) (ff[0], ff[1], ff[2], ff[3], ff[4])); case 1: return ((*(t_new1)(callthis)) (ss[0], ff[0], ff[1], ff[2], ff[3], ff[4])); case 2: return ((*(t_new2)(callthis)) (ss[0], ss[1], ff[0], ff[1], ff[2], ff[3], ff[4])); case 3: return ((*(t_new3)(callthis)) (ss[0], ss[1], ss[2], ff[0], ff[1], ff[2], ff[3], ff[4])); case 4: return ((*(t_new4)(callthis)) (ss[0], ss[1], ss[2], ss[3], ff[0], ff[1], ff[2], ff[3], ff[4])); case 5: return ((*(t_new5)(callthis)) (ss[0], ss[1], ss[2], ss[3], ss[4], ff[0], ff[1], ff[2], ff[3], ff[4])); case 6: return ((*(t_new6)(callthis)) (ss[0], ss[1], ss[2], ss[3], ss[4], ss[5], ff[0], ff[1], ff[2], ff[3], ff[4])); } badarg: loud_error(0, "bad creation arguments for class '%s'", cname->s_name); return (0); } void fragile_class_printnames(char *msg, int firstndx, int lastndx) { t_methodentry *mp = pd_objectmaker->c_methods; int ndx, len = strlen(msg); startpost(msg); for (ndx = firstndx, mp += ndx; ndx <= lastndx; ndx++, mp++) { t_symbol *s = mp->me_name; if (s && s->s_name[0] != '_') { int l = 1 + strlen(s->s_name); if ((len += l) > 66) { endpost(); startpost(" "); len = 3 + l; } poststring(s->s_name); } } endpost(); } /* This structure is local to g_array.c. We need it, because there is no other way to get into array's graph. */ struct _garray { t_gobj x_gobj; t_glist *x_glist; /* ... */ }; t_glist *fragile_garray_glist(void *arr) { return (((struct _garray *)arr)->x_glist); } /* This is local to m_obj.c. LATER export write access to o_connections field ('grab' class). LATER encapsulate 'traverseoutlet' routines (not in the stable API yet). */ struct _outlet { t_object *o_owner; struct _outlet *o_next; t_outconnect *o_connections; t_symbol *o_sym; }; /* obj_starttraverseoutlet() replacement */ t_outconnect *fragile_outlet_connections(t_outlet *o) { return (o ? o->o_connections : 0); } t_outconnect *fragile_outlet_nextconnection(t_outconnect *last, t_object **destp, int *innop) { t_inlet *dummy; return (obj_nexttraverseoutlet(last, destp, &dummy, innop)); } /* silent, if caller is empty */ t_object *fragile_outlet_destination(t_outlet *op, int ntypes, t_symbol **types, t_pd *caller, char *errand) { t_object *booty = 0; t_symbol *badtype = 0; int count = 0; t_outconnect *tobooty = fragile_outlet_connections(op); while (tobooty) { t_object *ob; int inno; count++; tobooty = fragile_outlet_nextconnection(tobooty, &ob, &inno); if (ob && inno == 0) { /* LATER ask for class_getname()'s symbol version */ t_symbol **tp, *dsttype = gensym(class_getname(*(t_pd *)ob)); int i; for (i = 0, tp = types; i < ntypes; i++, tp++) { if (*tp == dsttype) { booty = ob; break; } else badtype = dsttype; } } } if (booty) { if (count > 1 && caller) loud_warning(caller, 0, "multiple targets"); } else if (caller) { if (badtype) loud_error(caller, "bad target type '%s'", badtype->s_name); else loud_error(caller, "no target"); if (errand) loud_errand(caller, errand); } return (booty); } /* These are local to m_obj.c. */ union inletunion { t_symbol *iu_symto; t_gpointer *iu_pointerslot; t_float *iu_floatslot; t_symbol **iu_symslot; t_sample iu_floatsignalvalue; }; struct _inlet { t_pd i_pd; struct _inlet *i_next; t_object *i_owner; t_pd *i_dest; t_symbol *i_symfrom; union inletunion i_un; }; /* simplified obj_findsignalscalar(), works for non-left inlets */ t_sample *fragile_inlet_signalscalar(t_inlet *i) { return (&i->i_un.iu_floatsignalvalue); } cyclone-0.1-alpha55/shared/unstable/loader.h0000644000076500007650000000100711466617453017436 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __LOADER_H__ #define __LOADER_H__ enum { LOADER_OK, LOADER_FAILED, LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY }; int unstable_load_lib(char *dirname, char *classname); int unstable_dirload_lib(char *dirname, char *classname); int unstable_dirload_all(char *dirname, int beloud, int withclasses); #endif cyclone-0.1-alpha55/shared/unstable/fringe.h0000644000076500007650000000050311466617453017442 0ustar hanshans/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __FRINGE_H__ #define __FRINGE_H__ void gobj_recreate(t_glist *gl, t_gobj *ob, t_binbuf *bb); #endif cyclone-0.1-alpha55/shared/unstable/loader.c0000644000076500007650000001214311466617453017434 0ustar hanshans/* Copyright (c) 1997-2005 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is just a not-yet-in-the-API-sys_load_lib() duplication (modulo differentiating the error return codes). LATER use the original. */ #ifdef __linux__ #include #endif #ifdef UNIX #include #include #endif #ifdef NT #include #include #endif #ifdef MACOSX #include #endif #include #include #include "m_pd.h" #include "common/loud.h" #include "common/os.h" #include "loader.h" typedef void (*t_xxx)(void); static char sys_dllextent[] = #ifdef __FreeBSD__ ".pd_freebsd"; #endif #ifdef IRIX #ifdef N32 ".pd_irix6"; #else ".pd_irix5"; #endif #endif #ifdef __linux__ ".pd_linux"; #endif #ifdef MACOSX ".pd_darwin"; #endif #ifdef NT ".dll"; #endif static int unstable_doload_lib(char *dirname, char *classname) { char symname[MAXPDSTRING], filename[MAXPDSTRING], *lastdot; void *dlobj; t_xxx makeout; #ifdef NT HINSTANCE ntdll; #endif /* refabricate the pathname */ strcpy(filename, dirname); strcat(filename, "/"); strcat(filename, classname); /* extract the setup function name */ if (lastdot = strrchr(classname, '.')) *lastdot = 0; #ifdef MACOSX strcpy(symname, "_"); strcat(symname, classname); #else strcpy(symname, classname); #endif /* if the last character is a tilde, replace with "_tilde" */ if (symname[strlen(symname) - 1] == '~') strcpy(symname + (strlen(symname) - 1), "_tilde"); /* and append _setup to form the C setup function name */ strcat(symname, "_setup"); #ifdef __linux__ dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); if (!dlobj) { post("%s: %s", filename, dlerror()); return (LOADER_BADFILE); } makeout = (t_xxx)dlsym(dlobj, symname); #endif #ifdef NT sys_bashfilename(filename, filename); ntdll = LoadLibrary(filename); if (!ntdll) { post("%s: couldn't load", filename); return (LOADER_BADFILE); } makeout = (t_xxx)GetProcAddress(ntdll, symname); #endif #ifdef MACOSX { NSObjectFileImage image; void *ret; NSSymbol s; if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess ) { post("%s: couldn't load", filename); return (LOADER_BADFILE); } ret = NSLinkModule( image, filename, NSLINKMODULE_OPTION_BINDNOW + NSLINKMODULE_OPTION_PRIVATE); s = NSLookupSymbolInModule(ret, symname); if (s) makeout = (t_xxx)NSAddressOfSymbol( s); else makeout = 0; } #endif if (!makeout) { post("load_object: Symbol \"%s\" not found", symname); return (LOADER_NOENTRY); } (*makeout)(); return (LOADER_OK); } /* start searching from dirname, then search the path */ int unstable_load_lib(char *dirname, char *classname) { char dirbuf[MAXPDSTRING], *nameptr; int fd; if ((fd = open_via_path(dirname, classname, sys_dllextent, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) { return (LOADER_NOFILE); } else { close(fd); return (unstable_doload_lib(dirbuf, nameptr)); } } /* only dirname is searched */ int unstable_dirload_lib(char *dirname, char *classname) { if (strlen(dirname) + strlen(classname) + strlen(sys_dllextent) + 3 < MAXPDSTRING) { char namebuf[MAXPDSTRING], *slash, *nameptr; strcpy(namebuf, dirname); if (*dirname && namebuf[strlen(namebuf)-1] != '/') strcat(namebuf, "/"); strcat(namebuf, classname); strcat(namebuf, sys_dllextent); slash = strrchr(namebuf, '/'); if (slash) { *slash = 0; nameptr = slash + 1; } else nameptr = namebuf; return (unstable_doload_lib(namebuf, nameptr)); } else return (LOADER_FAILED); } /* return the number of successfully loaded libraries, or -1 on error */ int unstable_dirload_all(char *dirname, int beloud, int withclasses) { t_osdir *dp = osdir_open(dirname); if (dp) { int result = 0; char namebuf[MAXPDSTRING], *name; osdir_setmode(dp, OSDIR_FILEMODE); while (name = osdir_next(dp)) { int namelen = strlen(name), extlen = strlen(sys_dllextent); if ((namelen -= extlen) > 0 && strcmp(name + namelen, sys_dllextent) == 0) { strncpy(namebuf, name, namelen); namebuf[namelen] = 0; if (zgetfn(&pd_objectmaker, gensym(namebuf))) { if (beloud) loud_warning(0, "xeq", "plugin \"%s\" already loaded", namebuf); } else { int err; if (beloud) post("loading xeq plugin \"%s\"", namebuf); err = unstable_dirload_lib(dirname, namebuf); if (err == LOADER_NOFILE) { if (beloud) loud_error(0, "xeq plugin \"%s\" disappeared", namebuf); } else if (!zgetfn(&pd_objectmaker, gensym(namebuf))) { if (beloud) loud_error(0, "library \"%s\" not compatible", namebuf); } else result++; } } } osdir_close(dp); return (result); } else { if (beloud) loud_syserror(0, "cannot open \"%s\"", dirname); return (-1); } } cyclone-0.1-alpha55/shared/unstable/standalone.h0000644000076500007650000000174711466617453020333 0ustar hanshans/* Copyright (c) 2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef MIXED_STANDALONE #error MIXED_STANDALONE not defined #else #ifndef __STANDALONE_H__ #define __STANDALONE_H__ typedef int t_int; typedef float t_float; typedef struct _symbol { char *s_name; void *s_thing; struct _symbol *s_next; } t_symbol; typedef union word { t_float w_float; t_symbol *w_symbol; int w_index; } t_word; typedef enum { A_NULL, A_FLOAT, A_SYMBOL, A_POINTER, A_SEMI, A_COMMA, A_DEFFLOAT, A_DEFSYM, A_DOLLAR, A_DOLLSYM, A_GIMME, A_CANT } t_atomtype; typedef struct _atom { t_atomtype a_type; union word a_w; } t_atom; void *getbytes(size_t nbytes); void *resizebytes(void *old, size_t oldsize, size_t newsize); void freebytes(void *fatso, size_t nbytes); t_symbol *gensym(char *s); #endif #endif cyclone-0.1-alpha55/shared/unstable/forky.c0000644000076500007650000000550211466617453017321 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* Put here compilation conditionals supporting older Pd versions. */ #include "m_pd.h" #include "g_canvas.h" #include "shared.h" #include "unstable/forky.h" #if FORKY_VERSION < 37 /* need this for t_class::c_wb field access */ #include "unstable/pd_imp.h" #endif #ifdef KRZYSZCZ //#define FORKY_DEBUG #endif t_pd *forky_newobject(t_symbol *s, int ac, t_atom *av) { #if FORKY_VERSION >= 37 typedmess(&pd_objectmaker, s, ac, av); return (pd_newest()); #else return (0); #endif } void forky_setsavefn(t_class *c, t_forkysavefn fn) { #if FORKY_VERSION >= 37 class_setsavefn(c, fn); #else if (c->c_wb->w_savefn) { /* cloning is necessary, because class_setwidget has not been called */ t_widgetbehavior *wb = getbytes(sizeof(*wb)); /* never freed */ #ifdef FORKY_DEBUG fprintf(stderr, "cloning widgetbehavior...\n"); #endif *wb = *c->c_wb; wb->w_savefn = fn; class_setwidget(c, wb); } else c->c_wb->w_savefn = fn; #endif } void forky_setpropertiesfn(t_class *c, t_forkypropertiesfn fn) { #if FORKY_VERSION >= 37 class_setpropertiesfn(c, fn); #else /* assuming wb has already been either cloned (in forky_setsavefn), or defined from scratch -- it is unlikely to ever need props without a specialized save (always be sure to set props after save, though). */ c->c_wb->w_propertiesfn = fn; #endif } /* To be called in a 'dsp' method -- e.g. if there are no feeders, the caller might use an optimized version of a 'perform' routine. LATER think about replacing 'linetraverser' calls with something faster. */ int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) { t_linetraverser t; linetraverser_start(&t, glist); while (linetraverser_next(&t)) if (t.tr_ob2 == x && t.tr_inno == inno #if FORKY_VERSION >= 36 && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) #endif ) return (1); return (0); } /* Not really a forky, just found no better place to put it in. Used in sickle's bitwise signal binops (which use forky_hasfeeders() too). Checked against msp2. */ t_int forky_getbitmask(int ac, t_atom *av) { t_int result = 0; if (sizeof(shared_t_bitmask) >= sizeof(t_int)) { int nbits = sizeof(t_int) * 8; shared_t_bitmask bitmask = 1 << (nbits - 1); if (ac > nbits) ac = nbits; while (ac--) { if (av->a_type == A_FLOAT && (int)av->a_w.w_float) /* CHECKED */ result |= bitmask; /* CHECKED symbols are zero */ bitmask >>= 1; av++; } /* CHECKED missing are zero */ #ifdef FORKY_DEBUG fprintf(stderr, "mask set to %.8x\n", result); #endif } else bug("sizeof(shared_t_bitmask)"); return (result); } cyclone-0.1-alpha55/shared/unstable/standalone.c0000644000076500007650000000353511466617453020323 0ustar hanshans/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* Parts of Pd API are duplicated here, as needed by standalone versions of Pd modules. LATER standalones should be linked to the Pd API library. */ #include #include #include #include "standalone.h" void *getbytes(size_t nbytes) { void *ret; if (nbytes < 1) nbytes = 1; ret = (void *)calloc(nbytes, 1); if (!ret) fprintf(stderr, "ERROR: getbytes() failed -- out of memory"); return (ret); } void *resizebytes(void *old, size_t oldsize, size_t newsize) { void *ret; if (newsize < 1) newsize = 1; if (oldsize < 1) oldsize = 1; ret = (void *)realloc((char *)old, newsize); if (newsize > oldsize && ret) memset(((char *)ret) + oldsize, 0, newsize - oldsize); if (!ret) fprintf(stderr, "ERROR: resizebytes() failed -- out of memory"); return (ret); } void freebytes(void *fatso, size_t nbytes) { free(fatso); } #define HASHSIZE 1024 static t_symbol *symhash[HASHSIZE]; static t_symbol *dogensym(char *s, t_symbol *oldsym) { t_symbol **sym1, *sym2; unsigned int hash1 = 0, hash2 = 0; int length = 0; char *s2 = s; while (*s2) { hash1 += *s2; hash2 += hash1; length++; s2++; } sym1 = symhash + (hash2 & (HASHSIZE-1)); while (sym2 = *sym1) { if (!strcmp(sym2->s_name, s)) return(sym2); sym1 = &sym2->s_next; } if (oldsym) sym2 = oldsym; else { sym2 = (t_symbol *)getbytes(sizeof(*sym2)); sym2->s_name = getbytes(length+1); sym2->s_next = 0; sym2->s_thing = 0; strcpy(sym2->s_name, s); } *sym1 = sym2; return (sym2); } t_symbol *gensym(char *s) { return(dogensym(s, 0)); } cyclone-0.1-alpha55/shared/unstable/Makefile0000644000076500007650000000010611466617453017456 0ustar hanshansROOT_DIR = ../.. include $(ROOT_DIR)/Makefile.common all: $(OBJECTS) cyclone-0.1-alpha55/shared/unstable/pd_imp.h0000644000076500007650000000427411466617453017451 0ustar hanshans/* Copyright (c) 1997-2003 Miller Puckette and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __PD_IMP_H__ #define __PD_IMP_H__ #ifdef PD_MINOR_VERSION /* 0.37 and up */ #include "m_imp.h" #else /* 0.36 and down */ typedef struct _methodentry { t_symbol *me_name; t_gotfn me_fun; t_atomtype me_arg[MAXPDARG+1]; } t_methodentry; EXTERN_STRUCT _widgetbehavior; typedef void (*t_bangmethod)(t_pd *x); typedef void (*t_pointermethod)(t_pd *x, t_gpointer *gp); typedef void (*t_floatmethod)(t_pd *x, t_float f); typedef void (*t_symbolmethod)(t_pd *x, t_symbol *s); typedef void (*t_listmethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); typedef void (*t_anymethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); struct _class { t_symbol *c_name; /* name (mostly for error reporting) */ t_symbol *c_helpname; /* name of help file */ size_t c_size; /* size of an instance */ t_methodentry *c_methods; /* methods other than bang, etc below */ int c_nmethod; /* number of methods */ t_method c_freemethod; /* function to call before freeing */ t_bangmethod c_bangmethod; /* common methods */ t_pointermethod c_pointermethod; t_floatmethod c_floatmethod; t_symbolmethod c_symbolmethod; t_listmethod c_listmethod; t_anymethod c_anymethod; struct _widgetbehavior *c_wb; /* "gobjs" only */ struct _parentwidgetbehavior *c_pwb;/* widget behavior in parent */ int c_floatsignalin; /* onset to float for signal input */ char c_gobj; /* true if is a gobj */ char c_patchable; /* true if we have a t_object header */ char c_firstin; /* if patchable, true if draw first inlet */ char c_drawcommand; /* a drawing command for a template */ }; EXTERN int obj_noutlets(t_object *x); EXTERN int obj_ninlets(t_object *x); EXTERN t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, int nout); EXTERN t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect, t_object **destp, t_inlet **inletp, int *whichp); #endif #endif cyclone-0.1-alpha55/shared/unstable/Makefile.sources0000644000076500007650000000007411466617453021144 0ustar hanshansOTHER_SOURCES = \ forky.c \ fragile.c \ fringe.c \ loader.c cyclone-0.1-alpha55/shared/unstable/fragile.h0000644000076500007650000000227211466617453017606 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __FRAGILE_H__ #define __FRAGILE_H__ t_symbol *fragile_class_getexterndir(t_class *c); int fragile_class_count(void); int fragile_class_getnames(t_atom *av, int maxnames); void fragile_class_raise(t_symbol *cname, t_newmethod thiscall); t_pd *fragile_class_mutate(t_symbol *cname, t_newmethod thiscall, int ac, t_atom *av); t_newmethod fragile_class_getalien(t_symbol *cname, t_newmethod thiscall, t_atomtype **argtypesp); t_pd *fragile_class_createobject(t_symbol *cname, t_newmethod callthis, t_atomtype *argtypes, int ac, t_atom *av); void fragile_class_printnames(char *msg, int firstndx, int lastndx); t_glist *fragile_garray_glist(void *arr); t_outconnect *fragile_outlet_connections(t_outlet *o); t_outconnect *fragile_outlet_nextconnection(t_outconnect *last, t_object **destp, int *innop); t_object *fragile_outlet_destination(t_outlet *op, int ntypes, t_symbol **types, t_pd *caller, char *errand); t_sample *fragile_inlet_signalscalar(t_inlet *i); #endif cyclone-0.1-alpha55/shared/notes.txt0000644000076500007650000000557411466617453016110 0ustar hanshansTODO for root and shared * fitter: abstraction-scoped, class-selective compatibility control * fitter: fittterstate map * hammerfile, hammergui: version control DONE for root and shared with cyclone alpha55 * new module: messtree * qtree: . nodes of a custom tree may be caller-owned: a caller may pass 0 as nodesize to qtree_initcustom() and pass pre-allocated nodes to insert/multiinsert calls . new calls: qtree_override(), qtree_closestunder(), qtree_closestover() . all "closest" calls report a diff between key requested and key found * os: new calls (dummy under MSW, though): osdir_open(), osdir_setmode(), osdir_close(), osdir_rewind(), osdir_next(), osdir_isfile(), osdir_isdir() * loader: new calls, unstable_dirload_lib(), unstable_dirload_all() * fitter: . added "test" hook (as a first step towards a fittterstate map) . new calls: fitter_getfloat(), fitter_getsymbol() * fragile: new call fragile_class_getexterndir() * loud: loud_syserror() accepts a format string * support for building into subdirectory of the main bin directory (so that a library may automatically load all its plugin externals) with toxy alpha18 * plusbob: stubifying t_plusbob, in order to minimize memory leak to 4 words with rafts prealpha1 * new module: patchvalue with toxy alpha17 * scriptlet: new call scriptlet_newalike() with cyclone alpha54 and toxy alpha16 * props: . code cleanup . new calls: props_getfirst(), props_getnext(), props_diff(), props_clearall(), props_clearvalues() . props_add(): additional argument 'filter' (skip exact input-filter copies) * fragile: new call fragile_class_getnames() * hammereditor: . hammereditor_append() accepts unbalanced braces . defaults to dirty, if (older) tk misses edit command with cyclone alpha53 * binport: added half-byte #symbol id * hammereditor: . fixed closing by window manager . dirty flag bound, shown and observed (unless in viewer mode) . title specification simplified and standardized . bug fix: incomplete transfer from editor with cyclone alpha52 * fragile: class name resolution based on voluntary mutation and raising * fitter: mirroring removed * new module, os: opening files, parsing path * hammerpanel: two modes of -initialdir persistence * more mingw fixes with cyclone alpha51 * new module, fitter: encapsulates compatibility support (formerly in maxmode) * fitter: per-class callback and mirroring interface to compatibility mode * mingw fixes with toxy alpha14 * scriptlet: version control (verslet_ routines) * debug printout restricted to krzYszcz, sent to stderr with cyclone alpha50 * bug fixes . hammertree crasher (affecting funbuff and offer) . MouseState/toxy clash * builds with gcc3 by default (no need to edit Makefile.common) * midi file code has been cleaned, now ready for using in qlist cyclone-0.1-alpha55/shared/shared.c0000644000076500007650000000042111466617453015613 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "shared.h" void shared_debug(void) { /* LATER */ } cyclone-0.1-alpha55/shared/toxy/0000755000076500007650000000000011466617452015206 5ustar hanshanscyclone-0.1-alpha55/shared/toxy/scriptlet.c0000644000076500007650000006222311466617452017370 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #ifdef UNIX #include #endif #ifdef NT #include #endif #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" #include "common/grow.h" #include "common/props.h" #include "scriptlet.h" #ifdef KRZYSZCZ //#define SCRIPTLET_DEBUG #endif #define SCRIPTLET_INISIZE 1024 #define SCRIPTLET_INIDOTSIZE 256 #define SCRIPTLET_MARGIN 64 #define SCRIPTLET_DOTMARGIN 16 /* cf SOCKSIZE in older versions of t_tkcmd.c, FIXME */ #define SCRIPTLET_MAXPUSH 20000 enum { SCRIPTLET_CVOK, SCRIPTLET_CVUNKNOWN, SCRIPTLET_CVMISSING }; #define VERSLET_MAXPACKAGE 32 #define VERSLET_MAXVERSION 32 typedef struct _verslet { t_pd *v_owner; char v_package[VERSLET_MAXPACKAGE]; char v_version[VERSLET_MAXVERSION]; } t_verslet; struct _scriptlet { t_pd *s_owner; t_glist *s_glist; /* containing glist (empty allowed) */ t_symbol *s_rptarget; /* reply target */ t_symbol *s_cbtarget; /* callback target */ t_symbol *s_item; /* item's name (readable part of its path) */ t_scriptlet_cvfn s_cvfn; /* if empty, passing resolveall is a bug */ t_canvas *s_cv; /* as returned by cvfn */ int s_cvstate; int s_locked; /* append lock, for filtering, when reading from file */ int s_size; char *s_buffer; char s_bufini[SCRIPTLET_INISIZE]; char *s_head; /* ptr to the command part of a scriptlet */ char *s_tail; char s_separator; /* current separator, set before a new token */ int s_dotsize; int s_dotoffset; char *s_dotbuffer; char s_dotbufini[SCRIPTLET_INIDOTSIZE]; }; static t_canvas *scriptlet_canvasvalidate(t_scriptlet *sp, int visedonly) { t_canvas *cv; if (sp->s_cvstate == SCRIPTLET_CVUNKNOWN) { if (sp->s_cvfn) cv = sp->s_cv = sp->s_cvfn(sp->s_owner); else { loudbug_bug("scriptlet_canvasvalidate"); return (0); } if (cv && (!visedonly || glist_isvisible(cv))) sp->s_cvstate = SCRIPTLET_CVOK; else sp->s_cvstate = SCRIPTLET_CVMISSING; } else cv = sp->s_cv; return (sp->s_cvstate == SCRIPTLET_CVOK ? cv : 0); } static int scriptlet_ready(t_scriptlet *sp) { int len = sp->s_tail - sp->s_head; if (len > 0 && *sp->s_head && sp->s_cvstate != SCRIPTLET_CVMISSING) { if (len < SCRIPTLET_MAXPUSH) return (1); else loud_error(sp->s_owner, "scriptlet too long to be pushed (%d bytes)", len); } return (0); } static int scriptlet_doappend(t_scriptlet *sp, char *buf) { if (buf && !sp->s_locked) { int nprefix = sp->s_head - sp->s_buffer; int nused = sp->s_tail - sp->s_buffer; int newsize = nused + strlen(buf) + SCRIPTLET_MARGIN; if (newsize > sp->s_size) { int nrequested = newsize; sp->s_buffer = grow_withdata(&nrequested, &nused, &sp->s_size, sp->s_buffer, SCRIPTLET_INISIZE, sp->s_bufini, sizeof(*sp->s_buffer)); if (nrequested != newsize) { scriptlet_reset(sp); return (0); } sp->s_head = sp->s_buffer + nprefix; sp->s_tail = sp->s_buffer + nused; } if (sp->s_separator && sp->s_tail > sp->s_head) *sp->s_tail++ = sp->s_separator; *sp->s_tail = 0; strcpy(sp->s_tail, buf); sp->s_tail += strlen(sp->s_tail); } sp->s_separator = 0; return (1); } static int scriptlet_dotstring(t_scriptlet *sp, char *st) { int len = strlen(st), newsize = sp->s_dotoffset + len + SCRIPTLET_DOTMARGIN; if (newsize > sp->s_dotsize) { int nrequested = newsize; sp->s_dotbuffer = grow_withdata(&nrequested, &sp->s_dotoffset, &sp->s_dotsize, sp->s_dotbuffer, SCRIPTLET_INIDOTSIZE, sp->s_dotbufini, sizeof(*sp->s_dotbuffer)); if (nrequested != newsize) { sp->s_dotoffset = 0; sp->s_dotbuffer[0] = 0; return (0); } } strcpy(sp->s_dotbuffer + sp->s_dotoffset, st); sp->s_dotoffset += len; return (1); } static int scriptlet_dotfloat(t_scriptlet *sp, float f) { char obuf[32]; sprintf(obuf, "%g", f); return (scriptlet_dotstring(sp, obuf)); } static char *scriptlet_dedot(t_scriptlet *sp, char *ibuf, int resolveall, int visedonly, int ac, t_atom *av, t_props *argprops) { int len = 0; char *obuf = sp->s_dotbuffer; sp->s_dotoffset = 0; switch (*ibuf) { case '#': if (resolveall) { int which = ibuf[1] - '1'; if (which >= 0 && which < 9) { if (which < ac) { av += which; if (av->a_type == A_FLOAT) sprintf(obuf, "%g", av->a_w.w_float); else if (av->a_type == A_SYMBOL && av->a_w.w_symbol) scriptlet_dotstring(sp, av->a_w.w_symbol->s_name); else obuf[0] = 0; /* LATER rethink */ } else strcpy(obuf, "0"); len = 2; } else if (!strncmp(&ibuf[1], "args", 4)) { if (ac) while (1) { if (av->a_type == A_FLOAT) scriptlet_dotfloat(sp, av->a_w.w_float); else if (av->a_type == A_SYMBOL && av->a_w.w_symbol) scriptlet_dotstring(sp, av->a_w.w_symbol->s_name); else { /* LATER rethink */ obuf[0] = 0; break; } ac--; av++; if (ac) sp->s_dotbuffer[sp->s_dotoffset++] = ' '; else break; } else obuf[0] = 0; len = 5; } else if (argprops) { char *iptr, *optr, c; int cnt; for (iptr = ibuf + 1, c = *iptr, cnt = 1; c; iptr++, c = *iptr, cnt++) { if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) { *iptr = 0; break; } } if (optr = props_getvalue(argprops, ibuf + 1)) { scriptlet_dotstring(sp, optr); len = cnt; } if (c) *iptr = c; } } break; case '-': if (resolveall && sp->s_item) { t_canvas *cv; if (cv = scriptlet_canvasvalidate(sp, visedonly)) { sprintf(obuf, ".x%x.c.%s%x", (int)cv, sp->s_item->s_name, (int)sp->s_owner); len = 1; } } break; case '^': if (resolveall) { t_canvas *cv; if (cv = scriptlet_canvasvalidate(sp, visedonly)) { sprintf(obuf, ".x%x", (int)cv); len = 1; } } break; case '|': if (resolveall) { strcpy(obuf, sp->s_cbtarget->s_name); len = 1; } break; case '~': /* FIXME, the dot-tilde stuff is purely experimental. */ if (resolveall) { t_canvas *cv; if (cv = scriptlet_canvasvalidate(sp, 0)) { t_glist *glist; if (!strncmp(&ibuf[1], "tag", 3)) { t_rtext *rt; glist = cv->gl_owner; if (glist && glist_isvisible(glist) && glist->gl_editor && (rt = glist_findrtext(glist, (t_object *)cv))) sprintf(obuf, "%s", rtext_gettag(rt)); else obuf[0] = 0; len = 4; } else if (!strncmp(&ibuf[1], "parent", 6)) { glist = cv->gl_owner; if (glist && glist_isvisible(glist)) sprintf(obuf, ".x%x", (int)glist); else obuf[0] = 0; len = 7; } else if (!strncmp(&ibuf[1], "root", 4)) { glist = canvas_getrootfor(cv); if (glist && glist_isvisible(glist)) sprintf(obuf, ".x%x", (int)glist); else obuf[0] = 0; len = 5; } else if (!strncmp(&ibuf[1], "owner", 5)) { if (glist = canvas_getrootfor(cv)) glist = glist->gl_owner; if (glist && glist_isvisible(glist)) sprintf(obuf, ".x%x", (int)glist); else obuf[0] = 0; len = 6; } else if (!strncmp(&ibuf[1], "top", 3)) { glist = cv; while (glist->gl_owner) glist = glist->gl_owner; if (glist && glist_isvisible(glist)) sprintf(obuf, ".x%x", (int)glist); else obuf[0] = 0; len = 4; } /* LATER find out when gl_ are updated, think how to better sync them to Tk. */ else if (!strncmp(&ibuf[1], "x1", 2)) { sprintf(obuf, "%d", cv->gl_screenx1); len = 3; } else if (!strncmp(&ibuf[1], "x2", 2)) { sprintf(obuf, "%d", cv->gl_screenx2); len = 3; } else if (!strncmp(&ibuf[1], "y1", 2)) { sprintf(obuf, "%d", cv->gl_screeny1); len = 3; } else if (!strncmp(&ibuf[1], "y2", 2)) { sprintf(obuf, "%d", cv->gl_screeny2); len = 3; } else if (!strncmp(&ibuf[1], "edit", 4)) { sprintf(obuf, "%d", cv->gl_edit); len = 5; } else if (!strncmp(&ibuf[1], "gop", 3)) { sprintf(obuf, "%d", glist_isgraph(cv)); len = 4; } else if (!strncmp(&ibuf[1], "dir", 3)) { sprintf(obuf, "%s", canvas_getdir(cv)->s_name); len = 4; } else loud_error(sp->s_owner, "bad field '%s'", &ibuf[1]); } } break; case '`': sprintf(obuf, "\\"); len = 1; break; case ':': sprintf(obuf, ";"); len = 1; break; case '(': sprintf(obuf, "{"); len = 1; break; case ')': sprintf(obuf, "}"); len = 1; break; case '<': if (resolveall) { if (ibuf[1] == ':') { sprintf(obuf, "{pd [concat "); len = 2; } else if (ibuf[1] == '|') { sprintf(obuf, "{pd [concat %s ", sp->s_rptarget->s_name); len = 2; } else { sprintf(obuf, "{pd [concat %s _cb ", sp->s_cbtarget->s_name); len = 1; } } break; case '>': if (resolveall) { sprintf(obuf, "\\;]}"); len = 1; } break; } return (len ? ibuf + len : 0); } int scriptlet_isempty(t_scriptlet *sp) { return (!(sp->s_tail > sp->s_head && *sp->s_head)); } void scriptlet_reset(t_scriptlet *sp) { sp->s_cvstate = SCRIPTLET_CVUNKNOWN; sp->s_locked = 0; sp->s_separator = 0; strcpy(sp->s_buffer, "namespace eval ::toxy {\ proc query {} {set ::toxy::reply [\n"); sp->s_head = sp->s_tail = sp->s_buffer + strlen(sp->s_buffer); } void scriptlet_prealloc(t_scriptlet *sp, int sz, int mayshrink) { if (sz < SCRIPTLET_INISIZE) sz = SCRIPTLET_INISIZE; if (sz < sp->s_size && mayshrink) { if (sp->s_buffer != sp->s_bufini) freebytes(sp->s_buffer, sp->s_size * sizeof(*sp->s_buffer)); else loudbug_bug("scriptlet_prealloc"); sp->s_size = SCRIPTLET_INISIZE; sp->s_buffer = sp->s_bufini; } if (sz > sp->s_size) sp->s_buffer = grow_nodata(&sz, &sp->s_size, sp->s_buffer, SCRIPTLET_INISIZE, sp->s_bufini, sizeof(*sp->s_buffer)); scriptlet_reset(sp); } static int scriptlet_addstring(t_scriptlet *sp, char *ibuf, int resolveall, int visedonly, int ac, t_atom *av, t_props *argprops) { int result = 1; char *bp = ibuf, *ep = ibuf, *ep1; if (!sp->s_separator) sp->s_separator = ' '; while (*ep) { if (*ep == '.' && (ep1 = scriptlet_dedot(sp, ep + 1, resolveall, visedonly, ac, av, argprops))) { *ep = 0; if (!(result = scriptlet_doappend(sp, bp))) break; *ep = '.'; if (!(result = scriptlet_doappend(sp, sp->s_dotbuffer))) break; bp = ep = ep1; } else ep++; } if (result) result = scriptlet_doappend(sp, bp); sp->s_separator = 0; return (result); } static int scriptlet_addfloat(t_scriptlet *sp, t_float f) { char buf[64]; if (!sp->s_separator) sp->s_separator = ' '; sprintf(buf, "%g", f); return (scriptlet_doappend(sp, buf)); } int scriptlet_add(t_scriptlet *sp, int resolveall, int visedonly, int ac, t_atom *av) { while (ac--) { int result = 1; if (av->a_type == A_SYMBOL) result = scriptlet_addstring(sp, av->a_w.w_symbol->s_name, resolveall, visedonly, 0, 0, 0); else if (av->a_type == A_FLOAT) result = scriptlet_addfloat(sp, av->a_w.w_float); if (!result) return (0); av++; } return (1); } void scriptlet_setseparator(t_scriptlet *sp, char c) { sp->s_separator = c; } void scriptlet_push(t_scriptlet *sp) { if (scriptlet_ready(sp)) { char *tail = sp->s_tail; strcpy(tail, "\n"); sys_gui(sp->s_head); *tail = 0; } } void scriptlet_qpush(t_scriptlet *sp) { if (scriptlet_ready(sp)) { char buf[MAXPDSTRING]; char *tail = sp->s_tail; /* Could not find any other way, than to postpone processing of the query, after everything which might have been glued to our tail, is evaluated. Otherwise, any command arriving later, during blocking of the query (e.g. in a Tk dialog), would be evaluated prior to our tail, via Tcl_DoOneEvent(). We postpone also the setup step (defining the query proc), in order to be able to handle several queries at once. All this is far from ideal -- the sequence "query this, tot that", is swapped, unless written as "query this, tot after 0 .(that.)", which is going to cause much confusion... LATER revisit. Do not forget, that since pd_readsocket() is not reentrant, sys_gui()d commands should never enter event loop directly by blocking on a dialog, vwait, etc., because the pd_readsocket handler is event-driven on unix. */ sys_gui("after 0 {\n"); strcpy(tail, "]}}\n"); sys_gui(sp->s_buffer); *tail = 0; sprintf(buf, "\ if {[info tclversion] < 8.4} {\n\ trace variable ::toxy::reply w \"::toxy::doreply %s\"\n\ } else {\n\ trace add variable ::toxy::reply write \"::toxy::doreply %s\"\n\ }\n\ ::toxy::query}\n", sp->s_rptarget->s_name, sp->s_rptarget->s_name); sys_gui(buf); } } /* Non-substituting -- LATER think if this is likely to cause any confusion. Especially, consider the widget_vis() vs. widget_update() case. */ void scriptlet_vpush(t_scriptlet *sp, char *varname) { if (scriptlet_ready(sp)) { char *tail = sp->s_tail; strcpy(tail, "}\n"); sys_vgui("set ::toxy::%s { ", varname); sys_gui(sp->s_head); *tail = 0; } } int scriptlet_evaluate(t_scriptlet *insp, t_scriptlet *outsp, int visedonly, int ac, t_atom *av, t_props *argprops) { if (scriptlet_ready(insp)) { t_atom *ap; int i; char *bp; char separator = 0; /* FIXME pregrowing of the transient scriptlet */ scriptlet_reset(outsp); /* LATER abstract this into scriptlet_parse() */ bp = insp->s_head; while (*bp) { if (*bp == '\n') separator = '\n'; else if (*bp == ' ' || *bp == '\t') { if (!separator) separator = ' '; } else { int done = 1; char *ep = bp; char c = ' '; while (*++ep) { if (*ep == ' ' || *bp == '\t' || *ep == '\n') { done = 0; c = *ep; *ep = 0; break; } } outsp->s_separator = separator; scriptlet_addstring(outsp, bp, 1, visedonly, ac, av, argprops); if (done) break; *ep = c; bp = ep; separator = (c == '\t' ? ' ' : c); } bp++; } return (outsp->s_cvstate != SCRIPTLET_CVMISSING); } else return (0); } /* utility function to be used in a comment-parsing callback */ char *scriptlet_nextword(char *buf) { while (*++buf) { if (*buf == ' ' || *buf == '\t') { char *ptr = buf + 1; while (*ptr == ' ' || *ptr == '\t') ptr++; *buf = 0; return (*ptr ? ptr : 0); } } return (0); } static t_verslet *verslet_new(t_pd *owner) { t_verslet *vp = getbytes(sizeof(*vp)); vp->v_owner = owner; vp->v_package[0] = 0; vp->v_version[0] = 0; return (vp); } static void verslet_free(t_verslet *vp) { freebytes(vp, sizeof(*vp)); } static void verslet_set(t_verslet *vp, char *pname, char *vname) { strncpy(vp->v_package, pname, VERSLET_MAXPACKAGE-1); vp->v_package[VERSLET_MAXPACKAGE-1] = 0; strncpy(vp->v_version, vname, VERSLET_MAXVERSION-1); vp->v_version[VERSLET_MAXVERSION-1] = 0; } static int verslet_parse(t_verslet *vp, char *buf, int multiline) { char *ptr = buf; int plen = 0; vp->v_package[0] = 0; vp->v_version[0] = 0; if (multiline) { while (*ptr) { while (*ptr == ' ' || *ptr == '\t') ptr++; if (strncmp(ptr, "package", 7)) { while (*ptr && *ptr != '\n') ptr++; if (*ptr) buf = ++ptr; } else break; } if (*ptr) ptr += 7; else ptr = 0; } else { while (*ptr == ' ' || *ptr == '\t') ptr++; if (strncmp(ptr, "package", 7)) ptr = 0; else ptr += 7; } if (ptr) { while (*ptr == ' ' || *ptr == '\t') ptr++; if (!strncmp(ptr, "provide", 7)) { ptr += 7; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr) { for (plen = 0; plen < VERSLET_MAXPACKAGE-1 && *ptr; plen++, ptr++) { if (*ptr == '\n' || *ptr == '\r') break; else if (*ptr == ' ' || *ptr == '\t') { vp->v_package[plen] = 0; #ifdef SCRIPTLET_DEBUG loudbug_post("package \"%s\"", vp->v_package); #endif while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr >= '0' && *ptr <= '9') { int vlen; for (vlen = 0; vlen < VERSLET_MAXVERSION-1 && *ptr; vlen++, ptr++) { if ((*ptr >= '0' && *ptr <= '9') || *ptr == '.') vp->v_version[vlen] = *ptr; else break; } if (vlen) { vp->v_version[vlen] = 0; #ifdef SCRIPTLET_DEBUG loudbug_post("version \"%s\"", vp->v_version); #endif return (1); } } break; } else vp->v_package[plen] = *ptr; } } } if (plen) loud_error(vp->v_owner, "incomplete scriptlet version declaration \"%s\"", buf); } return (0); } static int verslet_compare(t_verslet *vp1, t_verslet *vp2) { char *vname1 = vp1->v_version, *vname2 = vp2->v_version; while (*vname1 || *vname2) { int v1, v2; for (v1 = 0; *vname1 >= '0' && *vname1 <= '9'; vname1++) v1 = v1 * 10 + *vname1 - '0'; for (v2 = 0; *vname2 >= '0' && *vname2 <= '9'; vname2++) v2 = v2 * 10 + *vname2 - '0'; if (v1 < v2) return (-1); else if (v1 > v2) return (1); if (*vname1) { if (*vname1 == '.') *vname1++; if (*vname1 < '0' || *vname1 > '9') { loud_error(vp1->v_owner, "invalid version \"%s\"", vp1->v_version); while (*vname1) *vname1++; } } if (*vname2) { if (*vname2 == '.') *vname2++; if (*vname2 < '0' || *vname2 > '9') { loud_error(vp2->v_owner, "invalid version \"%s\"", vp2->v_version); while (*vname2) *vname2++; } } } return (0); } static int scriptlet_doread(t_scriptlet *sp, t_pd *caller, FILE *fp, char *rc, t_verslet *vcompare, char *builtin, t_scriptlet_cmntfn cmntfn) { t_scriptlet *outsp = sp, *newsp; t_verslet *vp; int vdiff = 0; char buf[MAXPDSTRING]; if (!caller) caller = sp->s_owner; vp = (vcompare ? verslet_new(caller) : 0); while ((fp && !feof(fp) && fgets(buf, MAXPDSTRING - 1, fp)) || builtin) { char *ptr; if (builtin) { int i; for (i = 0, ptr = buf; i < MAXPDSTRING - 1; i++, ptr++) { if ((*ptr = (*builtin ? *builtin : '\n')) == '\n') { ptr[1] = 0; if (*builtin) builtin++; if (!*builtin) builtin = 0; break; } else builtin++; } } else { for (ptr = buf; *ptr; ptr++) if (*ptr == '\r') *ptr = ' '; /* LATER rethink */ if (vp && verslet_parse(vp, buf, 0)) { if (vdiff = verslet_compare(vp, vcompare)) goto readfailed; else { verslet_free(vp); vp = 0; } } } ptr = buf; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr == '#') { if (cmntfn) { char sel = *++ptr; if (sel && sel != '\n') { ptr++; while (*ptr == ' ' || *ptr == '\t') ptr++; if (*ptr == '\n') *ptr = 0; if (*ptr) { char *ep = ptr + strlen(ptr) - 1; while (*ep == ' ' || *ep == '\t' || *ep == '\n') ep--; ep[1] = 0; } if (vp) goto readfailed; /* FIXME call a request cmntfn? */ newsp = cmntfn(caller, rc, sel, ptr); if (newsp == SCRIPTLET_UNLOCK) outsp->s_locked = 0; else if (newsp == SCRIPTLET_LOCK) outsp->s_locked = 1; else if (newsp != outsp) { outsp->s_locked = 0; outsp = newsp; } } } } else if (*ptr && *ptr != '\n') scriptlet_doappend(outsp, buf); } readfailed: outsp->s_locked = 0; if (vp) { verslet_free(vp); scriptlet_reset(sp); if (vdiff < 0) return (SCRIPTLET_OLDERVERSION); else if (vdiff > 0) return (SCRIPTLET_NEWERVERSION); else return (SCRIPTLET_NOVERSION); } else return (SCRIPTLET_OK); } /* Load particular section(s) from buffer (skip up to an unlocking comment, keep appending up to a locking comment, repeat). */ int scriptlet_rcparse(t_scriptlet *sp, t_pd *caller, char *rc, char *contents, t_scriptlet_cmntfn cmntfn) { int result; sp->s_locked = 1; /* see scriptlet_doread() above for unlocking scheme */ result = scriptlet_doread(sp, caller, 0, rc, 0, contents, cmntfn); return (result); } int scriptlet_rcload(t_scriptlet *sp, t_pd *caller, char *rc, char *ext, char *builtin, t_scriptlet_cmntfn cmntfn) { int result; char filename[MAXPDSTRING], buf[MAXPDSTRING], *nameptr, *dir; int fd; if (sp->s_glist) dir = canvas_getdir(sp->s_glist)->s_name; else dir = ""; /* which means pwd, usually the same as at Pd startup... */ if ((fd = open_via_path(dir, rc, ext, buf, &nameptr, MAXPDSTRING, 0)) < 0) { result = SCRIPTLET_NOFILE; } else { FILE *fp; close(fd); if (nameptr != buf) { strcpy(filename, buf); strcat(filename, "/"); strcat(filename, nameptr); sys_bashfilename(filename, filename); } else sys_bashfilename(nameptr, filename); if (fp = fopen(filename, "r")) { t_verslet *vp; if (builtin) { vp = verslet_new(sp->s_owner); if (!verslet_parse(vp, builtin, 1)) { loudbug_bug("scriptlet_rcload 1"); verslet_free(vp); vp = 0; } } else vp = 0; result = scriptlet_doread(sp, caller, fp, rc, vp, 0, cmntfn); fclose(fp); if (vp) verslet_free(vp); } else { loudbug_bug("scriptlet_rcload 2"); result = SCRIPTLET_NOFILE; } } if (result != SCRIPTLET_OK) { scriptlet_doread(sp, caller, 0, rc, 0, builtin, cmntfn); } return (result); } int scriptlet_read(t_scriptlet *sp, t_symbol *fn) { int result; FILE *fp; char buf[MAXPDSTRING]; post("loading scriptlet file \"%s\"", fn->s_name); /* FIXME use open_via_path() */ if (sp->s_glist) canvas_makefilename(sp->s_glist, fn->s_name, buf, MAXPDSTRING); else strncpy(buf, fn->s_name, MAXPDSTRING); sys_bashfilename(buf, buf); if (fp = fopen(buf, "r")) { scriptlet_reset(sp); result = scriptlet_doread(sp, 0, fp, 0, 0, 0, 0); fclose(fp); } else { loud_error(sp->s_owner, "error while loading file \"%s\"", fn->s_name); result = SCRIPTLET_NOFILE; } return (result); } int scriptlet_write(t_scriptlet *sp, t_symbol *fn) { int size = sp->s_tail - sp->s_head; if (size > 0 && *sp->s_head) { FILE *fp; char buf[MAXPDSTRING]; post("saving scriptlet file \"%s\"", fn->s_name); if (sp->s_glist) canvas_makefilename(sp->s_glist, fn->s_name, buf, MAXPDSTRING); else strncpy(buf, fn->s_name, MAXPDSTRING); sys_bashfilename(buf, buf); if (fp = fopen(buf, "w")) { int result = fwrite(sp->s_head, 1, size, fp); fclose(fp); if (result == size) return (SCRIPTLET_OK); } loud_error(sp->s_owner, "error while saving file \"%s\"", fn->s_name); return (fp ? SCRIPTLET_BADFILE : SCRIPTLET_NOFILE); } else { loud_warning(sp->s_owner, "scriptlet", "empty scriptlet not written"); return (SCRIPTLET_IGNORED); } } char *scriptlet_getcontents(t_scriptlet *sp, int *lenp) { *lenp = sp->s_tail - sp->s_head; return (sp->s_head); } char *scriptlet_getbuffer(t_scriptlet *sp, int *sizep) { *sizep = sp->s_size; return (sp->s_buffer); } void scriptlet_setowner(t_scriptlet *sp, t_pd *owner) { sp->s_owner = owner; } void scriptlet_clone(t_scriptlet *to, t_scriptlet *from) { scriptlet_reset(to); to->s_separator = ' '; /* LATER add a flag to optionally use from's buffer with refcount */ scriptlet_doappend(to, from->s_head); } void scriptlet_append(t_scriptlet *to, t_scriptlet *from) { to->s_separator = ' '; scriptlet_doappend(to, from->s_head); } void scriptlet_free(t_scriptlet *sp) { if (sp) { if (sp->s_buffer != sp->s_bufini) freebytes(sp->s_buffer, sp->s_size * sizeof(*sp->s_buffer)); if (sp->s_dotbuffer != sp->s_dotbufini) freebytes(sp->s_dotbuffer, sp->s_dotsize * sizeof(*sp->s_dotbuffer)); freebytes(sp, sizeof(*sp)); } } /* The parameter 'gl' (null accepted) is necessary, because the 's_glist' field, if implicitly set, would be dangerous (after a glist is gone) and confusing (current directory used for i/o of a global scriptlet). */ t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, t_symbol *item, t_glist *glist, t_scriptlet_cvfn cvfn) { t_scriptlet *sp = getbytes(sizeof(*sp)); if (sp) { static int configured = 0; if (!configured) { sys_gui("image create bitmap ::toxy::img::empty -data {}\n"); sys_gui("proc ::toxy::doreply {target vname vndx op} {\n"); sys_gui(" pd [concat $target _rp $::toxy::reply \\;]\n"); sys_gui(" unset ::toxy::reply\n"); sys_gui("}\n"); configured = 1; } sp->s_owner = owner; sp->s_glist = glist; sp->s_rptarget = rptarget; sp->s_cbtarget = cbtarget; sp->s_item = item; sp->s_cvfn = cvfn; sp->s_size = SCRIPTLET_INISIZE; sp->s_buffer = sp->s_bufini; sp->s_dotsize = SCRIPTLET_INIDOTSIZE; sp->s_dotoffset = 0; sp->s_dotbuffer = sp->s_dotbufini; scriptlet_reset(sp); } return (sp); } t_scriptlet *scriptlet_newalike(t_scriptlet *sp) { return (scriptlet_new(sp->s_owner, sp->s_rptarget, sp->s_cbtarget, sp->s_item, sp->s_glist, sp->s_cvfn)); } cyclone-0.1-alpha55/shared/toxy/Makefile.objects0000644000076500007650000000000011466617452020264 0ustar hanshanscyclone-0.1-alpha55/shared/toxy/scriptlet.h0000644000076500007650000000414411466617452017373 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __SCRIPTLET_H__ #define __SCRIPTLET_H__ enum { SCRIPTLET_OK = 0, SCRIPTLET_NOFILE, SCRIPTLET_BADFILE, SCRIPTLET_NOVERSION, SCRIPTLET_OLDERVERSION, SCRIPTLET_NEWERVERSION, SCRIPTLET_IGNORED }; #define SCRIPTLET_UNLOCK ((t_scriptlet *)0) #define SCRIPTLET_LOCK ((t_scriptlet *)1) EXTERN_STRUCT _scriptlet; #define t_scriptlet struct _scriptlet typedef t_canvas *(*t_scriptlet_cvfn)(t_pd *); typedef t_scriptlet *(*t_scriptlet_cmntfn)(t_pd *, char *, char, char *); int scriptlet_isempty(t_scriptlet *sp); void scriptlet_reset(t_scriptlet *sp); void scriptlet_prealloc(t_scriptlet *sp, int sz, int mayshrink); int scriptlet_add(t_scriptlet *sp, int resolveall, int visedonly, int ac, t_atom *av); void scriptlet_setseparator(t_scriptlet *sp, char c); void scriptlet_push(t_scriptlet *sp); void scriptlet_qpush(t_scriptlet *sp); void scriptlet_vpush(t_scriptlet *sp, char *varname); int scriptlet_evaluate(t_scriptlet *insp, t_scriptlet *outsp, int visedonly, int ac, t_atom *av, t_props *argprops); char *scriptlet_nextword(char *buf); int scriptlet_rcparse(t_scriptlet *sp, t_pd *caller, char *rc, char *contents, t_scriptlet_cmntfn cmntfn); int scriptlet_rcload(t_scriptlet *sp, t_pd *caller, char *rc, char *ext, char *builtin, t_scriptlet_cmntfn cmntfn); int scriptlet_read(t_scriptlet *sp, t_symbol *fn); int scriptlet_write(t_scriptlet *sp, t_symbol *fn); char *scriptlet_getcontents(t_scriptlet *sp, int *lenp); char *scriptlet_getbuffer(t_scriptlet *sp, int *sizep); void scriptlet_setowner(t_scriptlet *sp, t_pd *owner); void scriptlet_clone(t_scriptlet *to, t_scriptlet *from); void scriptlet_append(t_scriptlet *to, t_scriptlet *from); void scriptlet_free(t_scriptlet *sp); t_scriptlet *scriptlet_new(t_pd *owner, t_symbol *rptarget, t_symbol *cbtarget, t_symbol *item, t_glist *glist, t_scriptlet_cvfn cvfn); t_scriptlet *scriptlet_newalike(t_scriptlet *sp); #endif cyclone-0.1-alpha55/shared/toxy/plusbob.h0000644000076500007650000000515111466617452017027 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __PLUSBOB_H__ #define __PLUSBOB_H__ EXTERN_STRUCT _plustype; #define t_plustype struct _plustype EXTERN_STRUCT _plusbob; #define t_plusbob struct _plusbob EXTERN_STRUCT _plusenv; #define t_plusenv struct _plusenv /* LATER move to plusbob.c */ struct _plusbob { t_symbol *bob_stub; /* points back to stub = symbol, pointer-to-here */ t_plustype *bob_type; /* our type */ t_plustype *bob_root; /* our base type directly derived from t_plusbob */ t_pd *bob_owner; int bob_refcount; int bob_dorefcount; t_plusbob *bob_children; /* empty, unless we are a parent */ /* each bob has exactly one parent, unless being a special, `orphan' case */ t_plusbob *bob_parent; t_plusbob *bob_prev; /* younger brother */ t_plusbob *bob_next; /* older sister */ }; struct _plusenv { t_plusbob env_bob; t_symbol *env_id; /* LATER use local symbol namespace */ }; #define PLUSBOB_OWNER ((t_pd *)-1) typedef void (*t_plustypefn)(void *); t_plusbob *plustag_isvalid(t_symbol *tag, t_pd *caller); t_plusbob *plustag_validtype(t_symbol *tag, t_symbol *tname, t_pd *caller); t_plusbob *plustag_validroot(t_symbol *tag, t_symbol *rname, t_pd *caller); t_symbol *plustag_typename(t_symbol *tag, int validate, t_pd *caller); t_symbol *plustag_rootname(t_symbol *tag, int validate, t_pd *caller); t_plustype *plustype_new(t_plustype *base, t_symbol *name, size_t sz, t_plustypefn deletefn, t_plustypefn preservefn, t_plustypefn releasefn, t_plustypefn attachfn); t_plusbob *plusbob_create(t_plustype *tp, t_plusbob *parent); void plusbob_preserve(t_plusbob *bob); void plusbob_release(t_plusbob *bob); t_plusbob *plusbob_getparent(t_plusbob *bob); void plusbob_attach(t_plusbob *bob, t_plusbob *newparent); t_plusbob *plusbob_getnext(t_plusbob *bob); t_plusbob *plusbob_getchildren(t_plusbob *bob); void plusbob_detachchildren(t_plusbob *bob, t_plusbob *newparent); void plusbob_detachownedchildren(t_plusbob *bob, t_plusbob *newparent, t_pd *owner); void plusbob_setowner(t_plusbob *bob, t_pd *owner); t_pd *plusbob_getowner(t_plusbob *bob); void outlet_plusbob(t_outlet *o, t_plusbob *bob); t_plusenv *plusenv_create(t_plustype *tp, t_plusbob *parent, t_symbol *id); t_plusenv *plusenv_find(t_symbol *id, t_plusenv *defenv); t_symbol *plusenv_getid(t_plusenv *env); t_plusbob *plusenv_getparent(t_plustype *tp); t_plustype *plusenv_setup(void); #endif cyclone-0.1-alpha55/shared/toxy/plusbob.c0000644000076500007650000002576211466617452017034 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/loud.h" #include "plusbob.h" #ifdef KRZYSZCZ //#define PLUSBOB_DEBUG #endif /* The main failure of the current implementation is when a foreign object stores a faked symbol beyond lifetime of a wrappee. There is no obvious way of protecting against stale pointers, other than leaking small portions of memory (four words) with every new faked symbol. In case of plustot, this is not a very big deal, since for each [+tot] object the number of wrapped tcl objects is small and constant. Another failure is when a foreign object binds something to a faked symbol (for example, when a faked symbol is passed to an array's rename method). This should not happen in usual contexts, and even if it does, it will unlikely cause any real harm. LATER let there be a choice of using either fake-symbols, or gpointers. The gpointer layout would be such: gs_un points to a plusbob-like structure (without the bob_stub field), a unique integer code has to be reserved for gs_which, the fields gp_un and gp_valid are ignored. Using bob_refcount instead of gs_refcount is likely to simplify code. */ typedef struct _plusstub { t_symbol sb_tag; /* common value for all bob types */ t_plusbob *sb_bob; } t_plusstub; /* Currently, objects of all +bob types are tagged with the same name: */ static char plustag_name[] = "+bob"; static void plustag_init(t_symbol *tag) { tag->s_name = plustag_name; tag->s_thing = 0; tag->s_next = 0; } /* returns tagged +bob if valid, null otherwise (silent if caller is empty) */ t_plusbob *plustag_isvalid(t_symbol *tag, t_pd *caller) { if (tag->s_name == plustag_name) return (((t_plusstub *)tag)->sb_bob); else if (caller) { if (strcmp(tag->s_name, plustag_name)) loud_error((caller == PLUSBOB_OWNER ? 0 : caller), "does not understand '%s' (check object connections)", tag->s_name); else loud_error((caller == PLUSBOB_OWNER ? 0 : caller), "confused..."); } return (0); } static t_plusstub *plusstub_create(t_plusbob *bob) { t_plusstub *stub = getbytes(sizeof(*stub)); plustag_init(&stub->sb_tag); stub->sb_bob = bob; return (stub); } /* +bob is an object tossed around, a bobbing object. Currently, this is a wrapping for Tcl_Interp, Tcl_Obj, or a tcl variable, but the +bob interface is abstract enough to be suitable for other types of objects. The t_plusbob is kind of a virtual base. */ struct _plustype { t_plustype *tp_base; /* empty, if directly derived from t_plusbob */ t_symbol *tp_name; size_t tp_size; /* constructor is to be called explicitly, from derived constructors, or from a public wrapper. */ t_plustypefn tp_deletefn; /* destructor */ t_plustypefn tp_preservefn; t_plustypefn tp_releasefn; t_plustypefn tp_attachfn; }; static t_plustype *plustype_default = 0; t_plustype *plustype_new(t_plustype *base, t_symbol *name, size_t sz, t_plustypefn deletefn, t_plustypefn preservefn, t_plustypefn releasefn, t_plustypefn attachfn) { t_plustype *tp = getbytes(sizeof(*tp)); tp->tp_base = base; tp->tp_name = name; tp->tp_size = sz; tp->tp_deletefn = deletefn; tp->tp_preservefn = preservefn; tp->tp_releasefn = releasefn; tp->tp_attachfn = attachfn; return (tp); } static void plusbob_doattach(t_plusbob *bob, t_plusbob *parent) { if (bob->bob_parent = parent) { /* become the youngest child: */ bob->bob_prev = 0; if (bob->bob_next = parent->bob_children) { if (parent->bob_children->bob_prev) loudbug_bug("plusbob_doattach 1"); parent->bob_children->bob_prev = bob; } parent->bob_children = bob; } else loudbug_bug("plusbob_doattach 2"); } static void plusbob_dodetach(t_plusbob *bob) { if (bob->bob_parent) { if (bob->bob_prev) { if (bob == bob->bob_parent->bob_children) loudbug_bug("plusbob_dodetach 1"); bob->bob_prev->bob_next = bob->bob_next; } if (bob->bob_next) bob->bob_next->bob_prev = bob->bob_prev; if (bob == bob->bob_parent->bob_children) bob->bob_parent->bob_children = bob->bob_next; } else loudbug_bug("plusbob_dodetach 2"); } /* To be called from derived constructors. Preserving is caller's responsibility. */ t_plusbob *plusbob_create(t_plustype *tp, t_plusbob *parent) { t_plusbob *bob; if (!tp) { if (!plustype_default) plustype_default = plustype_new(0, 0, sizeof(t_plusbob), 0, 0, 0, 0); tp = plustype_default; } if (bob = getbytes(tp->tp_size)) { bob->bob_stub = (t_symbol *)plusstub_create(bob); bob->bob_type = tp; while (tp->tp_base) tp = tp->tp_base; bob->bob_root = tp; bob->bob_owner = 0; bob->bob_refcount = 0; bob->bob_dorefcount = 1; bob->bob_children = 0; if (parent) plusbob_doattach(bob, parent); else bob->bob_parent = 0; } return (bob); } /* Should never be called, but from plusbob_release(). Calling from a derived destructor is illegal. */ static void plusbob_free(t_plusbob *bob) { t_plustype *tp; if (bob->bob_parent) plusbob_dodetach(bob); for (tp = bob->bob_type; tp; tp = tp->tp_base) if (tp->tp_deletefn) (*tp->tp_deletefn)(bob); freebytes(bob, (bob->bob_type ? bob->bob_type->tp_size : sizeof(*bob))); /* the stub remains... */ } void plusbob_preserve(t_plusbob *bob) { if (bob->bob_dorefcount) { t_plustype *tp; for (tp = bob->bob_type; tp; tp = tp->tp_base) if (tp->tp_preservefn) (*tp->tp_preservefn)(bob); bob->bob_refcount++; } } void plusbob_release(t_plusbob *bob) { if (bob->bob_dorefcount) { t_plustype *tp; for (tp = bob->bob_type; tp; tp = tp->tp_base) if (tp->tp_releasefn) (*tp->tp_releasefn)(bob); if (--bob->bob_refcount <= 0) { if (bob->bob_refcount == 0) plusbob_free(bob); else loudbug_bug("plusbob_release"); } } } t_plusbob *plusbob_getparent(t_plusbob *bob) { return (bob->bob_parent); } /* To be called for redirection only. Bobs created as orphans are a special case, and cannot be attached later on. Likewise, changing non-orphan bobs to orphans is illegal. */ void plusbob_attach(t_plusbob *bob, t_plusbob *newparent) { if (bob->bob_parent && newparent) { t_plustype *tp; plusbob_dodetach(bob); plusbob_doattach(bob, newparent); for (tp = bob->bob_type; tp; tp = tp->tp_base) if (tp->tp_attachfn) (*tp->tp_attachfn)(bob); } else if (newparent) loudbug_bug("plusbob_attach 1"); else loudbug_bug("plusbob_attach 2"); } t_plusbob *plusbob_getnext(t_plusbob *bob) { return (bob->bob_next); } t_plusbob *plusbob_getchildren(t_plusbob *bob) { return (bob->bob_children); } /* Redirect all bobs to a replacement parent. Assuming replacement exists. */ void plusbob_detachchildren(t_plusbob *bob, t_plusbob *newparent) { while (bob->bob_children) plusbob_attach(bob->bob_children, newparent); } void plusbob_detachownedchildren(t_plusbob *bob, t_plusbob *newparent, t_pd *owner) { t_plusbob *child = bob->bob_children, *next; while (child) { next = child->bob_next; if (child->bob_owner == owner) plusbob_attach(child, newparent); child = next; } } void plusbob_setowner(t_plusbob *bob, t_pd *owner) { bob->bob_owner = owner; } t_pd *plusbob_getowner(t_plusbob *bob) { return (bob->bob_owner); } void outlet_plusbob(t_outlet *o, t_plusbob *bob) { outlet_symbol(o, bob->bob_stub); } /* returns tagged +bob if valid, null otherwise (silent if caller is empty) */ t_plusbob *plustag_validtype(t_symbol *tag, t_symbol *tname, t_pd *caller) { if (tag->s_name == plustag_name) { t_plusbob *bob = ((t_plusstub *)tag)->sb_bob; if (bob->bob_type->tp_name == tname) return (bob); else if (caller) { t_symbol *s = bob->bob_type->tp_name; loud_error((caller == PLUSBOB_OWNER ? bob->bob_owner : caller), "invalid type '%s' ('%s' expected)", (s ? s->s_name : ""), (tname ? tname->s_name : "")); } } else if (plustag_isvalid(tag, caller)) /* print the error there */ loudbug_bug("plustag_validtype"); return (0); } /* returns tagged +bob if valid, null otherwise (silent if caller is empty) */ t_plusbob *plustag_validroot(t_symbol *tag, t_symbol *rname, t_pd *caller) { if (tag->s_name == plustag_name) { t_plusbob *bob = ((t_plusstub *)tag)->sb_bob; if (bob->bob_root->tp_name == rname) return (bob); else if (caller) { t_symbol *s = bob->bob_root->tp_name; loud_error((caller == PLUSBOB_OWNER ? bob->bob_owner : caller), "invalid base type '%s' ('%s' expected)", (s ? s->s_name : ""), (rname ? rname->s_name : "")); } } else if (plustag_isvalid(tag, caller)) /* print the error there */ loudbug_bug("plustag_validroot"); return (0); } t_symbol *plustag_typename(t_symbol *tag, int validate, t_pd *caller) { if (!validate || tag->s_name == plustag_name) return (((t_plusstub *)tag)->sb_bob->bob_type->tp_name); else if (plustag_isvalid(tag, caller)) /* print the error there */ loudbug_bug("plustag_typename"); return (0); } t_symbol *plustag_rootname(t_symbol *tag, int validate, t_pd *caller) { if (!validate || tag->s_name == plustag_name) return (((t_plusstub *)tag)->sb_bob->bob_root->tp_name); else if (plustag_isvalid(tag, caller)) /* print the error there */ loudbug_bug("plustag_rootname"); return (0); } /* Plusenv (aka +env) is the base for an `environment' +bob. Environment encapsulates data common for a collection of +bobs. This is the standard way of grouping +bobs, according to a parent/children relationship. */ static t_plustype *plusenv_type = 0; static t_plusbob *plusenv_parent = 0; /* the parent of all environments */ /* To be called from derived constructors (or, LATER, plusenv's provider). */ t_plusenv *plusenv_create(t_plustype *tp, t_plusbob *parent, t_symbol *id) { t_plusenv *env = 0; if (env = (t_plusenv *)plusbob_create(tp, parent)) { if (!id) /* LATER design a public interface for bob_dorefcount */ ((t_plusbob *)env)->bob_dorefcount = 0; env->env_id = id; /* LATER rethink */ } return (env); } t_plusenv *plusenv_find(t_symbol *id, t_plusenv *defenv) { if (plusenv_parent && id) { t_plusbob *bob; for (bob = plusenv_parent->bob_children; bob; bob = bob->bob_next) if (((t_plusenv *)bob)->env_id == id) break; return ((t_plusenv *)bob); } else return (defenv); } t_symbol *plusenv_getid(t_plusenv *env) { return (env->env_id); } /* Type ignored, LATER rethink. */ t_plusbob *plusenv_getparent(t_plustype *tp) { if (!plusenv_parent) plusenv_parent = plusbob_create(0, 0); return (plusenv_parent); } t_plustype *plusenv_setup(void) { if (!plusenv_type) { plusenv_type = plustype_new(0, gensym("+env"), sizeof(t_plusenv), 0, 0, 0, 0); } return (plusenv_type); } cyclone-0.1-alpha55/shared/toxy/Makefile0000644000076500007650000000010611466617452016643 0ustar hanshansROOT_DIR = ../.. include $(ROOT_DIR)/Makefile.common all: $(OBJECTS) cyclone-0.1-alpha55/shared/toxy/Makefile.sources0000644000076500007650000000005211466617452020325 0ustar hanshansOTHER_SOURCES = \ scriptlet.c \ plusbob.c cyclone-0.1-alpha55/shared/getridof.baddeps0000644000076500007650000000155311466617453017337 0ustar hanshansThis is the list of all dependencies among miXed/shared objects. Some are inevitable, but others can, and should be removed. unstable/fragile -> common/loud unstable/fringe -> unstable/forky unstable/loader -> common/os common/loud common/props -> common/grow common/loud common/vefl -> common/loud, unstable/fragile common/messtree -> common/loud common/qtree -> common/loud common/binport -> common/lex common/port -> common/loud, common/grow, common/binport, unstable/forky, unstable/fragile, unstable/fringe hammer/file -> common/os unstable/forky sickle/sic -> common/loud sickle/arsic -> common/loud, common/vefl, sickle/sic, unstable/fragile toxy/plusbob -> common/loud toxy/scriptlet -> common/loud, common/grow, common/props xeq/squ* -> common/loud, common/dict, common/qtree, common/messtree, common/mifi, xeq/squ* vex/hyphen -> common/dict vex/sofi -> vex/bifi cyclone-0.1-alpha55/shared/Makefile0000644000076500007650000000006211466617453015642 0ustar hanshansROOT_DIR = .. include $(ROOT_DIR)/Makefile.common cyclone-0.1-alpha55/shared/Makefile.dirs0000644000076500007650000000006011466617453016600 0ustar hanshansMIXED_DIRS = common hammer sickle toxy unstable cyclone-0.1-alpha55/shared/hammer/0000755000076500007650000000000011466617452015454 5ustar hanshanscyclone-0.1-alpha55/shared/hammer/tree.c0000644000076500007650000004751111466617452016567 0ustar hanshans/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "hammer/tree.h" /* Since there is no sentinel node, the deletion routine has to have a few extra checks. LATER rethink. */ /* LATER freelist */ typedef t_hammernode *(*t_hammertree_inserthook)(t_hammernode *); #ifdef HAMMERTREE_DEBUG /* returns black-height or 0 if failed */ static int hammernode_verify(t_hammernode *np) { if (np) { int bhl, bhr; if (((bhl = hammernode_verify(np->n_left)) == 0) || ((bhr = hammernode_verify(np->n_right)) == 0)) return (0); if (bhl != bhr) { /* failure: two paths rooted in the same node contain different number of black nodes */ bug("hammernode_verify: not balanced"); return (0); } if (np->n_black) return (bhl + 1); else { if ((np->n_left && !np->n_left->n_black) || (np->n_right && !np->n_right->n_black)) { bug("hammernode_verify: adjacent red nodes"); return (0); } return (bhl); } } else return (1); } /* returns black-height or 0 if failed */ static int hammertree_verify(t_hammertree *tree) { return (hammernode_verify(tree->t_root)); } static int hammernode_checkmulti(t_hammernode *np1, t_hammernode *np2) { if (np1 && np2 && np1->n_key == np2->n_key) { if (np1 == np2) bug("hammernode_checkmulti"); else return (1); } return (0); } static void hammernode_post(t_hammertree *tree, t_hammernode *np, t_hammernode_vshowhook hook, char *message) { startpost("%d ", np->n_key); if (tree->t_valuetype == HAMMERTYPE_FLOAT) startpost("%g ", HAMMERNODE_GETFLOAT(np)); else if (tree->t_valuetype == HAMMERTYPE_SYMBOL) startpost("%s ", HAMMERNODE_GETSYMBOL(np)->s_name); else if (tree->t_valuetype == HAMMERTYPE_ATOM) { t_atom *ap = HAMMERNODE_GETATOMPTR(np); if (ap->a_type == A_FLOAT) startpost("%g ", ap->a_w.w_float); else if (ap->a_type == A_SYMBOL) startpost("%s ", ap->a_w.w_symbol->s_name); } else if (hook) { char buf[MAXPDSTRING]; (*hook)(np, buf, MAXPDSTRING); startpost("%s ", buf); } else startpost("0x%08x ", (int)HAMMERNODE_GETSYMBOL(np)); startpost("%s ", (np->n_black ? "black" : "red")); if (hammernode_checkmulti(np, np->n_parent) || hammernode_checkmulti(np, np->n_left) || hammernode_checkmulti(np, np->n_right) || hammernode_checkmulti(np->n_parent, np->n_left) || hammernode_checkmulti(np->n_parent, np->n_right) || hammernode_checkmulti(np->n_left, np->n_right)) startpost("multi "); if (np->n_parent) startpost("(%d -> ", np->n_parent->n_key); else startpost("(nul -> "); if (np->n_left) startpost("%d, ", np->n_left->n_key); else startpost("nul, "); if (np->n_right) startpost("%d)", np->n_right->n_key); else startpost("nul)"); if (message) post(": %s", message); else endpost(); } /* Assert a standard stackless traversal producing the same sequence, as the auxiliary list. */ static int hammertree_checktraversal(t_hammertree *tree) { t_hammernode *treewalk = tree->t_root; t_hammernode *listwalk = tree->t_first; int count = 0; while (treewalk) { t_hammernode *prev = treewalk->n_left; if (prev) { while (prev->n_right && prev->n_right != treewalk) prev = prev->n_right; if (prev->n_right) { prev->n_right = 0; count++; if (treewalk == listwalk) listwalk = listwalk->n_next; else { bug("hammertree_checktraversal 1"); hammernode_post(tree, treewalk, 0, "treewalk"); if (listwalk) hammernode_post(tree, listwalk, 0, "listwalk"); else post("empty listwalk pointer"); listwalk = treewalk; } treewalk = treewalk->n_right; } else { prev->n_right = treewalk; treewalk = treewalk->n_left; } } else { count++; if (treewalk == listwalk) listwalk = listwalk->n_next; else { bug("hammertree_checktraversal 2"); hammernode_post(tree, treewalk, 0, "treewalk"); if (listwalk) hammernode_post(tree, listwalk, 0, "listwalk"); else post("empty listwalk pointer"); listwalk = treewalk; } treewalk = treewalk->n_right; } } return (count); } static int hammernode_height(t_hammernode *np) { if (np) { int lh = hammernode_height(np->n_left); int rh = hammernode_height(np->n_right); return (lh > rh ? lh + 1 : rh + 1); } else return (0); } void hammertree_debug(t_hammertree *tree, int level, t_hammernode_vshowhook hook) { t_hammernode *np; int count; post("------------------------"); count = hammertree_checktraversal(tree); if (level) { for (np = tree->t_first; np; np = np->n_next) hammernode_post(tree, np, hook, 0); if (level > 1) { post("************"); for (np = tree->t_last; np; np = np->n_prev) startpost("%d ", np->n_key); endpost(); } } if (tree->t_root) { t_hammernode *first = tree->t_root, *last = tree->t_root; while (first->n_left && first->n_left != tree->t_root) first = first->n_left; while (last->n_right && last->n_right != tree->t_root) last = last->n_right; post("count %d, height %d, root %d", count, hammernode_height(tree->t_root), tree->t_root->n_key); post("first %d, root->left* %d, last %d, root->right* %d", (tree->t_first ? tree->t_first->n_key : 0), first->n_key, (tree->t_last ? tree->t_last->n_key : 0), last->n_key); } else post("empty"); post("...verified (black-height is %d)", hammertree_verify(tree)); post("------------------------"); } #endif /* assuming that target node (np->n_right) exists */ static void hammertree_lrotate(t_hammertree *tree, t_hammernode *np) { t_hammernode *target = np->n_right; if (np->n_right = target->n_left) np->n_right->n_parent = np; if (!(target->n_parent = np->n_parent)) tree->t_root = target; else if (np == np->n_parent->n_left) np->n_parent->n_left = target; else np->n_parent->n_right = target; target->n_left = np; np->n_parent = target; } /* assuming that target node (np->n_left) exists */ static void hammertree_rrotate(t_hammertree *tree, t_hammernode *np) { t_hammernode *target = np->n_left; if (np->n_left = target->n_right) np->n_left->n_parent = np; if (!(target->n_parent = np->n_parent)) tree->t_root = target; else if (np == np->n_parent->n_left) np->n_parent->n_left = target; else np->n_parent->n_right = target; target->n_right = np; np->n_parent = target; } static t_hammernode *hammertree_preinserthook(t_hammernode *np) { while (np->n_prev && np->n_prev->n_key == np->n_key) np = np->n_prev; if (np->n_left) { np = np->n_prev; if (np->n_right) { /* LATER revisit */ bug("hammertree_preinserthook"); return (0); /* do nothing */ } } return (np); } static t_hammernode *hammertree_postinserthook(t_hammernode *np) { while (np->n_next && np->n_next->n_key == np->n_key) np = np->n_next; if (np->n_right) { np = np->n_next; if (np->n_left) { /* LATER revisit */ bug("hammertree_postinserthook"); return (0); /* do nothing */ } } return (np); } /* Returns a newly inserted or already existing node (or 0 if allocation failed). A caller is responsible for assigning a value. If hook is supplied, it is called iff key is found. In case of key being found (which means foundp returns 1), a new node is inserted, unless hook is either empty, or returns null. Hook's nonempty return is the parent for the new node. It is expected to have no more than one child. */ static t_hammernode *hammertree_doinsert(t_hammertree *tree, int key, t_hammertree_inserthook hook, int *foundp) { t_hammernode *np, *parent, *result; int leftchild; *foundp = 0; if (!(np = tree->t_root)) { if (!(np = getbytes(tree->t_nodesize))) return (0); np->n_key = key; np->n_black = 1; tree->t_root = tree->t_first = tree->t_last = np; return (np); } do { if (np->n_key == key) { *foundp = 1; if (hook && (parent = (*hook)(np))) { if (parent->n_left && parent->n_right) { bug("hammertree_insert, callback return 1"); parent = parent->n_next; } if (leftchild = (key < parent->n_key)) { if (parent->n_left) { bug("hammertree_insert, callback return 2"); leftchild = 0; } } else if (parent->n_right) leftchild = 1; goto addit; } else return (np); /* a caller may then keep or replace the value */ } else parent = np; } while (np = (key < np->n_key ? np->n_left : np->n_right)); leftchild = (key < parent->n_key); addit: /* parent has no more than one child, new node becomes parent's immediate successor or predecessor */ if (!(np = getbytes(tree->t_nodesize))) return (0); np->n_key = key; np->n_parent = parent; if (leftchild) { parent->n_left = np; /* update the auxiliary linked list structure */ np->n_next = parent; if (np->n_prev = parent->n_prev) np->n_prev->n_next = np; else tree->t_first = np; parent->n_prev = np; } else { parent->n_right = np; /* update the auxiliary linked list structure */ np->n_prev = parent; if (np->n_next = parent->n_next) np->n_next->n_prev = np; else tree->t_last = np; parent->n_next = np; } result = np; /* balance the tree -- LATER clean this if possible... */ np->n_black = 0; while (np != tree->t_root && !np->n_parent->n_black) { t_hammernode *uncle; /* np->n_parent->n_parent exists (we always paint root node in black) */ if (np->n_parent == np->n_parent->n_parent->n_left) { uncle = np->n_parent->n_parent->n_right; if (!uncle /* (sentinel not used) */ || uncle->n_black) { if (np == np->n_parent->n_right) { np = np->n_parent; hammertree_lrotate(tree, np); } np->n_parent->n_black = 1; np->n_parent->n_parent->n_black = 0; hammertree_rrotate(tree, np->n_parent->n_parent); } else { np->n_parent->n_black = 1; uncle->n_black = 1; np = np->n_parent->n_parent; np->n_black = 0; } } else { uncle = np->n_parent->n_parent->n_left; if (!uncle /* (sentinel not used) */ || uncle->n_black) { if (np == np->n_parent->n_left) { np = np->n_parent; hammertree_rrotate(tree, np); } np->n_parent->n_black = 1; np->n_parent->n_parent->n_black = 0; hammertree_lrotate(tree, np->n_parent->n_parent); } else { np->n_parent->n_black = 1; uncle->n_black = 1; np = np->n_parent->n_parent; np->n_black = 0; } } } tree->t_root->n_black = 1; return (result); } /* assuming that requested node exists */ void hammertree_delete(t_hammertree *tree, t_hammernode *gone) { t_hammernode *parent; /* parent of gone, after relinking */ t_hammernode *child; /* gone's only child (or null), after relinking */ /* gone has to be the parent of no more than one child */ if (gone->n_left && gone->n_right) { /* Successor is the new parent of gone's children, and a new child of gone's parent (if any). Successor always exists in this context, and it has no left child. The simplistic scheme is to replace gone's fields with successor's fields, and delete the successor. We cannot do so, however, because successor may be pointed at... */ t_hammernode *successor = gone->n_next; child = successor->n_right; successor->n_left = gone->n_left; successor->n_left->n_parent = successor; if (successor == gone->n_right) parent = successor; else { /* successor's parent always exists in this context, successor is the left child of its parent */ parent = successor->n_parent; parent->n_left = child; if (child) /* (sentinel not used) */ child->n_parent = parent; successor->n_right = gone->n_right; successor->n_right->n_parent = successor; } if (gone->n_parent) { int swp; if (gone == gone->n_parent->n_left) gone->n_parent->n_left = successor; else gone->n_parent->n_right = successor; successor->n_parent = gone->n_parent; swp = gone->n_black; gone->n_black = successor->n_black; successor->n_black = swp; } else { tree->t_root = successor; successor->n_parent = 0; gone->n_black = successor->n_black; successor->n_black = 1; /* LATER rethink */ } /* update the auxiliary linked list structure */ if (successor->n_prev = gone->n_prev) gone->n_prev->n_next = successor; else tree->t_first = successor; } else { /* update the auxiliary linked list structure */ if (gone->n_prev) gone->n_prev->n_next = gone->n_next; else tree->t_first = gone->n_next; if (gone->n_next) gone->n_next->n_prev = gone->n_prev; else tree->t_last = gone->n_prev; /* connect gone's child with gone's parent */ if (gone->n_left) child = gone->n_left; else child = gone->n_right; if (parent = gone->n_parent) { if (child) /* (sentinel not used) */ child->n_parent = parent; if (gone == parent->n_left) parent->n_left = child; else parent->n_right = child; } else { if (tree->t_root = child) { child->n_parent = 0; child->n_black = 1; /* LATER rethink */ } goto done; } } if (gone->n_black) { /* balance the tree -- LATER clean this if possible... */ /* on entry: tree is not empty, parent always exists, child not necessarily... */ while (child != tree->t_root && (!child || /* (sentinel not used) */ child->n_black)) { t_hammernode *other; /* another child of the same parent */ if (child == parent->n_left) { other = parent->n_right; if (other && /* (sentinel not used) */ !other->n_black) { other->n_black = 1; parent->n_black = 0; hammertree_lrotate(tree, parent); other = parent->n_right; } if (!other || /* (sentinel not used) */ (!other->n_left || other->n_left->n_black) && (!other->n_right || other->n_right->n_black)) { if (other) /* (sentinel not used) */ other->n_black = 0; child = parent; parent = parent->n_parent; } else { if (!other || /* (sentinel not used) */ !other->n_right || other->n_right->n_black) { if (other) /* (sentinel not used) */ { if (other->n_left) other->n_left->n_black = 1; other->n_black = 0; hammertree_rrotate(tree, other); other = parent->n_right; } } if (other) /* (sentinel not used) */ { if (other->n_right) other->n_right->n_black = 1; other->n_black = parent->n_black; } parent->n_black = 1; hammertree_lrotate(tree, parent); tree->t_root->n_black = 1; /* LATER rethink */ goto done; } } else /* right child */ { other = parent->n_left; if (other && /* (sentinel not used) */ !other->n_black) { other->n_black = 1; parent->n_black = 0; hammertree_rrotate(tree, parent); other = parent->n_left; } if (!other || /* (sentinel not used) */ (!other->n_left || other->n_left->n_black) && (!other->n_right || other->n_right->n_black)) { if (other) /* (sentinel not used) */ other->n_black = 0; child = parent; parent = parent->n_parent; } else { if (!other || /* (sentinel not used) */ !other->n_left || other->n_left->n_black) { if (other) /* (sentinel not used) */ { if (other->n_right) other->n_right->n_black = 1; other->n_black = 0; hammertree_lrotate(tree, other); other = parent->n_left; } } if (other) /* (sentinel not used) */ { if (other->n_left) other->n_left->n_black = 1; other->n_black = parent->n_black; } parent->n_black = 1; hammertree_rrotate(tree, parent); tree->t_root->n_black = 1; /* LATER rethink */ goto done; } } } if (child) /* (sentinel not used) */ child->n_black = 1; } done: freebytes(gone, tree->t_nodesize); #ifdef HAMMERTREE_DEBUG hammertree_verify(tree); #endif } t_hammernode *hammertree_search(t_hammertree *tree, int key) { t_hammernode *np = tree->t_root; while (np && np->n_key != key) np = (key < np->n_key ? np->n_left : np->n_right); return (np); } t_hammernode *hammertree_closest(t_hammertree *tree, int key, int geqflag) { t_hammernode *np, *parent; if (!(np = tree->t_root)) return (0); do if (np->n_key == key) return (np); else parent = np; while (np = (key < np->n_key ? np->n_left : np->n_right)); if (geqflag) return (key > parent->n_key ? parent->n_next : parent); else return (key < parent->n_key ? parent->n_prev : parent); } t_hammernode *hammertree_insert(t_hammertree *tree, int key, int *foundp) { return (hammertree_doinsert(tree, key, 0, foundp)); } t_hammernode *hammertree_multiinsert(t_hammertree *tree, int key, int fifoflag) { int found; return (hammertree_doinsert(tree, key, (fifoflag ? hammertree_postinserthook : hammertree_preinserthook), &found)); } t_hammernode *hammertree_insertfloat(t_hammertree *tree, int key, t_float f, int replaceflag) { int found; t_hammernode *np = hammertree_doinsert(tree, key, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == HAMMERTYPE_FLOAT) { t_hammernode_float *npf = (t_hammernode_float *)np; npf->nf_value = f; } else if (tree->t_valuetype == HAMMERTYPE_ATOM) { t_hammernode_atom *npa = (t_hammernode_atom *)np; t_atom *ap = &npa->na_value; SETFLOAT(ap, f); } else bug("hammertree_insertfloat"); } return (np); } t_hammernode *hammertree_insertsymbol(t_hammertree *tree, int key, t_symbol *s, int replaceflag) { int found; t_hammernode *np = hammertree_doinsert(tree, key, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == HAMMERTYPE_SYMBOL) { t_hammernode_symbol *nps = (t_hammernode_symbol *)np; nps->ns_value = s; } else if (tree->t_valuetype == HAMMERTYPE_ATOM) { t_hammernode_atom *npa = (t_hammernode_atom *)np; t_atom *ap = &npa->na_value; SETSYMBOL(ap, s); } else bug("hammertree_insertsymbol"); } return (np); } t_hammernode *hammertree_insertatom(t_hammertree *tree, int key, t_atom *ap, int replaceflag) { int found; t_hammernode *np = hammertree_doinsert(tree, key, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == HAMMERTYPE_ATOM) { t_hammernode_atom *npa = (t_hammernode_atom *)np; npa->na_value = *ap; } else bug("hammertree_insertatom"); } return (np); } /* LATER preallocate 'freecount' nodes */ static void hammertree_doinit(t_hammertree *tree, t_hammertype vtype, size_t nodesize, int freecount) { tree->t_root = tree->t_first = tree->t_last = 0; tree->t_valuetype = vtype; tree->t_nodesize = nodesize; } void hammertree_inittyped(t_hammertree *tree, t_hammertype vtype, int freecount) { size_t nsize; switch (vtype) { case HAMMERTYPE_FLOAT: nsize = sizeof(t_hammernode_float); break; case HAMMERTYPE_SYMBOL: nsize = sizeof(t_hammernode_symbol); break; case HAMMERTYPE_ATOM: nsize = sizeof(t_hammernode_atom); break; default: bug("hammertree_inittyped"); vtype = HAMMERTYPE_ILLEGAL; nsize = sizeof(t_hammernode); } hammertree_doinit(tree, vtype, nsize, freecount); } void hammertree_initcustom(t_hammertree *tree, size_t nodesize, int freecount) { hammertree_doinit(tree, HAMMERTYPE_CUSTOM, nodesize, freecount); } /* LATER keep and/or preallocate 'freecount' nodes (if negative, keep all) */ void hammertree_clear(t_hammertree *tree, int freecount) { t_hammernode *np, *next = tree->t_first; while (next) { np = next; next = next->n_next; freebytes(np, tree->t_nodesize); } hammertree_doinit(tree, tree->t_valuetype, tree->t_nodesize, 0); } cyclone-0.1-alpha55/shared/hammer/file.h0000644000076500007650000000261611466617452016551 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __HAMMERFILE_H__ #define __HAMMERFILE_H__ EXTERN_STRUCT _hammerfile; #define t_hammerfile struct _hammerfile typedef void (*t_hammerfilefn)(t_pd *, t_symbol *, int, t_atom *); typedef void (*t_hammerembedfn)(t_pd *, t_binbuf *, t_symbol *); void hammereditor_open(t_hammerfile *f, char *title, char *owner); void hammereditor_close(t_hammerfile *f, int ask); void hammereditor_append(t_hammerfile *f, char *contents); void hammereditor_setdirty(t_hammerfile *f, int flag); void hammerpanel_open(t_hammerfile *f, t_symbol *inidir); void hammerpanel_setopendir(t_hammerfile *f, t_symbol *dir); t_symbol *hammerpanel_getopendir(t_hammerfile *f); void hammerpanel_save(t_hammerfile *f, t_symbol *inidir, t_symbol *inifile); void hammerpanel_setsavedir(t_hammerfile *f, t_symbol *dir); t_symbol *hammerpanel_getsavedir(t_hammerfile *f); int hammerfile_ismapped(t_hammerfile *f); int hammerfile_isloading(t_hammerfile *f); int hammerfile_ispasting(t_hammerfile *f); void hammerfile_free(t_hammerfile *f); t_hammerfile *hammerfile_new(t_pd *master, t_hammerembedfn embedfn, t_hammerfilefn readfn, t_hammerfilefn writefn, t_hammerfilefn updatefn); void hammerfile_setup(t_class *c, int embeddable); #endif cyclone-0.1-alpha55/shared/hammer/Makefile.objects0000644000076500007650000000000011466617452020532 0ustar hanshanscyclone-0.1-alpha55/shared/hammer/file.c0000644000076500007650000004312011466617452016537 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* The three uses of the 'hammerfile' proxy class are: 1. providing `embedding' facility -- storing master object's state in a .pd file, 2. encapsulating openpanel/savepanel management, 3. extending the gui of Pd with a simple text editor window. A master class which needs embedding feature (like coll), passes a nonzero flag to the hammerfile setup routine, and a nonzero embedfn function pointer to the hammerfile constructor. If a master needs access to the panels (like collcommon), then it passes nonzero readfn and/or writefn callback pointers to the constructor. A master which has an associated text editor, AND wants to update object's state after edits, passes a nonzero updatefn callback in a call to the constructor. LATER extract the embedding stuff. */ #include #include #include "m_pd.h" #include "g_canvas.h" #include "common/os.h" #include "unstable/forky.h" #include "hammer/file.h" struct _hammerfile { t_pd f_pd; t_pd *f_master; t_canvas *f_canvas; t_symbol *f_bindname; t_symbol *f_currentdir; t_symbol *f_inidir; t_symbol *f_inifile; t_hammerfilefn f_panelfn; t_hammerfilefn f_editorfn; t_hammerembedfn f_embedfn; t_binbuf *f_binbuf; t_clock *f_panelclock; t_clock *f_editorclock; struct _hammerfile *f_savepanel; struct _hammerfile *f_next; }; static t_class *hammerfile_class = 0; static t_hammerfile *hammerfile_proxies; static t_symbol *ps__C; static t_hammerfile *hammerfile_getproxy(t_pd *master) { t_hammerfile *f; for (f = hammerfile_proxies; f; f = f->f_next) if (f->f_master == master) return (f); return (0); } static void hammereditor_guidefs(void) { sys_gui("proc hammereditor_open {name geometry title sendable} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); sys_gui(" $name.text delete 1.0 end\n"); sys_gui(" } else {\n"); sys_gui(" toplevel $name\n"); sys_gui(" wm title $name $title\n"); sys_gui(" wm geometry $name $geometry\n"); sys_gui(" if {$sendable} {\n"); sys_gui(" wm protocol $name WM_DELETE_WINDOW \\\n"); sys_gui(" [concat hammereditor_close $name 1]\n"); sys_gui(" bind $name <> \"hammereditor_dodirty $name\"\n"); sys_gui(" }\n"); sys_gui(" text $name.text -relief raised -bd 2 \\\n"); sys_gui(" -font -*-courier-medium--normal--12-* \\\n"); sys_gui(" -yscrollcommand \"$name.scroll set\" -background lightgrey\n"); sys_gui(" scrollbar $name.scroll -command \"$name.text yview\"\n"); sys_gui(" pack $name.scroll -side right -fill y\n"); sys_gui(" pack $name.text -side left -fill both -expand 1\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammereditor_dodirty {name} {\n"); sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 1}\n"); sys_gui(" set title [wm title $name]\n"); sys_gui(" set dt [string equal -length 1 $title \"*\"]\n"); sys_gui(" if {$dirty} {\n"); sys_gui(" if {$dt == 0} {wm title $name *$title}\n"); sys_gui(" } else {\n"); sys_gui(" if {$dt} {wm title $name [string range $title 1 end]}\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammereditor_setdirty {name flag} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); sys_gui(" catch {$name.text edit modified $flag}\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammereditor_doclose {name} {\n"); sys_gui(" destroy $name\n"); sys_gui("}\n"); sys_gui("proc hammereditor_append {name contents} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); sys_gui(" $name.text insert end $contents\n"); sys_gui(" }\n"); sys_gui("}\n"); /* FIXME make it more reliable */ sys_gui("proc hammereditor_send {name} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); sys_gui(" pd [concat miXed$name clear \\;]\n"); sys_gui(" for {set i 1} \\\n"); sys_gui(" {[$name.text compare $i.end < end]} \\\n"); sys_gui(" {incr i 1} {\n"); sys_gui(" set lin [$name.text get $i.0 $i.end]\n"); sys_gui(" if {$lin != \"\"} {\n"); /* LATER rethink semi/comma mapping */ sys_gui(" regsub -all \\; $lin \" _semi_ \" tmplin\n"); sys_gui(" regsub -all \\, $tmplin \" _comma_ \" lin\n"); sys_gui(" pd [concat miXed$name addline $lin \\;]\n"); sys_gui(" }\n"); sys_gui(" }\n"); sys_gui(" pd [concat miXed$name end \\;]\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammereditor_close {name ask} {\n"); sys_gui(" if {[winfo exists $name]} {\n"); sys_gui(" if {[catch {$name.text edit modified} dirty]} {set dirty 1}\n"); sys_gui(" if {$ask && $dirty} {\n"); sys_gui(" set title [wm title $name]\n"); sys_gui(" if {[string equal -length 1 $title \"*\"]} {\n"); sys_gui(" set title [string range $title 1 end]\n"); sys_gui(" }\n"); sys_gui(" set answer [tk_messageBox \\-type yesnocancel \\\n"); sys_gui(" \\-icon question \\\n"); sys_gui(" \\-message [concat Save changes to \\\"$title\\\"?]]\n"); sys_gui(" if {$answer == \"yes\"} {hammereditor_send $name}\n"); sys_gui(" if {$answer != \"cancel\"} {hammereditor_doclose $name}\n"); sys_gui(" } else {hammereditor_doclose $name}\n"); sys_gui(" }\n"); sys_gui("}\n"); } /* null owner defaults to class name, pass "" to supress */ void hammereditor_open(t_hammerfile *f, char *title, char *owner) { if (!owner) owner = class_getname(*f->f_master); if (!*owner) owner = 0; if (!title) { title = owner; owner = 0; } if (owner) sys_vgui("hammereditor_open .%x %dx%d {%s: %s} %d\n", (int)f, 600, 340, owner, title, (f->f_editorfn != 0)); else sys_vgui("hammereditor_open .%x %dx%d {%s} %d\n", (int)f, 600, 340, (title ? title : "Untitled"), (f->f_editorfn != 0)); } static void hammereditor_tick(t_hammerfile *f) { sys_vgui("hammereditor_close .%x 1\n", (int)f); } void hammereditor_close(t_hammerfile *f, int ask) { if (ask && f->f_editorfn) /* hack: deferring modal dialog creation in order to allow for a message box redraw to happen -- LATER investigate */ clock_delay(f->f_editorclock, 0); else sys_vgui("hammereditor_close .%x 0\n", (int)f); } void hammereditor_append(t_hammerfile *f, char *contents) { if (contents) { char *ptr; for (ptr = contents; *ptr; ptr++) { if (*ptr == '{' || *ptr == '}') { char c = *ptr; *ptr = 0; sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); sys_vgui("hammereditor_append .%x \"%c\"\n", (int)f, c); *ptr = c; contents = ptr + 1; } } if (*contents) sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); } } void hammereditor_setdirty(t_hammerfile *f, int flag) { if (f->f_editorfn) sys_vgui("hammereditor_setdirty .%x %d\n", (int)f, flag); } static void hammereditor_clear(t_hammerfile *f) { if (f->f_editorfn) { if (f->f_binbuf) binbuf_clear(f->f_binbuf); else f->f_binbuf = binbuf_new(); } } static void hammereditor_addline(t_hammerfile *f, t_symbol *s, int ac, t_atom *av) { if (f->f_editorfn) { int i; t_atom *ap; for (i = 0, ap = av; i < ac; i++, ap++) { if (ap->a_type == A_SYMBOL) { /* LATER rethink semi/comma mapping */ if (!strcmp(ap->a_w.w_symbol->s_name, "_semi_")) SETSEMI(ap); else if (!strcmp(ap->a_w.w_symbol->s_name, "_comma_")) SETCOMMA(ap); } } binbuf_add(f->f_binbuf, ac, av); } } static void hammereditor_end(t_hammerfile *f) { if (f->f_editorfn) { (*f->f_editorfn)(f->f_master, 0, binbuf_getnatom(f->f_binbuf), binbuf_getvec(f->f_binbuf)); binbuf_clear(f->f_binbuf); } } static void hammerpanel_guidefs(void) { sys_gui("proc hammerpanel_open {target inidir} {\n"); sys_gui(" global pd_opendir\n"); sys_gui(" if {$inidir == \"\"} {\n"); sys_gui(" set $inidir $pd_opendir\n"); sys_gui(" }\n"); sys_gui(" set filename [tk_getOpenFile \\\n"); sys_gui(" -initialdir $inidir]\n"); sys_gui(" if {$filename != \"\"} {\n"); sys_gui(" set directory [string range $filename 0 \\\n"); sys_gui(" [expr [string last / $filename ] - 1]]\n"); sys_gui(" if {$directory == \"\"} {set directory \"/\"}\n"); #if 1 sys_gui(" puts stderr [concat $directory]\n"); #endif sys_gui(" pd [concat $target path \\\n"); sys_gui(" [pdtk_enquote $filename] [pdtk_enquote $directory] \\;]\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammerpanel_save {target inidir inifile} {\n"); sys_gui(" if {$inifile != \"\"} {\n"); sys_gui(" set filename [tk_getSaveFile \\\n"); sys_gui(" -initialdir $inidir -initialfile $inifile]\n"); sys_gui(" } else {\n"); sys_gui(" set filename [tk_getSaveFile]\n"); sys_gui(" }\n"); sys_gui(" if {$filename != \"\"} {\n"); sys_gui(" set directory [string range $filename 0 \\\n"); sys_gui(" [expr [string last / $filename ] - 1]]\n"); sys_gui(" if {$directory == \"\"} {set directory \"/\"}\n"); sys_gui(" pd [concat $target path \\\n"); sys_gui(" [pdtk_enquote $filename] [pdtk_enquote $directory] \\;]\n"); sys_gui(" }\n"); sys_gui("}\n"); } /* There are two modes of -initialdir persistence: 1. Using last reply from gui (if any, default is canvas directory): pass null to hammerpanel_open/save() (for explicit cd, optionally call hammerpanel_setopen/savedir() first). 2. Starting always in the same directory (eg. canvasdir): feed hammerpanel_open/save(). Usually, first mode fits opening better, the second -- saving. */ /* This is obsolete, but has to stay, because older versions of miXed libraries might overwrite new hammerpanel_guidefs(). FIXME we need version control. */ static void hammerpanel_symbol(t_hammerfile *f, t_symbol *s) { if (s && s != &s_ && f->f_panelfn) (*f->f_panelfn)(f->f_master, s, 0, 0); } static void hammerpanel_path(t_hammerfile *f, t_symbol *s1, t_symbol *s2) { if (s2 && s2 != &s_) f->f_currentdir = s2; if (s1 && s1 != &s_ && f->f_panelfn) (*f->f_panelfn)(f->f_master, s1, 0, 0); } static void hammerpanel_tick(t_hammerfile *f) { if (f->f_savepanel) sys_vgui("hammerpanel_open %s {%s}\n", f->f_bindname->s_name, f->f_inidir->s_name); else sys_vgui("hammerpanel_save %s {%s} {%s}\n", f->f_bindname->s_name, f->f_inidir->s_name, f->f_inifile->s_name); } /* these are hacks: deferring modal dialog creation in order to allow for a message box redraw to happen -- LATER investigate */ void hammerpanel_open(t_hammerfile *f, t_symbol *inidir) { if (inidir) f->f_inidir = inidir; else f->f_inidir = (f->f_currentdir ? f->f_currentdir : &s_); clock_delay(f->f_panelclock, 0); } void hammerpanel_setopendir(t_hammerfile *f, t_symbol *dir) { if (f->f_currentdir && f->f_currentdir != &s_) { if (dir && dir != &s_) { int length; if (length = ospath_length(dir->s_name, f->f_currentdir->s_name)) { char *path = getbytes(length + 1); if (ospath_absolute(dir->s_name, f->f_currentdir->s_name, path)) /* LATER stat (think how to report a failure) */ f->f_currentdir = gensym(path); freebytes(path, length + 1); } } else if (f->f_canvas) f->f_currentdir = canvas_getdir(f->f_canvas); } else bug("hammerpanel_setopendir"); } t_symbol *hammerpanel_getopendir(t_hammerfile *f) { return (f->f_currentdir); } void hammerpanel_save(t_hammerfile *f, t_symbol *inidir, t_symbol *inifile) { if (f = f->f_savepanel) { if (inidir) f->f_inidir = inidir; else /* LATER ask if we can rely on s_ pointing to "" */ f->f_inidir = (f->f_currentdir ? f->f_currentdir : &s_); f->f_inifile = (inifile ? inifile : &s_); clock_delay(f->f_panelclock, 0); } } void hammerpanel_setsavedir(t_hammerfile *f, t_symbol *dir) { if (f = f->f_savepanel) hammerpanel_setopendir(f, dir); } t_symbol *hammerpanel_getsavedir(t_hammerfile *f) { return (f->f_savepanel ? f->f_savepanel->f_currentdir : 0); } /* Currently embeddable hammer classes do not use the 'saveto' method. In order to use it, any embeddable class would have to add a creation method to pd_canvasmaker -- then saving could be done with a 'proper' sequence: #N ; #X ; ...; #X restore ; However, this works only for -lib externals. So, we choose a sequence: #X obj ; #C ; ...; #C restore; Since the first message in this sequence is a valid creation message on its own, we have to distinguish loading from a .pd file, and other cases (editing). */ static void hammerembed_gc(t_pd *x, t_symbol *s, int expected) { t_pd *garbage; int count = 0; while (garbage = pd_findbyclass(s, *x)) pd_unbind(garbage, s), count++; if (count != expected) bug("hammerembed_gc (%d garbage bindings)", count); } static void hammerembed_restore(t_pd *master) { hammerembed_gc(master, ps__C, 1); } void hammerembed_save(t_gobj *master, t_binbuf *bb) { t_hammerfile *f = hammerfile_getproxy((t_pd *)master); t_text *t = (t_text *)master; binbuf_addv(bb, "ssii", &s__X, gensym("obj"), (int)t->te_xpix, (int)t->te_ypix); binbuf_addbinbuf(bb, t->te_binbuf); binbuf_addsemi(bb); if (f && f->f_embedfn) (*f->f_embedfn)(f->f_master, bb, ps__C); binbuf_addv(bb, "ss;", ps__C, gensym("restore")); } int hammerfile_ismapped(t_hammerfile *f) { return (f->f_canvas->gl_mapped); } int hammerfile_isloading(t_hammerfile *f) { return (f->f_canvas->gl_loading); } /* LATER find a better way */ int hammerfile_ispasting(t_hammerfile *f) { int result = 0; t_canvas *cv = f->f_canvas; if (!cv->gl_loading) { t_pd *z = s__X.s_thing; if (z == (t_pd *)cv) { pd_popsym(z); if (s__X.s_thing == (t_pd *)cv) result = 1; pd_pushsym(z); } else if (z) result = 1; } #if 0 if (result) post("pasting"); #endif return (result); } void hammerfile_free(t_hammerfile *f) { t_hammerfile *prev, *next; hammereditor_close(f, 0); if (f->f_embedfn) /* just in case of missing 'restore' */ hammerembed_gc(f->f_master, ps__C, 0); if (f->f_savepanel) { pd_unbind((t_pd *)f->f_savepanel, f->f_savepanel->f_bindname); pd_free((t_pd *)f->f_savepanel); } if (f->f_bindname) pd_unbind((t_pd *)f, f->f_bindname); if (f->f_panelclock) clock_free(f->f_panelclock); if (f->f_editorclock) clock_free(f->f_editorclock); for (prev = 0, next = hammerfile_proxies; next; prev = next, next = next->f_next) if (next == f) break; if (prev) prev->f_next = f->f_next; else if (f == hammerfile_proxies) hammerfile_proxies = f->f_next; pd_free((t_pd *)f); } t_hammerfile *hammerfile_new(t_pd *master, t_hammerembedfn embedfn, t_hammerfilefn readfn, t_hammerfilefn writefn, t_hammerfilefn updatefn) { t_hammerfile *result = (t_hammerfile *)pd_new(hammerfile_class); result->f_master = master; result->f_next = hammerfile_proxies; hammerfile_proxies = result; if (!(result->f_canvas = canvas_getcurrent())) { bug("hammerfile_new: out of context"); return (result); } /* 1. embedding */ if (result->f_embedfn = embedfn) { /* just in case of missing 'restore' */ hammerembed_gc(master, ps__C, 0); if (hammerfile_isloading(result) || hammerfile_ispasting(result)) pd_bind(master, ps__C); } /* 2. the panels */ if (readfn || writefn) { t_hammerfile *f; char buf[64]; sprintf(buf, "miXed.%x", (int)result); result->f_bindname = gensym(buf); pd_bind((t_pd *)result, result->f_bindname); result->f_currentdir = result->f_inidir = canvas_getdir(result->f_canvas); result->f_panelfn = readfn; result->f_panelclock = clock_new(result, (t_method)hammerpanel_tick); f = (t_hammerfile *)pd_new(hammerfile_class); f->f_master = master; f->f_canvas = result->f_canvas; sprintf(buf, "miXed.%x", (int)f); f->f_bindname = gensym(buf); pd_bind((t_pd *)f, f->f_bindname); f->f_currentdir = f->f_inidir = result->f_currentdir; f->f_panelfn = writefn; f->f_panelclock = clock_new(f, (t_method)hammerpanel_tick); result->f_savepanel = f; } else result->f_savepanel = 0; /* 3. editor */ if (result->f_editorfn = updatefn) { result->f_editorclock = clock_new(result, (t_method)hammereditor_tick); if (!result->f_bindname) { char buf[64]; sprintf(buf, "miXed.%x", (int)result); result->f_bindname = gensym(buf); pd_bind((t_pd *)result, result->f_bindname); } } return (result); } void hammerfile_setup(t_class *c, int embeddable) { if (embeddable) { forky_setsavefn(c, hammerembed_save); class_addmethod(c, (t_method)hammerembed_restore, gensym("restore"), 0); } if (!hammerfile_class) { ps__C = gensym("#C"); hammerfile_class = class_new(gensym("_hammerfile"), 0, 0, sizeof(t_hammerfile), CLASS_PD | CLASS_NOINLET, 0); class_addsymbol(hammerfile_class, hammerpanel_symbol); class_addmethod(hammerfile_class, (t_method)hammerpanel_path, gensym("path"), A_SYMBOL, A_DEFSYM, 0); class_addmethod(hammerfile_class, (t_method)hammereditor_clear, gensym("clear"), 0); class_addmethod(hammerfile_class, (t_method)hammereditor_addline, gensym("addline"), A_GIMME, 0); class_addmethod(hammerfile_class, (t_method)hammereditor_end, gensym("end"), 0); /* LATER find a way of ensuring that these are not defined yet... */ hammereditor_guidefs(); hammerpanel_guidefs(); } } cyclone-0.1-alpha55/shared/hammer/gui.h0000644000076500007650000000154211466617452016413 0ustar hanshans/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __HAMMERGUI_H__ #define __HAMMERGUI_H__ typedef struct _hammergui { t_pd g_pd; t_symbol *g_psgui; t_symbol *g_psmouse; t_symbol *g_pspoll; t_symbol *g_psfocus; t_symbol *g_psvised; int g_isup; } t_hammergui; void hammergui_bindmouse(t_pd *master); void hammergui_unbindmouse(t_pd *master); void hammergui_mousexy(t_symbol *s); void hammergui_willpoll(void); void hammergui_startpolling(t_pd *master); void hammergui_stoppolling(t_pd *master); void hammergui_bindfocus(t_pd *master); void hammergui_unbindfocus(t_pd *master); void hammergui_bindvised(t_pd *master); void hammergui_unbindvised(t_pd *master); #endif cyclone-0.1-alpha55/shared/hammer/Makefile0000644000076500007650000000010611466617452017111 0ustar hanshansROOT_DIR = ../.. include $(ROOT_DIR)/Makefile.common all: $(OBJECTS) cyclone-0.1-alpha55/shared/hammer/gui.c0000644000076500007650000003435011466617452016411 0ustar hanshans/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* FIXME use guiconnect */ /* LATER revisit tracking the mouse state within the focusless pd-gui (event bindings are local only in tk8.4, and there is no other call to XQueryPointer() but from winfo pointer). */ #include #include #include "m_pd.h" #include "g_canvas.h" #include "hammer/gui.h" #ifdef KRZYSZCZ //#define HAMMERGUI_DEBUG #endif static t_class *hammergui_class = 0; static t_hammergui *hammergui_sink = 0; static t_symbol *ps_hashhammergui; static t_symbol *ps__hammergui; static t_symbol *ps__up; static t_symbol *ps__focus; static t_symbol *ps__vised; static void hammergui_anything(t_hammergui *snk, t_symbol *s, int ac, t_atom *av) { /* Dummy method, filtering out messages from gui to the masters. This is needed in order to keep Pd's message system happy in a ``gray period'' -- after last master is unbound, and before gui bindings are cleared. */ #ifdef HAMMERGUI_DEBUG /* FIXME */ startpost("%s", s->s_name); postatom(ac, av); post(" (sink %x)", (int)snk); #endif } /* filtering out redundant "_up" messages */ static void hammergui__up(t_hammergui *snk, t_floatarg f) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "_up %g (sink %x)\n", f, (int)snk); #endif if (!snk->g_psmouse) { bug("hammergui__up"); return; } if ((int)f) { if (!snk->g_isup) { snk->g_isup = 1; if (snk->g_psmouse->s_thing) { t_atom at; SETFLOAT(&at, 1); pd_typedmess(snk->g_psmouse->s_thing, ps__up, 1, &at); } } } else { if (snk->g_isup) { snk->g_isup = 0; if (snk->g_psmouse->s_thing) { t_atom at; SETFLOAT(&at, 0); pd_typedmess(snk->g_psmouse->s_thing, ps__up, 1, &at); } } } } static void hammergui__focus(t_hammergui *snk, t_symbol *s, t_floatarg f) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "_focus %s %g (sink %x)\n", (s ? s->s_name : "???"), f, (int)snk); #endif if (!snk->g_psfocus) { bug("hammergui__focus"); return; } if (snk->g_psfocus->s_thing) { t_atom at[2]; SETSYMBOL(&at[0], s); SETFLOAT(&at[1], f); pd_typedmess(snk->g_psfocus->s_thing, ps__focus, 2, at); } } static void hammergui__vised(t_hammergui *snk, t_symbol *s, t_floatarg f) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "_vised %s %g (sink %x)\n", (s ? s->s_name : "???"), f, (int)snk); #endif if (!snk->g_psvised) { bug("hammergui__vised"); return; } if (snk->g_psvised->s_thing) { t_atom at[2]; SETSYMBOL(&at[0], s); SETFLOAT(&at[1], f); pd_typedmess(snk->g_psvised->s_thing, ps__vised, 2, at); } #if 0 /* How to be notified about changes of button state, prior to gui objects in a canvas? LATER find a reliable way -- delete if failed */ sys_vgui("bindtags %s {hammertag %s Canvas . all}\n", s->s_name, s->s_name); #endif } static void hammergui_dobindmouse(t_hammergui *snk) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "dobindmouse (sink %x)\n", (int)snk); #endif #if 0 /* How to be notified about changes of button state, prior to gui objects in a canvas? LATER find a reliable way -- delete if failed */ sys_vgui("bind hammertag <> {pd [concat %s _up 0 \\;]}\n", snk->g_psgui->s_name); sys_vgui("bind hammertag <> {pd [concat %s _up 1 \\;]}\n", snk->g_psgui->s_name); #endif sys_vgui("bind all <> {pd [concat %s _up 0 \\;]}\n", snk->g_psgui->s_name); sys_vgui("bind all <> {pd [concat %s _up 1 \\;]}\n", snk->g_psgui->s_name); } static void hammergui__remouse(t_hammergui *snk) { if (!snk->g_psmouse) { bug("hammergui__remouse"); return; } if (snk->g_psmouse->s_thing) { /* if a new master was bound in a gray period, we need to restore gui bindings */ #if 1 post("rebinding mouse..."); #endif hammergui_dobindmouse(snk); } } static void hammergui_dobindfocus(t_hammergui *snk) { sys_vgui("bind Canvas <> \ {if {[hammergui_ispatcher %%W]} \ {pd [concat %s _focus %%W 1 \\;]}}\n", snk->g_psgui->s_name); sys_vgui("bind Canvas <> \ {if {[hammergui_ispatcher %%W]} \ {pd [concat %s _focus %%W 0 \\;]}}\n", snk->g_psgui->s_name); } static void hammergui__refocus(t_hammergui *snk) { if (!snk->g_psfocus) { bug("hammergui__refocus"); return; } if (snk->g_psfocus->s_thing) { /* if a new master was bound in a gray period, we need to restore gui bindings */ #if 1 post("rebinding focus..."); #endif hammergui_dobindfocus(snk); } } static void hammergui_dobindvised(t_hammergui *snk) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "dobindvised (sink %x)\n", (int)snk); #endif sys_vgui("bind Canvas <> \ {if {[hammergui_ispatcher %%W]} \ {pd [concat %s _vised %%W 1 \\;]}}\n", snk->g_psgui->s_name); sys_vgui("bind Canvas <> \ {if {[hammergui_ispatcher %%W]} \ {pd [concat %s _vised %%W 0 \\;]}}\n", snk->g_psgui->s_name); } static void hammergui__revised(t_hammergui *snk) { if (!snk->g_psvised) { bug("hammergui__revised"); return; } if (snk->g_psvised->s_thing) { /* if a new master was bound in a gray period, we need to restore gui bindings */ #if 1 post("rebinding vised events..."); #endif hammergui_dobindvised(snk); } } static int hammergui_setup(void) { ps_hashhammergui = gensym("#hammergui"); ps__hammergui = gensym("_hammergui"); ps__up = gensym("_up"); ps__focus = gensym("_focus"); ps__vised = gensym("_vised"); if (ps_hashhammergui->s_thing) { char *cname = class_getname(*ps_hashhammergui->s_thing); #ifdef HAMMERGUI_DEBUG fprintf(stderr, "'%s' already registered as the global hammergui sink \n", (cname ? cname : "???")); #endif if (strcmp(cname, ps__hammergui->s_name)) { /* FIXME protect against the danger of someone else (e.g. receive) binding to #hammergui */ bug("hammergui_setup"); return (0); } else { /* FIXME compatibility test */ hammergui_class = *ps_hashhammergui->s_thing; return (1); } } hammergui_class = class_new(ps__hammergui, 0, 0, sizeof(t_hammergui), CLASS_PD | CLASS_NOINLET, 0); class_addanything(hammergui_class, hammergui_anything); class_addmethod(hammergui_class, (t_method)hammergui__remouse, gensym("_remouse"), 0); class_addmethod(hammergui_class, (t_method)hammergui__refocus, gensym("_refocus"), 0); class_addmethod(hammergui_class, (t_method)hammergui__revised, gensym("_revised"), 0); class_addmethod(hammergui_class, (t_method)hammergui__up, ps__up, A_FLOAT, 0); class_addmethod(hammergui_class, (t_method)hammergui__focus, ps__focus, A_SYMBOL, A_FLOAT, 0); class_addmethod(hammergui_class, (t_method)hammergui__vised, ps__vised, A_SYMBOL, A_FLOAT, 0); /* Protect against pdCmd being called (via "Canvas " binding) during Tcl_Finalize(). FIXME this should be a standard exit handler. */ sys_gui("proc hammergui_exithook {cmd op} {proc pd {} {}}\n"); sys_gui("if {[info tclversion] >= 8.4} {\n\ trace add execution exit enter hammergui_exithook}\n"); sys_gui("proc hammergui_ispatcher {cv} {\n"); sys_gui(" if {[string range $cv 0 1] == \".x\""); sys_gui(" && [string range $cv end-1 end] == \".c\"} {\n"); sys_gui(" return 1} else {return 0}\n"); sys_gui("}\n"); sys_gui("proc hammergui_remouse {} {\n"); sys_gui(" bind all <> {}\n"); sys_gui(" bind all <> {}\n"); sys_gui(" pd [concat #hammergui _remouse \\;]\n"); sys_gui("}\n"); sys_gui("proc hammergui_mousexy {target} {\n"); sys_gui(" set x [winfo pointerx .]\n"); sys_gui(" set y [winfo pointery .]\n"); sys_gui(" pd [concat #hammermouse $target $x $y \\;]\n"); sys_gui("}\n"); /* visibility hack for msw, LATER rethink */ sys_gui("global hammergui_ispolling\n"); sys_gui("global hammergui_x\n"); sys_gui("global hammergui_y\n"); sys_gui("set hammergui_ispolling 0\n"); sys_gui("set hammergui_x 0\n"); sys_gui("set hammergui_y 0\n"); sys_gui("proc hammergui_poll {} {\n"); sys_gui(" global hammergui_ispolling\n"); sys_gui(" global hammergui_x\n"); sys_gui(" global hammergui_y\n"); sys_gui(" if {$hammergui_ispolling == 1} {\n"); sys_gui(" set x [winfo pointerx .]\n"); sys_gui(" set y [winfo pointery .]\n"); sys_gui(" if {$hammergui_x != $x || $hammergui_y != $y} {\n"); sys_gui(" pd [concat #hammermouse _poll $x $y \\;]\n"); sys_gui(" set hammergui_x $x\n"); sys_gui(" set hammergui_y $y\n"); sys_gui(" }\n"); sys_gui(" after 50 hammergui_poll\n"); sys_gui(" }\n"); sys_gui("}\n"); sys_gui("proc hammergui_refocus {} {\n"); sys_gui(" bind Canvas <> {}\n"); sys_gui(" bind Canvas <> {}\n"); sys_gui(" pd [concat #hammergui _refocus \\;]\n"); sys_gui("}\n"); sys_gui("proc hammergui_revised {} {\n"); sys_gui(" bind Canvas <> {}\n"); sys_gui(" bind Canvas <> {}\n"); sys_gui(" pd [concat #hammergui _revised \\;]\n"); sys_gui("}\n"); return (1); } static int hammergui_validate(int dosetup) { if (dosetup && !hammergui_sink && (hammergui_class || hammergui_setup())) { if (ps_hashhammergui->s_thing) hammergui_sink = (t_hammergui *)ps_hashhammergui->s_thing; else { hammergui_sink = (t_hammergui *)pd_new(hammergui_class); hammergui_sink->g_psgui = ps_hashhammergui; pd_bind((t_pd *)hammergui_sink, ps_hashhammergui); /* never unbound */ } } if (hammergui_class && hammergui_sink) return (1); else { bug("hammergui_validate"); return (0); } } static int hammergui_mousevalidate(int dosetup) { if (dosetup && !hammergui_sink->g_psmouse) { hammergui_sink->g_psmouse = gensym("#hammermouse"); sys_gui("event add <> \n"); sys_gui("event add <> \n"); } if (hammergui_sink->g_psmouse) return (1); else { bug("hammergui_mousevalidate"); return (0); } } static int hammergui_pollvalidate(int dosetup) { if (dosetup && !hammergui_sink->g_pspoll) { hammergui_sink->g_pspoll = gensym("#hammerpoll"); pd_bind((t_pd *)hammergui_sink, hammergui_sink->g_pspoll); /* never unbound */ } if (hammergui_sink->g_pspoll) return (1); else { bug("hammergui_pollvalidate"); return (0); } } static int hammergui_focusvalidate(int dosetup) { if (dosetup && !hammergui_sink->g_psfocus) { hammergui_sink->g_psfocus = gensym("#hammerfocus"); sys_gui("event add <> \n"); sys_gui("event add <> \n"); } if (hammergui_sink->g_psfocus) return (1); else { bug("hammergui_focusvalidate"); return (0); } } static int hammergui_visedvalidate(int dosetup) { if (dosetup && !hammergui_sink->g_psvised) { hammergui_sink->g_psvised = gensym("#hammervised"); /* subsequent map events have to be filtered out at the caller's side, LATER investigate */ sys_gui("event add <> \n"); sys_gui("event add <> \n"); } if (hammergui_sink->g_psvised) return (1); else { bug("hammergui_visedvalidate"); return (0); } } void hammergui_bindmouse(t_pd *master) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "bindmouse, master %x\n", (int)master); #endif hammergui_validate(1); hammergui_mousevalidate(1); if (!hammergui_sink->g_psmouse->s_thing) hammergui_dobindmouse(hammergui_sink); pd_bind(master, hammergui_sink->g_psmouse); } void hammergui_unbindmouse(t_pd *master) { if (hammergui_validate(0) && hammergui_mousevalidate(0) && hammergui_sink->g_psmouse->s_thing) { pd_unbind(master, hammergui_sink->g_psmouse); if (!hammergui_sink->g_psmouse->s_thing) sys_gui("hammergui_remouse\n"); } else bug("hammergui_unbindmouse"); } void hammergui_mousexy(t_symbol *s) { if (hammergui_validate(0)) sys_vgui("hammergui_mousexy %s\n", s->s_name); } void hammergui_willpoll(void) { hammergui_validate(1); hammergui_pollvalidate(1); } void hammergui_startpolling(t_pd *master) { if (hammergui_validate(0) && hammergui_pollvalidate(0)) { int doinit = (hammergui_sink->g_pspoll->s_thing == (t_pd *)hammergui_sink); pd_bind(master, hammergui_sink->g_pspoll); if (doinit) { /* visibility hack for msw, LATER rethink */ sys_gui("global hammergui_ispolling\n"); sys_gui("set hammergui_ispolling 1\n"); sys_gui("hammergui_poll\n"); } } } void hammergui_stoppolling(t_pd *master) { if (hammergui_validate(0) && hammergui_pollvalidate(0)) { pd_unbind(master, hammergui_sink->g_pspoll); if (hammergui_sink->g_pspoll->s_thing == (t_pd *)hammergui_sink) { sys_gui("after cancel hammergui_poll\n"); /* visibility hack for msw, LATER rethink */ sys_gui("global hammergui_ispolling\n"); sys_gui("set hammergui_ispolling 0\n"); } } } void hammergui_bindfocus(t_pd *master) { hammergui_validate(1); hammergui_focusvalidate(1); if (!hammergui_sink->g_psfocus->s_thing) hammergui_dobindfocus(hammergui_sink); pd_bind(master, hammergui_sink->g_psfocus); } void hammergui_unbindfocus(t_pd *master) { if (hammergui_validate(0) && hammergui_focusvalidate(0) && hammergui_sink->g_psfocus->s_thing) { pd_unbind(master, hammergui_sink->g_psfocus); if (!hammergui_sink->g_psfocus->s_thing) sys_gui("hammergui_refocus\n"); } else bug("hammergui_unbindfocus"); } void hammergui_bindvised(t_pd *master) { #ifdef HAMMERGUI_DEBUG fprintf(stderr, "bindvised, master %x\n", (int)master); #endif hammergui_validate(1); hammergui_visedvalidate(1); if (!hammergui_sink->g_psvised->s_thing) hammergui_dobindvised(hammergui_sink); pd_bind(master, hammergui_sink->g_psvised); } void hammergui_unbindvised(t_pd *master) { if (hammergui_validate(0) && hammergui_visedvalidate(0) && hammergui_sink->g_psvised->s_thing) { pd_unbind(master, hammergui_sink->g_psvised); if (!hammergui_sink->g_psvised->s_thing) sys_gui("hammergui_revised\n"); } else bug("hammergui_unbindvised"); } cyclone-0.1-alpha55/shared/hammer/tree.h0000644000076500007650000000476411466617452016577 0ustar hanshans/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __HAMMERTREE_H__ #define __HAMMERTREE_H__ #ifdef KRZYSZCZ #define HAMMERTREE_DEBUG #endif typedef enum { HAMMERTYPE_FLOAT, HAMMERTYPE_SYMBOL, HAMMERTYPE_ATOM, HAMMERTYPE_CUSTOM, HAMMERTYPE_ILLEGAL } t_hammertype; typedef struct _hammernode { int n_key; int n_black; struct _hammernode *n_left; struct _hammernode *n_right; struct _hammernode *n_parent; struct _hammernode *n_prev; struct _hammernode *n_next; } t_hammernode; typedef struct _hammernode_float { t_hammernode nf_node; t_float nf_value; } t_hammernode_float; typedef struct _hammernode_symbol { t_hammernode ns_node; t_symbol *ns_value; } t_hammernode_symbol; typedef struct _hammernode_atom { t_hammernode na_node; t_atom na_value; } t_hammernode_atom; typedef struct _hammertree { t_hammernode *t_root; t_hammernode *t_first; t_hammernode *t_last; t_hammertype t_valuetype; size_t t_nodesize; } t_hammertree; #define HAMMERNODE_GETFLOAT(np) (((t_hammernode_float *)(np))->nf_value) #define HAMMERNODE_GETSYMBOL(np) (((t_hammernode_symbol *)(np))->ns_value) #define HAMMERNODE_GETATOMPTR(np) (&((t_hammernode_atom *)(np))->na_value) typedef void (*t_hammernode_vshowhook)(t_hammernode *, char *, unsigned); t_hammernode *hammertree_search(t_hammertree *tree, int key); t_hammernode *hammertree_closest(t_hammertree *tree, int key, int geqflag); t_hammernode *hammertree_insert(t_hammertree *tree, int key, int *foundp); t_hammernode *hammertree_multiinsert(t_hammertree *tree, int key, int fifoflag); t_hammernode *hammertree_insertfloat(t_hammertree *tree, int key, t_float f, int replaceflag); t_hammernode *hammertree_insertsymbol(t_hammertree *tree, int key, t_symbol *s, int replaceflag); t_hammernode *hammertree_insertatom(t_hammertree *tree, int key, t_atom *ap, int replaceflag); void hammertree_delete(t_hammertree *tree, t_hammernode *np); void hammertree_inittyped(t_hammertree *tree, t_hammertype vtype, int freecount); void hammertree_initcustom(t_hammertree *tree, size_t nodesize, int freecount); void hammertree_clear(t_hammertree *tree, int freecount); #ifdef HAMMERTREE_DEBUG void hammertree_debug(t_hammertree *tree, int level, t_hammernode_vshowhook hook); #endif #endif cyclone-0.1-alpha55/shared/hammer/Makefile.sources0000644000076500007650000000005211466617452020573 0ustar hanshansOTHER_SOURCES = \ file.c \ gui.c \ tree.c cyclone-0.1-alpha55/shared/sickle/0000755000076500007650000000000011466617452015455 5ustar hanshanscyclone-0.1-alpha55/shared/sickle/Makefile.objects0000644000076500007650000000000011466617452020533 0ustar hanshanscyclone-0.1-alpha55/shared/sickle/sic.h0000644000076500007650000000130011466617452016376 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __SIC_H__ #define __SIC_H__ typedef struct _sic { t_object s_ob; t_float s_f; int s_disabled; } t_sic; #define SIC_FLOATTOSIGNAL ((void *)0) #define SIC_NOMAINSIGNALIN ((void *)-1) #define SIC_NCOSTABLES 16 /* this is oscbank~'s max, LATER rethink */ t_inlet *sic_inlet(t_sic *x, int ix, t_float df, int ax, int ac, t_atom *av); t_inlet *sic_newinlet(t_sic *x, t_float f); t_float *sic_makecostable(int *sizep); void sic_setup(t_class *c, void *dspfn, void *floatfn); #endif cyclone-0.1-alpha55/shared/sickle/arsic.h0000644000076500007650000000225611466617452016734 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __ARSIC_H__ #define __ARSIC_H__ typedef struct _arsic { t_sic s_sic; int s_vecsize; /* used also as a validation flag */ int s_nchannels; t_float **s_vectors; t_symbol **s_channames; int s_nperfargs; t_int *s_perfargs; t_symbol *s_mononame; /* used also as an 'ismono' flag */ char *s_stub; float s_ksr; int s_playable; int s_minsize; } t_arsic; void arsic_clear(t_arsic *x); void arsic_redraw(t_arsic *x); void arsic_validate(t_arsic *x, int complain); void arsic_check(t_arsic *x); int arsic_getnchannels(t_arsic *x); void arsic_setarray(t_arsic *x, t_symbol *s, int complain); void arsic_setminsize(t_arsic *x, int i); void arsic_dsp(t_arsic *x, t_signal **sp, t_perfroutine perf, int complain); void *arsic_new(t_class *c, t_symbol *s, int nchannels, int nsigs, int nauxsigs); void arsic_free(t_arsic *x); void arsic_setup(t_class *c, void *dspfn, void *floatfn); #endif cyclone-0.1-alpha55/shared/sickle/sic.c0000644000076500007650000000600011466617452016373 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* generic signal class */ #include #include "m_pd.h" #include "shared.h" #include "common/loud.h" #include "sickle/sic.h" #ifdef KRZYSZCZ //#define SIC_DEBUG #endif #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define cosf cos #endif t_inlet *sic_inlet(t_sic *x, int ix, t_float df, int ax, int ac, t_atom *av) { t_inlet *in = 0; if (ax < ac) { if (av[ax].a_type == A_FLOAT) df = av[ax].a_w.w_float; else loud_error((t_pd *)x, "bad argument %d (float expected)", ax + 1); } if (ix) { in = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); /* this is persistent (in->i_un.iu_floatsignalvalue = df) */ pd_float((t_pd *)in, df); } else { in = ((t_object *)x)->ob_inlet; pd_float((t_pd *)x, df); } return (in); } t_inlet *sic_newinlet(t_sic *x, t_float f) { return (sic_inlet(x, 1, f, 0, 0, 0)); } t_float *sic_makecostable(int *sizep) { /* permanent cache (tables are never freed); LATER rethink */ static t_float *sic_costables[SIC_NCOSTABLES]; int ndx, sz; /* round upwards -- always return at least requested number of elements, unless the maximum of 2^SIC_NCOSTABLES is exceeded; LATER rethink */ /* (the minimum, at ndx 0, is 2^1) */ for (ndx = 0, sz = 2; ndx < (SIC_NCOSTABLES - 1); ndx++, sz <<= 1) if (sz >= *sizep) break; #ifdef SIC_DEBUG loudbug_post("request for a costable of %d points (effective %d, ndx %d)", *sizep, sz, ndx); #endif *sizep = sz; if (sic_costables[ndx]) return (sic_costables[ndx]); else if (sz == COSTABSIZE && cos_table) return (sic_costables[ndx] = cos_table); else { int cnt = sz + 1; float phase = 0, phsinc = SHARED_2PI / sz; t_float *table = (t_float *)getbytes(cnt * sizeof(*table)), *tp = table; if (table) { #ifdef SIC_DEBUG loudbug_post("got %d points of a costable", cnt); #endif while (cnt--) { *tp++ = cosf(phase); phase += phsinc; } } return (sic_costables[ndx] = table); } } static void sic_enable(t_sic *x, t_floatarg f) { x->s_disabled = (f == 0); } void sic_setup(t_class *c, void *dspfn, void *floatfn) { static int checked = 0; if (!checked) { /* MSP: here we check at startup whether the byte alignment is as we declared it. If not, the code has to be recompiled the other way. */ t_shared_wrappy wrappy; wrappy.w_d = SHARED_UNITBIT32 + 0.5; if ((unsigned)wrappy.w_i[SHARED_LOWOFFSET] != 0x80000000) loudbug_bug("sic_setup: unexpected machine alignment"); checked = 1; } if (floatfn != SIC_NOMAINSIGNALIN) { if (floatfn) { class_domainsignalin(c, -1); class_addfloat(c, floatfn); } else CLASS_MAINSIGNALIN(c, t_sic, s_f); } class_addmethod(c, (t_method)dspfn, gensym("dsp"), 0); class_addmethod(c, (t_method)sic_enable, gensym("enable"), 0); } cyclone-0.1-alpha55/shared/sickle/Makefile0000644000076500007650000000010611466617452017112 0ustar hanshansROOT_DIR = ../.. include $(ROOT_DIR)/Makefile.common all: $(OBJECTS) cyclone-0.1-alpha55/shared/sickle/Makefile.sources0000644000076500007650000000004211466617452020573 0ustar hanshansOTHER_SOURCES = \ sic.c \ arsic.c cyclone-0.1-alpha55/shared/sickle/arsic.c0000644000076500007650000001240311466617452016722 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* generic array-based signal class */ #include #include #include "m_pd.h" #include "shared.h" #include "common/loud.h" #include "common/vefl.h" #include "sickle/sic.h" #include "sickle/arsic.h" void arsic_clear(t_arsic *x) { x->s_vecsize = 0; memset(x->s_vectors, 0, x->s_nchannels * sizeof(*x->s_vectors)); } void arsic_redraw(t_arsic *x) { if (x->s_mononame) { t_garray *ap = (t_garray *)pd_findbyclass(x->s_mononame, garray_class); if (ap) garray_redraw(ap); else if (x->s_vectors[0]) loudbug_bug("arsic_redraw 1"); } else if (*x->s_stub) { int ch = x->s_nchannels; while (ch--) { t_garray *ap = (t_garray *)pd_findbyclass(x->s_channames[ch], garray_class); if (ap) garray_redraw(ap); else if (x->s_vectors[ch]) loudbug_bug("arsic_redraw 2"); } } } void arsic_validate(t_arsic *x, int complain) { arsic_clear(x); x->s_vecsize = SHARED_INT_MAX; if (x->s_mononame) { x->s_vectors[0] = vefl_get(x->s_mononame, &x->s_vecsize, 1, (complain ? (t_pd *)x : 0)); } else if (*x->s_stub) { int ch; for (ch = 0; ch < x->s_nchannels ; ch++) { int vsz = x->s_vecsize; /* ignore missing arrays */ x->s_vectors[ch] = vefl_get(x->s_channames[ch], &vsz, 1, (complain ? (t_pd *)x : 0)); if (vsz < x->s_vecsize) x->s_vecsize = vsz; } } if (x->s_vecsize == SHARED_INT_MAX) x->s_vecsize = 0; } void arsic_check(t_arsic *x) { x->s_playable = (!((t_sic *)x)->s_disabled && x->s_vecsize >= x->s_minsize); } int arsic_getnchannels(t_arsic *x) { return (x->s_nchannels); } void arsic_setarray(t_arsic *x, t_symbol *s, int complain) { if (s) { if (x->s_mononame) x->s_mononame = s; else { x->s_stub = s->s_name; if (*x->s_stub) { char buf[MAXPDSTRING]; int ch; for (ch = 0; ch < x->s_nchannels; ch++) { sprintf(buf, "%d-%s", ch, x->s_stub); x->s_channames[ch] = gensym(buf); } } } arsic_validate(x, complain); } arsic_check(x); } void arsic_setminsize(t_arsic *x, int i) { x->s_minsize = i; } void arsic_dsp(t_arsic *x, t_signal **sp, t_perfroutine perf, int complain) { t_int *ap = x->s_perfargs; if (ap) { int i, nsigs = x->s_nperfargs - 2; x->s_ksr = sp[0]->s_sr * 0.001; arsic_validate(x, complain); arsic_check(x); /* LATER consider glist traversing, and, if we have no feeders, choosing an optimized version of perform routine */ *ap++ = (t_int)x; *ap++ = (t_int)sp[0]->s_n; for (i = 0; i < nsigs; i++) *ap++ = (t_int)sp[i]->s_vec; dsp_addv(perf, x->s_nperfargs, x->s_perfargs); } else loudbug_bug("arsic_dsp"); } void arsic_free(t_arsic *x) { if (x->s_vectors) freebytes(x->s_vectors, x->s_nchannels * sizeof(*x->s_vectors)); if (x->s_channames) freebytes(x->s_channames, x->s_nchannels * sizeof(*x->s_channames)); if (x->s_perfargs) freebytes(x->s_perfargs, x->s_nperfargs * sizeof(*x->s_perfargs)); } /* If nauxsigs is positive, then the number of signals is nchannels + nauxsigs; otherwise the channels are not used as signals, and the number of signals is nsigs -- provided that nsigs is positive -- or, if it is not, then an arsic is not used in dsp (peek~). */ void *arsic_new(t_class *c, t_symbol *s, int nchannels, int nsigs, int nauxsigs) { t_arsic *x; t_symbol *mononame; char *stub; t_float **vectors; int nperfargs = 0; t_int *perfargs = 0; t_symbol **channames = 0; if (!s) s = &s_; if (nchannels < 1) { nchannels = 1; mononame = s; stub = 0; } else { mononame = 0; stub = s->s_name; } if (!(vectors = (t_float **)getbytes(nchannels * sizeof(*vectors)))) return (0); if (nauxsigs > 0) nperfargs = nchannels + nauxsigs + 2; else if (nsigs > 0) nperfargs = nsigs + 2; if (nperfargs && !(perfargs = (t_int *)getbytes(nperfargs * sizeof(*perfargs)))) { freebytes(vectors, nchannels * sizeof(*vectors)); return (0); } if (stub && !(channames = (t_symbol **)getbytes(nchannels * sizeof(*channames)))) { freebytes(vectors, nchannels * sizeof(*vectors)); if (perfargs) freebytes(perfargs, nperfargs * sizeof(*perfargs)); return (0); } x = (t_arsic *)pd_new(c); x->s_vecsize = 0; x->s_nchannels = nchannels; x->s_vectors = vectors; x->s_channames = channames; x->s_nperfargs = nperfargs; x->s_perfargs = perfargs; x->s_mononame = mononame; x->s_stub = stub; x->s_ksr = sys_getsr() * 0.001; ((t_sic *)x)->s_disabled = 0; x->s_playable = 0; x->s_minsize = 1; arsic_setarray(x, s, 0); return (x); } static void arsic_enable(t_arsic *x, t_floatarg f) { ((t_sic *)x)->s_disabled = (f == 0); arsic_check(x); } /* LATER somehow link this to sic_setup() */ void arsic_setup(t_class *c, void *dspfn, void *floatfn) { if (floatfn != SIC_NOMAINSIGNALIN) { if (floatfn) { class_domainsignalin(c, -1); class_addfloat(c, floatfn); } else CLASS_MAINSIGNALIN(c, t_sic, s_f); } class_addmethod(c, (t_method)dspfn, gensym("dsp"), 0); class_addmethod(c, (t_method)arsic_enable, gensym("enable"), 0); } cyclone-0.1-alpha55/shared/shared.h0000644000076500007650000000742611466617453015634 0ustar hanshans/* Copyright (c) 2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __SHARED_H__ #define __SHARED_H__ /* LATER find a proper place for #include */ #ifdef INT_MAX #define SHARED_INT_MAX INT_MAX #else #define SHARED_INT_MAX 0x7FFFFFFF #endif #ifdef INT_MIN #define SHARED_INT_MIN INT_MIN #else #define SHARED_INT_MIN ((int)0x80000000) #endif /* LATER find a proper place for #include */ #ifdef FLT_MAX #define SHARED_FLT_MAX FLT_MAX #else #define SHARED_FLT_MAX 1E+36 #endif typedef unsigned long shared_t_bitmask; #ifdef __linux__ #include #ifndef int32 typedef int32_t int32; #endif #ifndef uint32 typedef u_int32_t uint32; #endif #ifndef int16 typedef int16_t int16; #endif #ifndef uint16 typedef u_int16_t uint16; #endif #ifndef uchar typedef u_int8_t uchar; #endif #include #if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) #error No byte order defined #endif #if __BYTE_ORDER == __LITTLE_ENDIAN #define SHARED_HIOFFSET 1 #define SHARED_LOWOFFSET 0 #else #define SHARED_HIOFFSET 0 #define SHARED_LOWOFFSET 1 #endif #endif #ifdef NT #ifndef int32 typedef long int32; #endif #ifndef uint32 typedef unsigned long uint32; #endif #ifndef int16 typedef short int16; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #define SHARED_HIOFFSET 1 #define SHARED_LOWOFFSET 0 #endif #ifdef MACOSX #ifndef int32 typedef int int32; #endif #ifndef uint32 typedef unsigned int uint32; #endif #ifndef int16 typedef short int16; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #ifdef __BIG_ENDIAN__ #define SHARED_HIOFFSET 0 #define SHARED_LOWOFFSET 1 #else #define SHARED_HIOFFSET 1 #define SHARED_LOWOFFSET 0 #endif #endif #ifdef IRIX #ifndef int32 typedef long int32; #endif #ifndef uint32 typedef unsigned long uint32; #endif #ifndef int16 typedef short int16; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #define SHARED_HIOFFSET 0 #define SHARED_LOWOFFSET 1 #endif #ifdef __FreeBSD__ #include #ifndef int32 typedef int32_t int32; #endif #ifndef uint32 typedef u_int32_t uint32; #endif #ifndef int16 typedef int16_t int16; #endif #ifndef uint16 typedef u_int16_t uint16; #endif #ifndef uchar typedef u_int8_t uchar; #endif #include #if BYTE_ORDER == LITTLE_ENDIAN #define SHARED_HIOFFSET 1 #define SHARED_LOWOFFSET 0 #else #define SHARED_HIOFFSET 0 #define SHARED_LOWOFFSET 1 #endif #endif #define SHARED_UNITBIT32 1572864. /* 3*(2^19) gives 32 fractional bits */ #define SHARED_UNITBIT0 6755399441055744. /* 3*(2^51), no fractional bits */ #define SHARED_UNITBIT0_HIPART 0x43380000 typedef union _shared_wrappy { double w_d; int32 w_i[2]; } t_shared_wrappy; typedef union _shared_floatint { t_float fi_f; int32 fi_i; } t_shared_floatint; #define SHARED_TRUEBITS 0x3f800000 /* t_float f = 1; *(int32 *)&f */ #define SHARED_PI 3.14159265359 #define SHARED_2PI 6.28318530718 #ifndef PD_BADFLOAT #ifdef __i386__ #define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) #else #define PD_BADFLOAT(f) 0 #endif #endif #ifndef PD_BIGORSMALL #ifdef __i386__ #define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \ (((*(unsigned int*)&(f))&0x60000000)==0x60000000)) #else #define PD_BIGORSMALL(f) 0 #endif #endif #endif cyclone-0.1-alpha55/shared/Makefile.sources0000644000076500007650000000003311466617453017322 0ustar hanshansOTHER_SOURCES = \ shared.c cyclone-0.1-alpha55/shared/common/0000755000076500007650000000000011466617452015473 5ustar hanshanscyclone-0.1-alpha55/shared/common/lex.h0000644000076500007650000000127511466617452016441 0ustar hanshans/* Copyright (c) 2003-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __LEX_H__ #define __LEX_H__ typedef struct _lex { FILE *l_fp; unsigned char *l_buf; int l_bufsize; int l_bufndx; t_atomtype l_inttype; t_atomtype l_lasttype; int l_errbinary; } t_lex; int lex_nextatom(t_lex *lx, t_atom *ap); void lex_atomstring(t_atom *ap, char *buf, int bufsize, t_atomtype inttype); int lex_isbinary(t_lex *lx); void lex_free(t_lex *lx); t_lex *lex_new(FILE *fp, t_atomtype inttype); #endif cyclone-0.1-alpha55/shared/common/dict.c0000644000076500007650000001543111466617452016566 0ustar hanshans/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* this is merely an abstraction layer over gensym() from m_class.c with various additions adapted from m_pd.c */ #include #include #include "m_pd.h" #include "dict.h" #ifdef KRZYSZCZ //#define DICT_DEBUG #endif #define DICT_VERBOSE #define DICT_HASHSIZE_DEFAULT 1024 #define DICT_HASHSIZE_MIN 8 #define DICT_HASHSIZE_MAX 16384 /* two structures local to m_pd.c */ typedef struct _dict_bindelem { t_pd *e_who; struct _dict_bindelem *e_next; } t_dict_bindelem; typedef struct _dict_bindlist { t_pd b_pd; t_dict_bindelem *b_list; } t_dict_bindlist; /* adapted bindlist_anything() from m_pd.c */ static void dict_bindlist_anything(t_dict_bindlist *x, t_symbol *s, int argc, t_atom *argv) { t_dict_bindelem *e; for (e = x->b_list; e; e = e->e_next) pd_typedmess(e->e_who, s, argc, argv); } /* adapted m_pd_setup() from m_pd.c */ static void dict_bindlist_setup(t_dict *x) { x->d_bindlist_class = class_new(dict_key(x, "bindlist"), 0, 0, sizeof(t_dict_bindlist), CLASS_PD, 0); class_addanything(x->d_bindlist_class, dict_bindlist_anything); } t_dict *dict_new(size_t hashsize) { t_dict *x = getbytes(sizeof(*x)); size_t sz; if (x) { if (!hashsize) sz = DICT_HASHSIZE_DEFAULT; else if (hashsize >= DICT_HASHSIZE_MAX) sz = DICT_HASHSIZE_MAX; else if (hashsize <= DICT_HASHSIZE_MIN) sz = DICT_HASHSIZE_MIN; else for (sz = DICT_HASHSIZE_MAX; sz > DICT_HASHSIZE_MIN; sz >>= 1) if (sz <= hashsize) break; #ifdef DICT_DEBUG fprintf(stderr, "allocating dictionary with %d-element hashtable\n", sz); #endif if (x->d_hashtable = getbytes((x->d_hashsize = sz) * sizeof(*x->d_hashtable))) { dict_bindlist_setup(x); return (x); } freebytes(x, sizeof(*x)); } return (0); } void dict_free(t_dict *x) { if (x->d_hashtable) freebytes(x->d_hashtable, x->d_hashsize * sizeof(*x->d_hashtable)); freebytes(x, sizeof(*x)); } /* adapted dogensym() from m_class.c */ t_symbol *dict_dokey(t_dict *x, char *s, t_symbol *oldsym) { t_symbol **sym1, *sym2; unsigned int hash1 = 0, hash2 = 0; int length = 0; char *s2 = s; int mask = x->d_hashsize - 1; #ifdef DICT_DEBUG fprintf(stderr, "make symbol-key from \"%s\"", s); #endif while (*s2) { hash1 += *s2; hash2 += hash1; length++; s2++; } sym1 = x->d_hashtable + (hash2 & mask); #ifdef DICT_DEBUG fprintf(stderr, " in slot %d\n", (hash2 & mask)); #endif while (sym2 = *sym1) { #ifdef DICT_DEBUG fprintf(stderr, "try \"%s\"\n", sym2->s_name); #endif if (!strcmp(sym2->s_name, s)) { #ifdef DICT_DEBUG fprintf(stderr, "found at address %x\n", (int)sym2); #endif return(sym2); } sym1 = &sym2->s_next; } if (oldsym) sym2 = oldsym; else { sym2 = (t_symbol *)t_getbytes(sizeof(*sym2)); sym2->s_name = t_getbytes(length+1); sym2->s_next = 0; sym2->s_thing = 0; strcpy(sym2->s_name, s); } *sym1 = sym2; #ifdef DICT_DEBUG fprintf(stderr, "appended at address %x\n", (int)sym2); #endif return (sym2); } /* adapted gensym() from m_class.c */ t_symbol *dict_key(t_dict *x, char *s) { return (dict_dokey(x, s, 0)); } /* adapted pd_bind() from m_pd.c */ void dict_bind(t_dict *x, t_pd *obj, t_symbol *s) { #ifdef DICT_DEBUG fprintf(stderr, "bind %x to \"%s\" at %x\n", (int)obj, s->s_name, (int)s); #endif if (s->s_thing) { #ifdef DICT_DEBUG fprintf(stderr, "(next one)\n"); #endif if (*s->s_thing == x->d_bindlist_class) { t_dict_bindlist *b = (t_dict_bindlist *)s->s_thing; t_dict_bindelem *e = (t_dict_bindelem *)getbytes(sizeof(t_dict_bindelem)); e->e_next = b->b_list; e->e_who = obj; b->b_list = e; } else { t_dict_bindlist *b = (t_dict_bindlist *)pd_new(x->d_bindlist_class); t_dict_bindelem *e1 = (t_dict_bindelem *)getbytes(sizeof(t_dict_bindelem)); t_dict_bindelem *e2 = (t_dict_bindelem *)getbytes(sizeof(t_dict_bindelem)); b->b_list = e1; e1->e_who = obj; e1->e_next = e2; e2->e_who = s->s_thing; e2->e_next = 0; s->s_thing = &b->b_pd; } } else s->s_thing = obj; } /* adapted pd_unbind() from m_pd.c */ void dict_unbind(t_dict *x, t_pd *obj, t_symbol *s) { #ifdef DICT_DEBUG fprintf(stderr, "unbind %x from \"%s\" at %x\n", (int)obj, s->s_name, (int)s); #endif if (s->s_thing == obj) s->s_thing = 0; else if (s->s_thing && *s->s_thing == x->d_bindlist_class) { /* bindlists always have at least two elements... if the number goes down to one, get rid of the bindlist and bind the symbol straight to the remaining element. */ t_dict_bindlist *b = (t_dict_bindlist *)s->s_thing; t_dict_bindelem *e, *e2; if ((e = b->b_list)->e_who == obj) { b->b_list = e->e_next; freebytes(e, sizeof(t_dict_bindelem)); } else for (e = b->b_list; e2 = e->e_next; e = e2) if (e2->e_who == obj) { e->e_next = e2->e_next; freebytes(e2, sizeof(t_dict_bindelem)); break; } if (!b->b_list->e_next) { s->s_thing = b->b_list->e_who; freebytes(b->b_list, sizeof(t_dict_bindelem)); pd_free(&b->b_pd); } } else pd_error(obj, "%s: couldn't unbind", s->s_name); } t_pd *dict_firstvalue(t_dict *dict, t_symbol *s, void **nextp) { if (s->s_thing) { if (*s->s_thing == dict->d_bindlist_class) { t_dict_bindelem *e = ((t_dict_bindlist *)s->s_thing)->b_list; if (e) { if (nextp) *nextp = e->e_next; return (e->e_who); } else return (0); } else { if (nextp) *nextp = 0; return (s->s_thing); } } else return (0); } t_pd *dict_nextvalue(t_dict *dict, t_symbol *s, void **nextp) { if (s->s_thing) { if (*s->s_thing == dict->d_bindlist_class && *nextp) { t_dict_bindelem *e = (t_dict_bindelem *)*nextp; *nextp = e->e_next; return (e->e_who); } } else bug("dict_nextvalue"); return (0); } #if 0 t_pd *dict_xvalue(t_dict *x, t_symbol *s) { return (s && s != &s_ ? dict_value(x, dict_key(x, s->s_name)) : 0); } #endif int dict_forall(t_dict *x, t_symbol *s, t_dict_hook hook, void *hookarg) { if (!s->s_thing) return (0); if (*s->s_thing == x->d_bindlist_class) { t_dict_bindelem *e = ((t_dict_bindlist *)s->s_thing)->b_list; if (!e) return (0); if (!hook) return (1); do if (!hook(e->e_who, hookarg)) return (0); while (e = e->e_next); return (1); } return (hook ? hook(s->s_thing, hookarg) : 1); } cyclone-0.1-alpha55/shared/common/Makefile.objects0000644000076500007650000000000011466617452020551 0ustar hanshanscyclone-0.1-alpha55/shared/common/binport.c0000644000076500007650000004763211466617452017330 0ustar hanshans/* Copyright (c) 1997-2005 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER verify endianness transparency */ #include #include #include #include #include #define BINPORT_MAXSTRING 1000 #define BINPORT_SYMGROW 64 #ifndef MIXED_STANDALONE /* load a max binary file into a Pd binbuf */ #include "m_pd.h" #else /* make a max-textual listing from a max binary file */ /* This is a standalone version of a ``max binary to binbuf'' module. It uses certain Pd calls and structs, which are duplicated in the "standalone" module defined in shared/unstable. LATER standalone binport should be linked to the Pd API library. */ #include "unstable/standalone.h" #ifdef KRZYSZCZ //#define BINPORT_DEBUG #endif #define BINPORT_VERBOSE #endif #include "common/lex.h" #include "binport.h" static void binport_error(char *fmt, ...) { char buf[BINPORT_MAXSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); #ifdef MIXED_STANDALONE fprintf(stderr, "ERROR (binport): %s\n", buf); #else post("ERROR (binport): %s", buf); #endif va_end(ap); } static void binport_warning(char *fmt, ...) { #if defined (MIXED_STANDALONE) || defined(BINPORT_VERBOSE) char buf[BINPORT_MAXSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); #ifdef MIXED_STANDALONE fprintf(stderr, "warning (binport): %s\n", buf); #else post("warning (binport): %s", buf); #endif va_end(ap); #endif } static void binport_bug(char *fmt, ...) { char buf[BINPORT_MAXSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); #ifdef MIXED_STANDALONE fprintf(stderr, "BUG (binport): %s\n", buf); #else bug("(binport) %s", buf); #endif va_end(ap); } static void binport_failure(char *filename) { binport_error("\"%s\" doesn't look like a patch file", filename); } static void binpold_failure(char *filename) { binport_error("tried reading \"%s\" as an old format file, but failed", filename); } enum { BINPORT_NULLTYPE, BINPORT_INTTYPE = 1, BINPORT_FLOATTYPE, BINPORT_SYMTYPE, BINPORT_DEFINTTYPE = 5, BINPORT_DEFFLOATTYPE, BINPORT_DEFSYMTYPE, BINPORT_DEFDOLLSYMTYPE = 9, BINPORT_SEMITYPE = 10, BINPORT_COMMATYPE, BINPORT_DOLLARTYPE, BINPORT_DOLLSYMTYPE }; /* We use A_INT atom type not only for listing, but for import too -- the parser passes ints to individual token handlers, so that any required conversion has to be done during Pd message generation. */ #define A_INT A_DEFFLOAT static int binport_readbuf(FILE *fp, char *buf, size_t sz) { return (fread(buf, 1, sz, fp) == sz ? sz : 0); } static int binport_readbyte(FILE *fp, unsigned char *buf) { int c; if ((c = fgetc(fp)) == EOF) return (0); *buf = (unsigned char)c; return (1); } static int binport_readint(FILE *fp, int *iptr) { unsigned char word[4]; if (fread(word, 1, 4, fp) == 4) { *iptr = ((word[0] << 24) | (word[1] << 16) | (word[2] << 8) | word[3]); return (4); } else return (0); } /* LATER more testing */ /* make it binpold_readfloat() */ static int binport_readfloat(FILE *fp, float *fptr) { unsigned char word[10]; if (fread(word, 1, 10, fp) == 10) { int ex; unsigned hi, lo; ex = ((word[0] & 0x7F) << 8) | word[1]; hi = ((unsigned)word[2] << 24) | ((unsigned)word[3] << 16) | ((unsigned)word[4] << 8) | (unsigned)word[5]; lo = ((unsigned)word[6] << 24) | ((unsigned)word[7] << 16) | ((unsigned)word[8] << 8) | (unsigned)word[9]; if (ex == 0x7FFF) { binport_warning("NaN atom bashed to zero"); *fptr = 0.; } else if (ex || hi || lo) { double dhi, dlo, dabs; ex -= 0x401e; dhi = (double)((hi - 0x7fffffff) - 1) + ((float)0x7fffffff + 1.); dlo = (double)((lo - 0x7fffffff) - 1) + ((float)0x7fffffff + 1.); dabs = ldexp(dhi, ex) + ldexp(dlo, ex - 32); *fptr = ((word[0] & 0x80) ? -(float)dabs : (float)dabs); } else *fptr = 0.; #ifdef BINPORT_DEBUG fprintf(stderr, "%02x%02x", (int)word[0], (int)word[1]); fprintf(stderr, " %02x%02x%02x%02x", (int)word[2], (int)word[3], (int)word[4], (int)word[5]); fprintf(stderr, " %02x%02x%02x%02x", (int)word[6], (int)word[7], (int)word[8], (int)word[9]); fprintf(stderr, " == %g\n", *fptr); #endif return (10); } else return (0); } static int binport_readstring(FILE *fp, char *buf) { int c, i = 1; while (c = fgetc(fp)) { if (c == EOF) return (0); if (++i < BINPORT_MAXSTRING) *buf++ = (unsigned char)c; } *buf = '\0'; if (i >= BINPORT_MAXSTRING) binport_warning("symbol string too long, skipped"); return (i); } typedef struct _binpold { FILE *o_fp; int o_natoms; int o_bodysize; int o_nsymbols; int o_symbolid; int o_ndx; t_atom *o_atombuf; } t_binpold; #define BINPOLD_NATOMTYPES 16 #define BINPOLD_MAXATOMS 1000000 /* LATER rethink */ static t_atomtype binpold_atomtypes[BINPOLD_NATOMTYPES] = { A_NULL, A_INT, A_FLOAT, A_SYMBOL, A_CANT, A_CANT, A_CANT, A_CANT, A_CANT, A_CANT, A_SEMI, A_COMMA, A_DOLLAR, A_CANT, A_CANT, A_CANT }; static int binpold_gettype(t_binpold *old, t_atom *ap) { int typecode; if ((typecode = fgetc(old->o_fp)) != EOF) { if (typecode > 0 && typecode < BINPOLD_NATOMTYPES) { ap->a_type = binpold_atomtypes[typecode]; if (ap->a_type != A_CANT) return (1); else binport_warning("unsupported type of atom %d: %d", old->o_ndx, typecode); } else binport_warning("bad type of atom %d: %d", old->o_ndx, typecode); } else binport_warning("failed reading type of atom %d", old->o_ndx); return (0); } static int binpold_getvalue(t_binpold *old, t_atom *ap, int *countp) { int ival; float fval; *countp = 0; switch (ap->a_type) { case A_INT: case A_SYMBOL: if (*countp = binport_readint(old->o_fp, &ival)) ap->a_w.w_index = ival; else goto valuefailed; if (ap->a_type == A_SYMBOL) { if (ival >= old->o_nsymbols) old->o_nsymbols = ival + 1; ap->a_type = A_DEFSYM; /* invalidate, until w_symbol is known */ } break; case A_FLOAT: if (*countp = binport_readfloat(old->o_fp, &fval)) ap->a_w.w_float = fval; else goto valuefailed; break; case A_SEMI: case A_COMMA: break; case A_DOLLAR: if (*countp = binport_readint(old->o_fp, &ival)) ap->a_w.w_index = ival; else goto valuefailed; break; default: goto valuefailed; } return (1); valuefailed: binport_warning("failed reading value of atom %d (type %d)", old->o_ndx, ap->a_type); return (0); } static int binpold_load(t_binpold *old) { char buf[BINPORT_MAXSTRING]; t_atom *ap; int total; #ifdef BINPORT_DEBUG fprintf(stderr, "old format: %d atoms, %d-byte chunk of atom values\n", old->o_natoms, old->o_bodysize); #endif for (old->o_ndx = 0, ap = old->o_atombuf; old->o_ndx < old->o_natoms; old->o_ndx++, ap++) if (!binpold_gettype(old, ap)) return (0); old->o_nsymbols = 0; total = 0; for (old->o_ndx = 0, ap = old->o_atombuf; old->o_ndx < old->o_natoms; old->o_ndx++, ap++) { int count; if (!binpold_getvalue(old, ap, &count)) return (0); total += count; } if (total != old->o_bodysize) { binport_warning("actual chunk size %d inconsistent with declared %d", total, old->o_bodysize); return (0); } for (old->o_symbolid = 0; old->o_symbolid < old->o_nsymbols; old->o_symbolid++) { if (binport_readstring(old->o_fp, buf)) { t_symbol *s = gensym(buf); for (old->o_ndx = 0, ap = old->o_atombuf; old->o_ndx < old->o_natoms; old->o_ndx++, ap++) { if (ap->a_type == A_DEFSYM && ap->a_w.w_index == old->o_symbolid) { ap->a_type = A_SYMBOL; ap->a_w.w_symbol = s; } } } else { binport_warning("failed reading string for symbol %d", old->o_symbolid); return (0); } } for (old->o_ndx = 0, ap = old->o_atombuf; old->o_ndx < old->o_natoms; old->o_ndx++, ap++) { if (ap->a_type == A_DEFSYM) { binport_warning("unknown string for symbol %d", ap->a_w.w_index); return (0); } else if (ap->a_type == A_DOLLAR) { sprintf(buf, "#%d", ap->a_w.w_index); ap->a_type = A_SYMBOL; ap->a_w.w_symbol = gensym(buf); } /* CHECKME A_DOLLSYM */ } return (1); } static int binpold_nextatom(t_binpold *old, t_atom *ap) { if (old->o_ndx < old->o_natoms) { *ap = old->o_atombuf[old->o_ndx++]; return (1); } else return (0); } static void binpold_free(t_binpold *old) { if (old->o_fp) fclose(old->o_fp); if (old->o_atombuf) freebytes(old->o_atombuf, old->o_natoms * sizeof(*old->o_atombuf)); freebytes(old, sizeof(*old)); } static t_binpold *binpold_new(FILE *fp) { int natoms, bodysize; if (binport_readint(fp, &natoms)) { if (natoms < 0 || natoms > BINPOLD_MAXATOMS) binport_warning("bad number of atoms: %d", natoms); else if (binport_readint(fp, &bodysize)) { if (bodysize < 0) binport_warning("negative chunk size: %d", bodysize); else { t_binpold *old = getbytes(sizeof(*old)); old->o_fp = fp; old->o_natoms = natoms; old->o_bodysize = bodysize; if (!(old->o_atombuf = getbytes(old->o_natoms * sizeof(*old->o_atombuf)))) { binport_error("could not allocate %d atoms", old->o_natoms); freebytes(old, sizeof(*old)); fclose(fp); return (0); } return (old); } } } else binport_warning("file too short"); fclose(fp); return (0); } typedef struct _binport { FILE *b_fp; int b_ftype; int b_nsymbols; int b_symsize; t_symbol **b_symtable; t_binpold *b_old; t_lex *b_lex; } t_binport; static void binport_setint(t_atom *ap, int i) { ap->a_type = A_INT; ap->a_w.w_index = i; } static void binport_setfloat(t_atom *ap, float f) { ap->a_type = A_FLOAT; ap->a_w.w_float = f; } static void binport_setsymbol(t_atom *ap, t_symbol *s) { ap->a_type = A_SYMBOL; ap->a_w.w_symbol = s; } static t_symbol *binport_makesymbol(t_binport *bp, int id) { char s[BINPORT_MAXSTRING]; if (id < bp->b_nsymbols) binport_bug("symbol id mismatch"); else if (id > bp->b_nsymbols) binport_error("unexpected symbol id"); else if (binport_readstring(bp->b_fp, s)) { int reqsize = ++bp->b_nsymbols; if (reqsize > bp->b_symsize) { reqsize += (BINPORT_SYMGROW - 1); #ifdef BINPORT_DEBUG binport_warning("resizing symbol table to %d elements", reqsize); #endif if (bp->b_symtable = resizebytes(bp->b_symtable, bp->b_symsize * sizeof(*bp->b_symtable), reqsize * sizeof(*bp->b_symtable))) bp->b_symsize = reqsize; else { bp->b_nsymbols = bp->b_symsize = 0; return (0); } } return (bp->b_symtable[id] = gensym(s)); } return (0); } static int binport_setbysymtable(t_binport *bp, t_atom *ap, int id) { t_symbol *s; if (id < bp->b_nsymbols) s = bp->b_symtable[id]; else s = binport_makesymbol(bp, id); if (s) { ap->a_type = A_SYMBOL; ap->a_w.w_symbol = s; } return (s != 0); } static int binport_nextatom(t_binport *bp, t_atom *ap) { unsigned char opcode; int opval; char buf[64]; if (bp->b_ftype == BINPORT_MAXTEXT && bp->b_lex) return (lex_nextatom(bp->b_lex, ap)); else if (bp->b_ftype == BINPORT_MAXOLD && bp->b_old) return (binpold_nextatom(bp->b_old, ap)); if (!binport_readbyte(bp->b_fp, &opcode)) goto badbin; opval = opcode & 0x0f; switch (opcode >> 4) { case BINPORT_INTTYPE: /* variable length int, opval: length (number of bytes that follow) */ if (!binport_readbuf(bp->b_fp, buf, opval)) goto badbin; else { unsigned char *p = (unsigned char *)buf + opval; int i = 0; while (opval--) i = (i << 8) | *--p; if (opcode == 0x12) /* FIXME */ i = (short)i; binport_setint(ap, i); } break; case BINPORT_FLOATTYPE: /* variable length float, opval: length (number of bytes that follow) */ if (!binport_readbuf(bp->b_fp, buf, opval)) goto badbin; else { unsigned char *p = (unsigned char *)buf + opval; int i = 0; while (opval--) i = (i << 8) | *--p; binport_setfloat(ap, *(t_float *)&i); } break; case BINPORT_SYMTYPE: /* variable length symbol id, opval: length (number of bytes that follow) */ if (!binport_readbuf(bp->b_fp, buf, opval)) goto badbin; else { unsigned char *p = (unsigned char *)buf + opval; int i = 0; while (opval--) i = (i << 8) | *--p; if (!binport_setbysymtable(bp, ap, i)) goto badbin; } break; case BINPORT_DEFINTTYPE: /* half-byte int */ binport_setint(ap, opval); break; case BINPORT_DEFSYMTYPE: /* half-byte symbol id */ if (!binport_setbysymtable(bp, ap, opval)) goto badbin; break; case BINPORT_DEFDOLLSYMTYPE: /* half-byte #symbol id */ if (!binport_setbysymtable(bp, ap, opval)) goto badbin; sprintf(buf, "#%s", ap->a_w.w_symbol->s_name); #ifdef BINPORT_DEBUG binport_warning(buf); #endif ap->a_w.w_symbol = gensym(buf); break; case BINPORT_SEMITYPE: /* LATER warn about nonzero opval */ ap->a_type = A_SEMI; break; case BINPORT_COMMATYPE: /* CHECKME apparently never used? */ binport_warning("found the comma type in max binary..."); /* LATER warn about nonzero opval */ ap->a_type = A_COMMA; break; case BINPORT_DOLLARTYPE: /* #number */ sprintf(buf, "#%d", opval); ap->a_type = A_SYMBOL; ap->a_w.w_symbol = gensym(buf); break; case BINPORT_DOLLSYMTYPE: /* #symbol id, opval: length (number of bytes that follow) */ if (!binport_readbuf(bp->b_fp, buf, opval)) goto badbin; else { unsigned char *p = (unsigned char *)buf + opval; int i = 0; while (opval--) i = (i << 8) | *--p; if (!binport_setbysymtable(bp, ap, i)) goto badbin; } sprintf(buf, "#%s", ap->a_w.w_symbol->s_name); #ifdef BINPORT_DEBUG binport_warning(buf); #endif ap->a_w.w_symbol = gensym(buf); break; default: binport_error("unknown opcode %x", (int)opcode); goto badbin; } return (1); badbin: return (0); } static int binport_alike(char *header, int *ftypep) { static char bin_header[4] = { 2, 0, 0, 0 }; /* CHECKME any others? */ static char old_header[4] = { 0, 0, 0, 1 }; /* CHECKME any others? */ static char text_header[4] = { 'm', 'a', 'x', ' ' }; static char pd_header[3] = { '#', 'N', ' ' }; /* canvas or struct */ if (memcmp(header, bin_header, 4) == 0) *ftypep = BINPORT_MAXBINARY; else if (memcmp(header, text_header, 4) == 0) *ftypep = BINPORT_MAXTEXT; else if (memcmp(header, old_header, 4) == 0) *ftypep = BINPORT_MAXOLD; else { if (memcmp(header, pd_header, 3) == 0) *ftypep = BINPORT_PDFILE; else *ftypep = BINPORT_INVALID; return (0); } return (1); } static void binport_free(t_binport *bp) { fclose(bp->b_fp); if (bp->b_symtable) freebytes(bp->b_symtable, bp->b_symsize * sizeof(*bp->b_symtable)); if (bp->b_old) { bp->b_old->o_fp = 0; binpold_free(bp->b_old); } if (bp->b_lex) { bp->b_lex->l_fp = 0; lex_free(bp->b_lex); } freebytes(bp, sizeof(*bp)); } static t_binport *binport_new(FILE *fp, int *ftypep) { t_binport *bp = 0; char header[4]; if (fread(header, 1, 4, fp) == 4) { int alike = binport_alike(header, ftypep); if (alike) { bp = getbytes(sizeof(*bp)); bp->b_fp = fp; bp->b_ftype = *ftypep; bp->b_nsymbols = 0; if (*ftypep == BINPORT_MAXBINARY) { bp->b_symsize = BINPORT_SYMGROW; bp->b_symtable = getbytes(bp->b_symsize * sizeof(*bp->b_symtable)); } else { bp->b_symsize = 0; bp->b_symtable = 0; } bp->b_old = 0; bp->b_lex = 0; } else if (*ftypep != BINPORT_PDFILE) binport_warning("unknown header: %02x%02x%02x%02x", (int)header[0], (int)header[1], (int)header[2], (int)header[3]); } else { binport_warning("file too short"); *ftypep = BINPORT_INVALID; } if (!bp) fclose(fp); return (bp); } static void binport_print(t_binport *bp, FILE *fp) { char buf[BINPORT_MAXSTRING]; t_atom at; int cnt = 0; if (bp->b_old) bp->b_old->o_ndx = 0; while (binport_nextatom(bp, &at)) { if (at.a_type == A_SEMI) { fputs(";\n", fp); cnt = 0; } else if (at.a_type != A_NULL) { if (cnt++) fputc(' ', fp); lex_atomstring(&at, buf, BINPORT_MAXSTRING, A_INT); fputs(buf, fp); } } } #ifndef MIXED_STANDALONE static int binport_tobinbuf(t_binport *bp, t_binbuf *bb) { t_atom at; if (bp->b_old) bp->b_old->o_ndx = 0; while (binport_nextatom(bp, &at)) if (at.a_type != A_NULL) binbuf_add(bb, 1, &at); return (1); } /* LATER deal with corrupt binary files? */ int binport_read(t_binbuf *bb, char *filename, char *dirname) { int result; FILE *fp; char namebuf[MAXPDSTRING]; namebuf[0] = 0; if (*dirname) strcat(namebuf, dirname), strcat(namebuf, "/"); strcat(namebuf, filename); sys_bashfilename(namebuf, namebuf); if (fp = fopen(namebuf, "rb")) { int ftype; t_binport *bp = binport_new(fp, &ftype); if (bp) { if (ftype == BINPORT_MAXBINARY) result = (binport_tobinbuf(bp, bb) ? BINPORT_MAXBINARY : BINPORT_CORRUPT); else if (ftype == BINPORT_MAXTEXT) { t_atom at; if (bp->b_lex = lex_new(fp, A_INT)) { while (binport_nextatom(bp, &at)) if (at.a_type == A_SEMI) break; binbuf_addv(bb, "ss;", gensym("max"), gensym("v2")); result = (binport_tobinbuf(bp, bb) ? BINPORT_MAXTEXT : BINPORT_CORRUPT); } else result = BINPORT_FAILED; } else if (ftype == BINPORT_MAXOLD) { t_binpold *old = binpold_new(fp); result = BINPORT_FAILED; if (old) { bp->b_old = old; if (binpold_load(old) && binport_tobinbuf(bp, bb)) result = BINPORT_MAXOLD; } else binpold_failure(filename); } else result = BINPORT_FAILED; binport_free(bp); } else if (ftype == BINPORT_PDFILE) result = (binbuf_read(bb, filename, dirname, 0) ? BINPORT_FAILED : BINPORT_PDFILE); else { binport_failure(filename); result = BINPORT_INVALID; } } else { binport_bug("cannot open file"); result = BINPORT_FAILED; } return (result); } /* save as MAXTEXT */ void binport_write(t_binbuf *bb, char *filename, char *dirname) { int result; FILE *fp; char namebuf[MAXPDSTRING]; namebuf[0] = 0; if (*dirname) strcat(namebuf, dirname), strcat(namebuf, "/"); strcat(namebuf, filename); sys_bashfilename(namebuf, namebuf); if (fp = fopen(namebuf, "w")) { char buf[BINPORT_MAXSTRING]; t_atom *ap = binbuf_getvec(bb); int cnt = 0, ac = binbuf_getnatom(bb); while (ac--) { if (ap->a_type == A_SEMI) { fputs(";\n", fp); cnt = 0; } else if (ap->a_type != A_NULL) { if (cnt++) fputc(' ', fp); lex_atomstring(ap, buf, BINPORT_MAXSTRING, A_INT); fputs(buf, fp); } ap++; } fclose(fp); } } #else int main(int ac, char **av) { if (ac > 1) { FILE *fp = fopen(av[1], "rb"); if (fp) { int ftype; t_binport *bp = binport_new(fp, &ftype); if (bp) { if (ftype == BINPORT_MAXBINARY) binport_print(bp, stdout); else if (ftype == BINPORT_MAXTEXT) binport_warning("\"%s\" looks like a Max text file", av[1]); else if (ftype == BINPORT_MAXOLD) { t_binpold *old = binpold_new(fp); if (old) { bp->b_old = old; if (binpold_load(old)) binport_print(bp, stdout); else ftype = BINPORT_FAILED; } else ftype = BINPORT_FAILED; if (ftype == BINPORT_FAILED) binpold_failure(av[1]); } binport_free(bp); } else if (ftype == BINPORT_PDFILE) binport_warning("\"%s\" looks like a Pd patch file", av[1]); else binport_failure(av[1]); } else binport_error("cannot open file \"%s\"", av[1]); } else binport_error("what file?"); return (0); } #endif cyclone-0.1-alpha55/shared/common/rand.h0000644000076500007650000000070311466617452016570 0ustar hanshans/* Copyright (c) 2002-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __RAND_H__ #define __RAND_H__ #define RAND_DEBUG void rand_seed(unsigned int *statep, unsigned int seed); int rand_int(unsigned int *statep, int range); float rand_unipolar(unsigned int *statep); float rand_bipolar(unsigned int *statep); #endif cyclone-0.1-alpha55/shared/common/fitter.h0000644000076500007650000000130011466617452017133 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __FITTER_H__ #define __FITTER_H__ typedef void (*t_fitterstate_callback)(void); void fitter_setup(t_class *owner, t_fitterstate_callback callback); void fitter_drop(t_class *owner); t_float *fitter_getfloat(t_symbol *s); t_symbol *fitter_getsymbol(t_symbol *s); void fitter_setmode(t_symbol *s); t_symbol *fitter_getmode(void); void fittermax_set(void); int fittermax_get(void); void fittermax_warning(t_class *c, char *fmt, ...); void fittermax_rangewarning(t_class *c, int maxmax, char *what); #endif cyclone-0.1-alpha55/shared/common/fitter.c0000644000076500007650000001624511466617452017144 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include #include "m_pd.h" #include "fitter.h" #ifdef KRZYSZCZ # include "loud.h" # define FITTER_DEBUG #else # define loudbug_bug(msg) fprintf(stderr, "BUG: %s\n", msg), bug(msg) #endif /* FIXME compatibility mode should be a standard Pd feature. When it is, it will be possible to simplify the implementation. Until then, we have to handle multiple copies of the 'fitterstate_mode' variable (coming from different externals), and the only way is multicasting through a symbol (#miXed). */ static t_symbol *fitterstate_mode = 0; /* FIXME keep state in an extensible fitterstate_dictionary */ static t_symbol *fitterstate_test = 0; typedef struct _fitterstate_client { t_class *fc_owner; t_canvas *fc_canvas; t_fitterstate_callback fc_callback; struct _fitterstate_client *fc_next; } t_fitterstate_client; static t_fitterstate_client *fitterstate_clients = 0; static t_class *fitterstate_class = 0; static t_pd *fitterstate_target = 0; static int fitterstate_ready = 0; static t_symbol *fitterps_hashmiXed = 0; static t_symbol *fitterps_mode = 0; static t_symbol *fitterps_test = 0; static t_symbol *fitterps_max = 0; static t_symbol *fitterps_none = 0; /* read access (query), called only from fitterstate_dosetup() or through "#miXed" */ static void fitterstate_bang(t_pd *x) { if (fitterps_hashmiXed) { if (fitterstate_ready /* do not reply to own request */ && fitterps_hashmiXed->s_thing) { t_atom atout[2]; /* these proliferate for the third and subsequent fitterstate_dosetup() calls... */ SETSYMBOL(&atout[0], fitterps_mode); SETSYMBOL(&atout[1], fitterstate_mode); typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); SETSYMBOL(&atout[0], fitterps_test); SETSYMBOL(&atout[1], fitterstate_test); typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); } } else loudbug_bug("fitterstate_bang"); } /* read access (query), called only through "#miXed" */ static void fitterstate_symbol(t_pd *x, t_symbol *s) { if (fitterstate_ready && fitterps_hashmiXed && fitterps_hashmiXed->s_thing) { t_atom atout[2]; if (s == fitterps_mode) { SETSYMBOL(&atout[0], fitterps_mode); SETSYMBOL(&atout[1], fitterstate_mode); typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); } else if (s == fitterps_test) { SETSYMBOL(&atout[0], fitterps_test); SETSYMBOL(&atout[1], fitterstate_test); typedmess(fitterps_hashmiXed->s_thing, gensym("reply"), 2, atout); } else post("\"%s\": no such key in the miXed state", (s ? s->s_name : "???")); } else loudbug_bug("fitterstate_symbol"); } /* read access (reply), called only from fitter_dosetup() or through "#miXed" */ static void fitterstate_reply(t_pd *x, t_symbol *s1, t_symbol *s2) { if (!s2 || s2 == &s_) { loudbug_bug("fitterstate_reply"); s2 = fitterps_none; } if (s1 == fitterps_mode) fitterstate_mode = s2; else if (s1 == fitterps_test) fitterstate_test = s2; } /* write access, called only from fitter_setmode() or through "#miXed" */ static void fitterstate_set(t_pd *x, t_symbol *s1, t_symbol *s2) { t_fitterstate_client *fc; if (s1 == fitterps_mode) fitterstate_mode = s2; else if (s1 == fitterps_test) fitterstate_test = s2; for (fc = fitterstate_clients; fc; fc = fc->fc_next) if (fc->fc_callback) fc->fc_callback(); } static void fitterstate_dosetup(int noquery) { if (fitterstate_class || fitterstate_target) loudbug_bug("fitterstate_dosetup"); fitterps_hashmiXed = gensym("#miXed"); fitterps_mode = gensym("mode"); fitterps_test = gensym("test"); fitterps_max = gensym("max"); fitterps_none = gensym("none"); fitterstate_mode = fitterps_none; fitterstate_test = fitterps_none; fitterstate_class = class_new(fitterps_hashmiXed, 0, 0, sizeof(t_pd), CLASS_PD | CLASS_NOINLET, 0); class_addbang(fitterstate_class, fitterstate_bang); class_addsymbol(fitterstate_class, fitterstate_symbol); class_addmethod(fitterstate_class, (t_method)fitterstate_reply, gensym("reply"), A_SYMBOL, A_SYMBOL, 0); class_addmethod(fitterstate_class, (t_method)fitterstate_set, gensym("set"), A_SYMBOL, A_SYMBOL, 0); fitterstate_target = pd_new(fitterstate_class); pd_bind(fitterstate_target, fitterps_hashmiXed); if (!noquery) pd_bang(fitterps_hashmiXed->s_thing); fitterstate_ready = 1; } void fitter_setup(t_class *owner, t_fitterstate_callback callback) { if (!fitterstate_class) fitterstate_dosetup(0); if (callback) { t_fitterstate_client *fc = getbytes(sizeof(*fc)); fc->fc_owner = owner; fc->fc_canvas = 0; /* a global client */ fc->fc_callback = callback; fc->fc_next = fitterstate_clients; fitterstate_clients = fc; } } void fitter_drop(t_class *owner) { if (fitterstate_class && fitterps_hashmiXed->s_thing) { t_fitterstate_client *fcp = 0, *fc = fitterstate_clients; while (fc) { if (fc->fc_owner == owner) { if (fcp) fcp->fc_next = fc->fc_next; else fitterstate_clients = fc->fc_next; break; } fcp = fc; fc = fc->fc_next; } if (fc) freebytes(fc, sizeof(*fc)); else loudbug_bug("fitter_drop 1"); } else loudbug_bug("fitter_drop 2"); } t_float *fitter_getfloat(t_symbol *s) { if (!fitterstate_class) fitterstate_dosetup(0); loudbug_bug("fitter_getfloat"); return (0); } t_symbol *fitter_getsymbol(t_symbol *s) { if (!fitterstate_class) fitterstate_dosetup(0); if (s == fitterps_mode) return (fitterstate_mode); else if (s == fitterps_test) return (fitterstate_test); else { loudbug_bug("fitter_getsymbol"); return (0); } } void fitter_setmode(t_symbol *s) { if (!s || s == &s_) s = fitterps_none; post("setting compatibility mode to '%s'", s->s_name); if (!fitterstate_class) fitterstate_dosetup(1); if (fitterps_hashmiXed->s_thing) { t_atom atout[2]; SETSYMBOL(&atout[0], fitterps_mode); SETSYMBOL(&atout[1], s); typedmess(fitterps_hashmiXed->s_thing, gensym("set"), 2, atout); } else loudbug_bug("fitter_setmode"); } t_symbol *fitter_getmode(void) { if (!fitterstate_class) fitterstate_dosetup(0); return (fitterstate_mode); } void fittermax_set(void) { if (!fitterstate_class) fitterstate_dosetup(0); fitter_setmode(fitterps_max); } int fittermax_get(void) { if (!fitterstate_class) fitterstate_dosetup(0); return (fitterstate_mode == fitterps_max); } void fittermax_warning(t_class *c, char *fmt, ...) { if (!fitterstate_class) fitterstate_dosetup(0); if (fitterstate_mode == fitterps_max) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); post("'%s' class incompatibility warning:\n\t%s", class_getname(c), buf); va_end(ap); } } void fittermax_rangewarning(t_class *c, int maxmax, char *what) { fittermax_warning(c, "more than %d %s requested", maxmax, what); } cyclone-0.1-alpha55/shared/common/messtree.h0000644000076500007650000000265311466617452017501 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __MESSTREE_H__ #define __MESSTREE_H__ typedef int (*t_messcall)(t_pd *, t_symbol *, int, t_atom *); typedef char *t_messarg; typedef struct _messslot { char *ms_name; t_messcall ms_call; char *ms_argument; int ms_flags; struct _messnode *ms_subnode; } t_messslot; typedef struct _messnode /* a parser's symbol definition, sort of... */ { t_messslot *mn_table; int mn_nslots; int mn_index; } t_messnode; EXTERN_STRUCT _messtree; #define t_messtree struct _messtree #define MESSTREE_NSLOTS(slots) (sizeof(slots)/sizeof(*(slots))) enum { MESSTREE_OK, /* done current message parsing, parse next */ MESSTREE_CONTINUE, /* continue current message parsing */ MESSTREE_UNKNOWN, /* current message unknown, parse next */ MESSTREE_CORRUPT, /* current message corrupt, parse next */ MESSTREE_FATAL /* exit parsing */ }; #define MESSTREE_NONEXCLUSIVE 1 t_messtree *messtree_new(t_symbol *selector); void messtree_add(t_messtree *mt, t_messnode *rootnode); t_messtree *messtree_build(t_messslot *rootslot); int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp, t_pd *target, t_symbol *s, int ac, t_atom *av); #endif cyclone-0.1-alpha55/shared/common/patchvalue.h0000644000076500007650000000144611466617452020005 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __PATCHVALUE_H__ #define __PATCHVALUE_H__ typedef struct _patchvalue { t_pd pv_pd; t_symbol *pv_name; int pv_refcount; struct _patchvalue *pv_next; } t_patchvalue; t_class *patchvalue_classnew(t_symbol *cname, size_t size); t_patchvalue *patchvalue_use(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name); t_patchvalue *patchvalue_get(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name); t_patchvalue *patchvalue_resolve(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name); #endif cyclone-0.1-alpha55/shared/common/port.h0000644000076500007650000000065711466617452016640 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __PORT_H__ #define __PORT_H__ int import_max(char *fn, char *dir); void import_setmapping(int size, char **mapping); char **import_getmapping(int *sizep); char *port_usemapping(char *from, int mapsize, char **mapping); #endif cyclone-0.1-alpha55/shared/common/grow.h0000644000076500007650000000117111466617452016622 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __GROW_H__ #define __GROW_H__ void *grow_nodata(int *nrequested, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize); void *grow_withdata(int *nrequested, int *nexisting, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize); void *grow_withtail(int *nrequested, int *nexisting, char **startp, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize); #endif cyclone-0.1-alpha55/shared/common/loud.c0000644000076500007650000002314411466617452016606 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include #include #include "m_pd.h" #include "loud.h" #ifdef MSW #define vsnprintf _vsnprintf #endif /* The 'shared_' calls do not really belong here, LATER find them a permanent home. */ int shared_matchignorecase(char *test, char *pattern) { char ct, cp; for (ct = *test, cp = *pattern; ct && cp; ct = *++test, cp = *++pattern) if (ct != cp && ((ct < 'A' || ct > 'z') || ((ct > 'Z' || ct + 32 != cp) && (ct < 'a' || ct - 32 != cp)))) return (0); return (ct == cp); } struct _loudcontext { t_pd *lc_caller; /* an object reporting trouble */ char *lc_callername; int lc_cnsize; /* during object creation, use the following: */ t_symbol *lc_selector; /* creation message selector (class name) */ int lc_ac; /* creation message arguments */ t_atom *lc_av; /* void out of creation context */ int lc_andindent; }; #define LOUD_ERROR_DEFAULT "error (miXed):" char *loud_ordinal(int n) { static char buf[16]; /* assuming 10-digit INT_MAX */ sprintf(buf, "%dth", n); if (n < 0) n = -n; n %= 100; if (n > 20) n %= 10; if (n && n <= 3) { char *ptr = buf + strlen(buf) - 2; switch (n) { case 1: strcpy(ptr, "st"); break; case 2: strcpy(ptr, "nd"); break; case 3: strcpy(ptr, "rd"); break; } } return (buf); } void loud_error(t_pd *x, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); if (x) { startpost("%s's ", class_getname(*x)); pd_error(x, buf); } else post("%s %s", LOUD_ERROR_DEFAULT, buf); va_end(ap); } void loud_errand(t_pd *x, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); post("%*s%s", (int)(x ? strlen(class_getname(*x)) + 10 : strlen(LOUD_ERROR_DEFAULT) + 1), "", buf); va_end(ap); } void loud_syserror(t_pd *x, char *fmt, ...) { if (fmt) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); loud_error(x, "%s (%s)", buf, strerror(errno)); va_end(ap); } else loud_error(x, strerror(errno)); } void loud_nomethod(t_pd *x, t_symbol *s) { loud_error(x, "doesn't understand \"%s\"", s->s_name); } void loud_messarg(t_pd *x, t_symbol *s) { loud_error(x, "bad arguments for message \"%s\"", s->s_name); } int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess) { if ((*valuep = (int)f) == f) return (1); else { static t_symbol *floatsym = 0; if (!floatsym) floatsym = gensym("noninteger float"); if (mess == &s_float) loud_nomethod(x, floatsym); else if (mess) loud_error(x, "\"%s\" argument invalid for message \"%s\"", floatsym->s_name, mess->s_name); return (0); } } void loud_classarg(t_class *c) { loud_error(0, "missing or bad arguments in \"%s\"", class_getname(c)); } void loud_warning(t_pd *x, char *who, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); post("warning (%s): %s", (x ? class_getname(*x) : (who ? who : "miXed")), buf); va_end(ap); } void loud_notimplemented(t_pd *x, char *name) { if (name) loud_warning(x, 0, "\"%s\" method not implemented (yet)", name); else loud_warning(x, 0, "not implemented (yet)"); } int loud_floatarg(t_class *c, int which, int ac, t_atom *av, t_float *vp, t_float minval, t_float maxval, int underaction, int overaction, char *what) { int result = LOUD_ARGOK; if (which < ac) { av += which; if (av->a_type == A_FLOAT) { t_float f = av->a_w.w_float; if (f < minval) { *vp = (underaction & LOUD_CLIP ? minval : f); if (underaction) result = LOUD_ARGUNDER; } else if (f > maxval) { *vp = (overaction & LOUD_CLIP ? maxval : f); if (overaction) result = LOUD_ARGOVER; } else *vp = f; } else result = LOUD_ARGTYPE; } else result = LOUD_ARGMISSING; if (what) { switch (result) { case LOUD_ARGUNDER: if (underaction & LOUD_WARN) { if (underaction & LOUD_CLIP) loud_warning(&c, 0, "%s rounded up to %g", what, minval); else loud_warning(&c, 0, "less than %g %s requested", minval, what); } break; case LOUD_ARGOVER: if (overaction & LOUD_WARN) { if (overaction & LOUD_CLIP) loud_warning(&c, 0, "%s truncated to %g", what, maxval); else loud_warning(&c, 0, "more than %g %s requested", maxval, what); } break; case LOUD_ARGTYPE: loud_error(0, "bad argument %d (%s)", which, class_getname(c)); break; default:; } } return (result); } void loudx_error(t_loudcontext *lc, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); if (lc->lc_caller) { startpost("%s's ", (lc->lc_callername ? lc->lc_callername : class_getname(*lc->lc_caller))); pd_error(lc->lc_caller, buf); } else { if (lc->lc_callername) post("error (%s): %s", lc->lc_callername, buf); else if (lc->lc_selector) post("error (%s): %s", lc->lc_selector->s_name, buf); else post("%s %s", LOUD_ERROR_DEFAULT, buf); } va_end(ap); } void loudx_errand(t_loudcontext *lc, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); post("%*s%s", lc->lc_andindent, "", buf); va_end(ap); } void loudx_nomethod(t_loudcontext *lc, t_symbol *s) { loudx_error(lc, "doesn't understand \"%s\"", s->s_name); } void loudx_messarg(t_loudcontext *lc, t_symbol *s) { loudx_error(lc, "bad arguments for message \"%s\"", s->s_name); } void loudx_warning(t_loudcontext *lc, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); if (lc->lc_callername) post("warning (%s): %s", lc->lc_callername, buf); else if (lc->lc_selector) post("warning (%s): %s", lc->lc_selector->s_name, buf); else post("warning (miXed): %s", buf); va_end(ap); } void loudx_setcontext(t_loudcontext *lc, t_pd *caller, char *callername, t_symbol *s, int ac, t_atom *av) { if (lc->lc_callername) freebytes(lc->lc_callername, lc->lc_cnsize); lc->lc_caller = caller; if (callername) { lc->lc_cnsize = strlen(callername) + 1; lc->lc_callername = getbytes(lc->lc_cnsize); strcpy(lc->lc_callername, callername); } else { lc->lc_callername = 0; lc->lc_cnsize = 0; } lc->lc_selector = s; lc->lc_ac = ac; lc->lc_av = av; if (callername) lc->lc_andindent = lc->lc_cnsize + 9; else if (caller) lc->lc_andindent = strlen(class_getname(*caller)) + 10; else if (s) lc->lc_andindent = strlen(s->s_name) + 10; else lc->lc_andindent = strlen(LOUD_ERROR_DEFAULT) + 1; } /* must call before going out of creation context */ void loudx_setcaller(t_loudcontext *lc, t_pd *caller, char *callerfmt, ...) { va_list ap; va_start(ap, callerfmt); if (callerfmt) { char buf[MAXPDSTRING]; vsprintf(buf, callerfmt, ap); loudx_setcontext(lc, caller, buf, lc->lc_selector, 0, 0); } else loudx_setcontext(lc, caller, 0, lc->lc_selector, 0, 0); va_end(ap); } t_symbol *loudx_getselector(t_loudcontext *lc) { return (lc->lc_selector); } t_atom *loudx_getarguments(t_loudcontext *lc, int *acp) { *acp = lc->lc_ac; return (lc->lc_av); } void loudx_freecontext(t_loudcontext *lc) { if (lc->lc_callername) freebytes(lc->lc_callername, lc->lc_cnsize); freebytes(lc, sizeof(*lc)); } t_loudcontext *loudx_newcontext(t_pd *caller, char *callername, t_symbol *s, int ac, t_atom *av) { t_loudcontext *lc = getbytes(sizeof(*lc)); lc->lc_callername = 0; loudx_setcontext(lc, caller, callername, s, ac, av); return (lc); } void loudbug_post(char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsnprintf(buf, MAXPDSTRING-1, fmt, ap); va_end(ap); fprintf(stderr, "%s\n", buf); #ifdef MSW fflush(stderr); #endif } void loudbug_startpost(char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsnprintf(buf, MAXPDSTRING-1, fmt, ap); va_end(ap); fputs(buf, stderr); #ifdef MSW fflush(stderr); #endif } void loudbug_stringpost(char *s) { fputs(s, stderr); #ifdef MSW fflush(stderr); #endif } void loudbug_endpost(void) { fputs("\n", stderr); #ifdef MSW fflush(stderr); #endif } void loudbug_postatom(int ac, t_atom *av) { while (ac--) { char buf[MAXPDSTRING]; atom_string(av++, buf, MAXPDSTRING); fprintf(stderr, " %s", buf); #ifdef MSW fflush(stderr); #endif } } void loudbug_postbinbuf(t_binbuf *bb) { int ac = binbuf_getnatom(bb); t_atom *aprev = 0, *ap = binbuf_getvec(bb); while (ac--) { char buf[MAXPDSTRING]; atom_string(ap, buf, MAXPDSTRING); if (aprev) { if (aprev->a_type == A_SEMI) fprintf(stderr, "\n%s", buf); else fprintf(stderr, " %s", buf); } else fprintf(stderr, "%s", buf); #ifdef MSW fflush(stderr); #endif aprev = ap++; } if (aprev) { fputs("\n", stderr); #ifdef MSW fflush(stderr); #endif } } void loudbug_bug(char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsnprintf(buf, MAXPDSTRING-1, fmt, ap); va_end(ap); fprintf(stderr, "miXed consistency check failed: %s\n", buf); #ifdef MSW fflush(stderr); #endif bug(buf); } cyclone-0.1-alpha55/shared/common/dict.h0000644000076500007650000000165311466617452016574 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __DICT_H__ #define __DICT_H__ typedef struct _dict { size_t d_hashsize; t_symbol **d_hashtable; t_class *d_bindlist_class; } t_dict; typedef int (*t_dict_hook)(t_pd *x, void *arg); t_dict *dict_new(size_t hashsize); void dict_free(t_dict *x); t_symbol *dict_dokey(t_dict *x, char *s, t_symbol *oldsym); t_symbol *dict_key(t_dict *x, char *s); void dict_bind(t_dict *x, t_pd *obj, t_symbol *s); void dict_unbind(t_dict *x, t_pd *obj, t_symbol *s); t_pd *dict_firstvalue(t_dict *dict, t_symbol *s, void **nextp); t_pd *dict_nextvalue(t_dict *dict, t_symbol *s, void **nextp); #if 0 t_pd *dict_xvalue(t_dict *x, t_symbol *s); #endif int dict_forall(t_dict *x, t_symbol *s, t_dict_hook hook, void *hookarg); #endif cyclone-0.1-alpha55/shared/common/qtree.h0000644000076500007650000000467411466617452016777 0ustar hanshans/* Copyright (c) 2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __QTREE_H__ #define __QTREE_H__ #ifdef KRZYSZCZ #define QTREE_DEBUG #endif typedef enum { QTREETYPE_FLOAT, QTREETYPE_SYMBOL, QTREETYPE_ATOM, QTREETYPE_CUSTOM, QTREETYPE_ILLEGAL } t_qtreetype; typedef struct _qnode { double n_key; int n_black; struct _qnode *n_left; struct _qnode *n_right; struct _qnode *n_parent; struct _qnode *n_prev; struct _qnode *n_next; } t_qnode; typedef struct _qnode_float { t_qnode nf_node; t_float nf_value; } t_qnode_float; typedef struct _qnode_symbol { t_qnode ns_node; t_symbol *ns_value; } t_qnode_symbol; typedef struct _qnode_atom { t_qnode na_node; t_atom na_value; } t_qnode_atom; typedef struct _qtree { t_qnode *t_root; t_qnode *t_first; t_qnode *t_last; t_qtreetype t_valuetype; size_t t_nodesize; } t_qtree; #define QNODE_GETFLOAT(np) (((t_qnode_float *)(np))->nf_value) #define QNODE_GETSYMBOL(np) (((t_qnode_symbol *)(np))->ns_value) #define QNODE_GETATOMPTR(np) (&((t_qnode_atom *)(np))->na_value) typedef void (*t_qnode_vshowhook)(t_qnode *, char *, unsigned); t_qnode *qtree_search(t_qtree *tree, double key); t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap); t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap); t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap); t_qnode *qtree_insert(t_qtree *tree, double key, t_qnode *preexisting, int *foundp); t_qnode *qtree_multiinsert(t_qtree *tree, double key, t_qnode *preexisting, int fifoflag); t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode); t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f, int replaceflag); t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s, int replaceflag); t_qnode *qtree_insertatom(t_qtree *tree, double key, t_atom *ap, int replaceflag); void qtree_delete(t_qtree *tree, t_qnode *np); void qtree_inittyped(t_qtree *tree, t_qtreetype vtype, int freecount); void qtree_initcustom(t_qtree *tree, size_t nodesize, int freecount); void qtree_clear(t_qtree *tree, int freecount); #ifdef QTREE_DEBUG void qtree_debug(t_qtree *tree, int level, t_qnode_vshowhook hook); #endif #endif cyclone-0.1-alpha55/shared/common/clc.h0000644000076500007650000000046111466617452016406 0ustar hanshans/* Copyright (c) 2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __CLC_H__ #define __CLC_H__ void clccurve_coefs(int nhops, double crv, double *bbp, double *mmp); #endif cyclone-0.1-alpha55/shared/common/messtree.c0000644000076500007650000000742011466617452017471 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This module covers parsing of a single message received by an object or used for creation of an object, as well as parsing of multiple messages contained in an imported buffer, etc. */ #include "m_pd.h" #include "common/loud.h" #include "messtree.h" #ifdef KRZYSZCZ #define MESSTREE_DEBUG #endif /* There are two different messtree structures: the compile-time input (t_messslot/t_messnode) and the run-time one (t_messtree). The reasons are: to allow plugins to extend a message tree, and to make the compile-time input initializer-friendly. */ struct _messtree { t_messslot *mt_slot; t_symbol *mt_selector; t_messcall mt_method; int mt_nonexclusive; struct _messtree *mt_sublist; struct _messtree *mt_next; }; t_messtree *messtree_new(t_symbol *selector) { t_messtree *mt = getbytes(sizeof(*mt)); mt->mt_slot = 0; mt->mt_selector = selector; mt->mt_method = 0; /* LATER define a default */ mt->mt_nonexclusive = 0; mt->mt_sublist = 0; mt->mt_next = 0; return (mt); } static void messtree_addnode(t_messtree *mt, t_messnode *mn) { /* LATER respect mn->mn_index */ t_messslot *ms; int i; for (i = 0, ms = mn->mn_table + mn->mn_nslots - 1; i < mn->mn_nslots; i++, ms--) { t_messtree *bch = messtree_new(gensym(ms->ms_name)); bch->mt_slot = ms; bch->mt_method = ms->ms_call; bch->mt_nonexclusive = (ms->ms_flags & MESSTREE_NONEXCLUSIVE); bch->mt_next = mt->mt_sublist; mt->mt_sublist = bch; if (ms->ms_subnode) messtree_addnode(bch, ms->ms_subnode); } } void messtree_add(t_messtree *mt, t_messnode *rootnode) { messtree_addnode(mt, rootnode); } t_messtree *messtree_build(t_messslot *rootslot) { t_messtree *mt = messtree_new(gensym(rootslot->ms_name)); mt->mt_slot = rootslot; mt->mt_method = rootslot->ms_call; mt->mt_nonexclusive = (rootslot->ms_flags & MESSTREE_NONEXCLUSIVE); mt->mt_sublist = 0; mt->mt_next = 0; if (rootslot->ms_subnode) messtree_addnode(mt, rootslot->ms_subnode); return (mt); } int messtree_doit(t_messtree *mt, t_messslot **msp, int *nargp, t_pd *target, t_symbol *s, int ac, t_atom *av) { int result = MESSTREE_OK, nargpdummy; t_messslot *mspdummy; if (!msp) msp = &mspdummy; if (!nargp) nargp = &nargpdummy; if (s && s != mt->mt_selector) { loud_warning(target, (target ? 0 : "messtree"), "unexpected selector \"%s\"", s->s_name); *msp = 0; *nargp = 0; return (MESSTREE_CORRUPT); } if (ac && av->a_type == A_SYMBOL) { t_messtree *bch; for (bch = mt->mt_sublist; bch; bch = bch->mt_next) { if (av->a_w.w_symbol == bch->mt_selector) { if (bch->mt_sublist) return (messtree_doit(bch, msp, nargp, target, av->a_w.w_symbol, ac - 1, av + 1)); else { if (target && bch->mt_method) result = bch->mt_method(target, av->a_w.w_symbol, ac - 1, av + 1); *msp = (result == MESSTREE_OK ? bch->mt_slot : 0); *nargp = ac - 1; return (result); } } } if (mt->mt_nonexclusive) { if (target && mt->mt_method) result = mt->mt_method(target, 0, ac, av); /* LATER rethink */ *msp = (result == MESSTREE_OK ? mt->mt_slot : 0); *nargp = ac; return (result); } else { loud_warning(target, (target ? 0 : "messtree"), "unknown property \"%s\"", av->a_w.w_symbol->s_name); *msp = 0; *nargp = 0; return (MESSTREE_UNKNOWN); } } else { if (target && mt->mt_method) result = mt->mt_method(target, 0, ac, av); *msp = (result == MESSTREE_OK ? mt->mt_slot : 0); *nargp = ac; return (result); } } cyclone-0.1-alpha55/shared/common/vefl.h0000644000076500007650000000227211466617452016603 0ustar hanshans/* Copyright (c) 2001-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __VEFL_H__ #define __VEFL_H__ typedef struct _vefl { int v_autoalloc; t_symbol *v_name; t_glist *v_glist; t_garray *v_garray; int v_size; t_float *v_data; t_symbol *v_type; t_clock *v_clock; int v_clockset; double v_updtime; } t_vefl; t_float *vefl_get(t_symbol *name, int *vszp, int indsp, t_pd *complain); t_vefl *vefl_new(t_symbol *name, int writable, t_glist *gl, t_garray *arr); t_vefl *vefl_placement_new(t_vefl *vp, t_symbol *name, int writable, t_glist *gl, t_garray *arr); void vefl_free(t_vefl *vp); int vefl_renew(t_vefl *vp, t_symbol *name, t_pd *complain); void vefl_redraw(t_vefl *vp, float suppresstime); void vefl_redraw_stop(t_vefl *vp); void vefl_getbounds(t_vefl *vp, t_float *xminp, t_float *yminp, t_float *xmaxp, t_float *ymaxp); void vefl_setbounds(t_vefl *vp, t_float xmin, t_float ymin, t_float xmax, t_float ymax); void vefl_getrange(t_vefl *vp, t_float *yminp, t_float *ymaxp); #endif cyclone-0.1-alpha55/shared/common/binport.h0000644000076500007650000000157211466617452017326 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __BINPORT_H__ #define __BINPORT_H__ /* return values of binport_read() and import_max(), also passed to outlet_float() by cyclone library objects (cyclone, maxmode...) */ #define BINPORT_FAILED -4 /* internal error */ #define BINPORT_CORRUPT -3 /* file contents inconsistency */ #define BINPORT_INVALID -2 /* file type not recognized */ #define BINPORT_NOFILE -1 /* file not found */ #define BINPORT_MAXBINARY 0 #define BINPORT_MAXTEXT 1 #define BINPORT_MAXOLD 2 #define BINPORT_PDFILE 3 #ifndef MIXED_STANDALONE int binport_read(t_binbuf *bb, char *filename, char *dirname); void binport_write(t_binbuf *bb, char *filename, char *dirname); #endif #endif cyclone-0.1-alpha55/shared/common/grow.c0000644000076500007650000000565611466617452016631 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER generic handling of reentrant output request and self-invoked set */ #include #include "m_pd.h" #include "grow.h" /* Prior to this call a caller is supposed to check for *nrequested > *sizep. Returns a reallocated buffer's pointer (success) or a given 'bufini' default value (failure). Upon return *nrequested contains the actual number of elements: requested (success) or a given default value of 'inisize' (failure). */ void *grow_nodata(int *nrequested, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize) { int newsize = *sizep * 2; while (newsize < *nrequested) newsize *= 2; if (bufp == bufini) bufp = getbytes(newsize * typesize); else bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize); if (bufp) { *sizep = newsize; return (bufp); } else { *nrequested = *sizep = inisize; return (bufini); } } /* Like grow_nodata(), but preserving first *nexisting elements. */ void *grow_withdata(int *nrequested, int *nexisting, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize) { int newsize = *sizep * 2; while (newsize < *nrequested) newsize *= 2; if (bufp == bufini) { if (!(bufp = getbytes(newsize * typesize))) { *nrequested = *sizep = inisize; return (bufini); } *sizep = newsize; memcpy(bufp, bufini, *nexisting * typesize); } else { int oldsize = *sizep; if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize))) { *nrequested = *sizep = inisize; *nexisting = 0; return (bufini); } *sizep = newsize; } return (bufp); } /* Like grow_nodata(), but preserving a 'tail' of *nexisting elements, starting from *startp. */ /* LATER rethink handling of a start pointer (clumsy now) */ void *grow_withtail(int *nrequested, int *nexisting, char **startp, int *sizep, void *bufp, int inisize, void *bufini, size_t typesize) { int newsize = *sizep * 2; while (newsize < *nrequested) newsize *= 2; if (bufp == bufini) { char *oldstart = *startp; if (!(bufp = getbytes(newsize * typesize))) { *nrequested = *sizep = inisize; return (bufini); } *startp = (char *)bufp + (newsize - *nexisting) * typesize; *sizep = newsize; memcpy(*startp, oldstart, *nexisting * typesize); } else { int oldsize = *sizep; if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize))) { *startp = (char *)bufini + inisize * typesize; *nrequested = *sizep = inisize; *nexisting = 0; return (bufini); } *startp = (char *)bufp + (newsize - *nexisting) * typesize; *sizep = newsize; memmove(*startp, (char *)bufp + (oldsize - *nexisting) * typesize, *nexisting * typesize); } return (bufp); } cyclone-0.1-alpha55/shared/common/clc.c0000644000076500007650000000537411466617452016411 0ustar hanshans/* Copyright (c) 2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "clc.h" /* Problem: find a function f : p -> q (where p is user's curve control parameter, q is log factor) such that the curves will bend in a semi-linear way over the p's range of 0..1. The curve function is then g(x, p) = (exp(f(p) * x) - 1) / (exp(f(p)) - 1), where x is curve's domain. If, for example, the points g(0.5, p) are to make a semi-linear pattern, then the solution is a function f that minimizes the integral of the error function e(p) = sqr(((1-p)/2)-g(.5, p)) over 0..1. Until someone does this analytically, we are left with a lame formula, which has been tweaked and tested in gnuplot: f(p) = h(p) / (1 - h(p)), where h(p) = (((p + 1e-20) * 1.2) ** .41) * .91. The file curve.gp, in the sickle's source directory, may come handy, in case there is anyone, who fancy tweaking it even further. To implement this, start from these equations: nhops = npoints - 1 bb * mm ^ nhops = bb + 1 (bb ^ 2) * (mm ^ nhops) = ((exp(ff/2) - 1) / (exp(ff) - 1)) ^ 2 and calculate: hh = pow(((p + c1) * c2), c3) * c4 ff = hh / (1 - hh) eff = exp(ff) - 1 gh = (exp(ff * .5) - 1) / eff bb = gh * (gh / (1 - (gh + gh))) mm = ((exp(ff * (1/nhops)) - 1) / (eff * bb)) + 1 The loop is: for (vv = bb, i = 0; i <= nhops; vv *= mm, i++) result = (vv - bb) * (y1 - y0) + y0 where y0, y1 are start and destination values This formula generates curves with < .000004% deviation from the straight line for p = 0 at half-domain, range 1. There are no nans for -1 <= p <= 1. */ #define CLCCURVE_C1 1e-20 #define CLCCURVE_C2 1.2 #define CLCCURVE_C3 0.41 #define CLCCURVE_C4 0.91 void clccurve_coefs(int nhops, double crv, double *bbp, double *mmp) { if (nhops > 0) { double hh, ff, eff, gh; if (crv < 0) { if (crv < -1.) crv = -1.; hh = pow(((CLCCURVE_C1 - crv) * CLCCURVE_C2), CLCCURVE_C3) * CLCCURVE_C4; ff = hh / (1. - hh); eff = exp(ff) - 1.; gh = (exp(ff * .5) - 1.) / eff; *bbp = gh * (gh / (1. - (gh + gh))); *mmp = 1. / (((exp(ff * (1. / (double)nhops)) - 1.) / (eff * *bbp)) + 1.); *bbp += 1.; } else { if (crv > 1.) crv = 1.; hh = pow(((crv + CLCCURVE_C1) * CLCCURVE_C2), CLCCURVE_C3) * CLCCURVE_C4; ff = hh / (1. - hh); eff = exp(ff) - 1.; gh = (exp(ff * .5) - 1.) / eff; *bbp = gh * (gh / (1. - (gh + gh))); *mmp = ((exp(ff * (1. / (double)nhops)) - 1.) / (eff * *bbp)) + 1.; } } else if (crv < 0) *bbp = 2., *mmp = 1.; else *bbp = *mmp = 1.; } cyclone-0.1-alpha55/shared/common/vefl.c0000644000076500007650000001247311466617452016602 0ustar hanshans/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* The simplest of garrays: vector of floats */ /* Array checking is done in three points: 1. vefl_new(): never complains 2. vefl_renew(): this should be called once per every message 3. vefl_tick(): no template checking (only redraw is involved) */ /* LATER rethink indsp flag */ #include "m_pd.h" #include "g_canvas.h" #include "shared.h" #include "unstable/fragile.h" #include "common/loud.h" #include "vefl.h" #ifdef KRZYSZCZ //#define VEFL_DEBUG #endif #define VEFL_VERBOSE /* on failure *vszp is not modified */ t_float *vefl_get(t_symbol *name, int *vszp, int indsp, t_pd *complain) { if (name && name != &s_) { t_garray *ap = (t_garray *)pd_findbyclass(name, garray_class); if (ap) { int vsz; t_float *vec; if (garray_getfloatarray(ap, &vsz, &vec)) { if (indsp) garray_usedindsp(ap); if (vszp) *vszp = vsz; return (vec); } else loud_error(complain, /* always complain */ "bad template of array '%s'", name->s_name); } else if (complain) loud_error(complain, "no such array '%s'", name->s_name); } return (0); } static void vefl_tick(t_vefl *vp) { if (vp->v_name && vp->v_name != &s_ /* Check if an array has not been deleted (e.g. during patch closing sequence). */ && (vp->v_garray = (t_garray *)pd_findbyclass(vp->v_name, garray_class))) { vp->v_glist = fragile_garray_glist(vp->v_garray); garray_redraw(vp->v_garray); } vp->v_clockset = 0; vp->v_updtime = clock_getsystime(); } t_vefl *vefl_placement_new(t_vefl *vp, t_symbol *name, int writable, t_glist *gl, t_garray *arr) { if (sizeof(t_word) != sizeof(t_float)) { loudbug_bug("vefl_new: sizeof(t_word) != sizeof(t_float)"); return (0); } if (!vp) { if (!(vp = getbytes(sizeof(*vp)))) return (0); vp->v_autoalloc = 1; } else vp->v_autoalloc = 0; vp->v_name = name; if (writable) { vp->v_updtime = clock_getsystime(); vp->v_clock = clock_new(vp, (t_method)vefl_tick); vp->v_clockset = 0; } else vp->v_clock = 0; vp->v_glist = gl; vp->v_garray = arr; vp->v_size = 0; vp->v_data = 0; vp->v_type = &s_float; if (!arr && name && name != &s_) { vp->v_garray = (t_garray *)pd_findbyclass(name, garray_class); vp->v_glist = vp->v_garray ? fragile_garray_glist(vp->v_garray) : 0; } if (vp->v_garray && !garray_getfloatarray(vp->v_garray, &vp->v_size, &vp->v_data)) { vp->v_glist = 0; vp->v_garray = 0; vp->v_type = 0; /* template mismatch */ } return (vp); } t_vefl *vefl_new(t_symbol *name, int writable, t_glist *gl, t_garray *arr) { return (vefl_placement_new(0, name, writable, gl, arr)); } void vefl_free(t_vefl *vp) { if (vp->v_clock) clock_free(vp->v_clock); if (vp->v_autoalloc) freebytes(vp, sizeof(*vp)); } /* LATER handle yonset */ int vefl_renew(t_vefl *vp, t_symbol *name, t_pd *complain) { if (!name || name == &s_) name = vp->v_name; if (name && name != &s_) { vp->v_glist = 0; /* There are three possible ways: */ #if 0 vp->v_name = 0; #elif 1 /* , do nothing, and */ vp->v_name = name; #endif /* LATER check all the cases and decide... */ if (!(vp->v_garray = (t_garray *)pd_findbyclass(name, garray_class))) { if (complain) loud_error(complain, "no such array '%s'", name->s_name); } else if (!garray_getfloatarray(vp->v_garray, &vp->v_size, &vp->v_data)) { vp->v_garray = 0; loud_error(complain, /* always complain */ "bad template of array '%s'", name->s_name); } else { vp->v_glist = fragile_garray_glist(vp->v_garray); vp->v_name = name; return (1); } } return (0); } void vefl_redraw(t_vefl *vp, float suppresstime) { if (vp->v_clock) /* requests from readers are ignored */ { if (suppresstime > 0) { double timesince = clock_gettimesince(vp->v_updtime); if (timesince > suppresstime) { clock_unset(vp->v_clock); vefl_tick(vp); } else if (!vp->v_clockset) { clock_delay(vp->v_clock, suppresstime - timesince); vp->v_clockset = 1; } } else { clock_unset(vp->v_clock); vefl_tick(vp); } } } void vefl_redraw_stop(t_vefl *vp) { if (vp->v_clock) /* requests from readers are ignored */ { clock_unset(vp->v_clock); vp->v_clockset = 0; } } /* Y-bounds flipped here */ void vefl_getbounds(t_vefl *vp, t_float *xminp, t_float *yminp, t_float *xmaxp, t_float *ymaxp) { t_glist *gl = vp->v_glist; if (gl) { *xminp = gl->gl_x1; *xmaxp = gl->gl_x2; *yminp = gl->gl_y2; *ymaxp = gl->gl_y1; } } /* Y-bounds flipped here */ void vefl_setbounds(t_vefl *vp, t_float xmin, t_float ymin, t_float xmax, t_float ymax) { vmess((t_pd *)vp->v_glist, gensym("bounds"), "ffff", xmin, ymax, xmax, ymin); } void vefl_getrange(t_vefl *vp, t_float *yminp, t_float *ymaxp) { int vsz = vp->v_size; t_float *vec = vp->v_data; if (vec && vsz) { t_float ymin = SHARED_FLT_MAX, ymax = -SHARED_FLT_MAX; while (vsz--) { if (*vec > ymax) { ymax = *vec; if (ymax < ymin) ymin = ymax; } else if (*vec < ymin) ymin = *vec; vec++; } *yminp = ymin; *ymaxp = ymax; } } cyclone-0.1-alpha55/shared/common/mifi.h0000644000076500007650000001053511466617452016574 0ustar hanshans/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __MIFI_H__ #define __MIFI_H__ EXTERN_STRUCT _mifiread; #define t_mifiread struct _mifiread EXTERN_STRUCT _mifiwrite; #define t_mifiwrite struct _mifiwrite typedef int (*t_mifireadhook)(t_mifiread *mf, void *hookdata, int evtype); #define MIFI_MAXTRACKS 0x7fff #define MIFI_MAXBEATTICKS 0x7fff /* event types, as returned by mifiread_nextevent(), ... */ #define MIFIREAD_FATAL -3 /* unexpected eof, last track's or file error */ #define MIFIREAD_EOF -2 /* regular eof */ #define MIFIREAD_SKIP -1 /* error and successful skip to the next track */ #define MIFIMETA_SEQNUM 0 #define MIFIMETA_TEXT 1 #define MIFIMETA_COPYRIGHT 2 #define MIFIMETA_TRACKNAME 3 #define MIFIMETA_INSTRUMENT 4 #define MIFIMETA_LYRIC 5 #define MIFIMETA_MARKER 6 #define MIFIMETA_CUE 7 #define MIFIMETA_MAXPRINTABLE 15 /* 1..15 are various text meta-events */ #define MIFIMETA_CHANNEL 0x20 /* channel prefix (obsolete) */ #define MIFIMETA_PORT 0x21 /* port prefix (obsolete) */ #define MIFIMETA_EOT 0x2f /* end of track */ #define MIFIMETA_TEMPO 0x51 #define MIFIMETA_SMPTE 0x54 /* SMPTE offset */ #define MIFIMETA_TIMESIG 0x58 /* time signature */ #define MIFIMETA_KEYSIG 0x59 /* key signature */ #define MIFIMETA_PROPRIETARY 0x7f /* ...channel status codes go here, too obvious to #define... */ #define MIFISYSEX_FIRST 0xf0 #define MIFISYSEX_NEXT 0xf7 #define MIFISYSEX_ESCAPE 0xf7 /* without preceding MIFISYSEX_FIRST */ /* this code is not returned as an event type, but in e_status of t_mifievent */ #define MIFIEVENT_META 0xff /* system messages (expected inside of sysex escape events) */ #define MIFISYS_SONGPOINTER 0xf2 #define MIFISYS_SONGSELECT 0xf3 #define MIFISYS_TUNEREQUEST 0xf6 #define MIFISYS_CLOCK 0xf8 #define MIFISYS_START 0xfa #define MIFISYS_CONTINUE 0xfb #define MIFISYS_STOP 0xfc #define MIFISYS_ACTIVESENSING 0xfe /* true if one of channel messages */ #define MIFI_ISCHANNEL(status) (((status) & 0x80) && (status) < 0xf0) /* true if one of the two shorter channel messages */ #define MIFI_ONEDATABYTE(status) (((status) & 0xe0) == 0xc0) int mifiread_getnevents(t_mifiread *mr); int mifiread_getntempi(t_mifiread *mr); int mifiread_gethdtracks(t_mifiread *mr); int mifiread_getformat(t_mifiread *mr); int mifiread_getnframes(t_mifiread *mr); int mifiread_getbeatticks(t_mifiread *mr); double mifiread_getdeftempo(t_mifiread *mr); int mifiread_getbarindex(t_mifiread *mr); double mifiread_getbarspan(t_mifiread *mr); double mifiread_gettick(t_mifiread *mr); double mifiread_getscoretime(t_mifiread *mr); double mifiread_gettempo(t_mifiread *mr); double mifiread_getmscoef(t_mifiread *mr); t_symbol *mifiread_gettrackname(t_mifiread *mr); unsigned mifiread_getstatus(t_mifiread *mr); unsigned mifiread_getdata1(t_mifiread *mr); unsigned mifiread_getdata2(t_mifiread *mr); unsigned mifiread_getchannel(t_mifiread *mr); t_pd *mifiread_getowner(t_mifiread *mr); t_mifiread *mifiread_new(t_pd *owner); void mifiread_setuserticks(t_mifiread *mr, double wholeticks); int mifiread_open(t_mifiread *mr, const char *filename, const char *dirname, int complain); int mifiread_doit(t_mifiread *mr, t_mifireadhook hook, void *hookdata); void mifiread_close(t_mifiread *mr); void mifiread_free(t_mifiread *mr); t_mifiwrite *mifiwrite_new(t_pd *owner); void mifiwrite_sethardticks(t_mifiwrite *mw, int beatticks); void mifiwrite_setuserticks(t_mifiwrite *mw, double wholeticks); void mifiwrite_setusertempo(t_mifiwrite *mw, double tickspersec); int mifiwrite_open(t_mifiwrite *mw, const char *filename, const char *dirname, int ntracks, int complain); int mifiwrite_opentrack(t_mifiwrite *mw, char *trackname, int complain); int mifiwrite_textevent(t_mifiwrite *mw, double delay, unsigned type, char *text); int mifiwrite_channelevent(t_mifiwrite *mw, double delay, unsigned status, unsigned channel, unsigned data1, unsigned data2); int mifiwrite_closetrack(t_mifiwrite *mw, double enddelay, int complain); void mifiwrite_close(t_mifiwrite *mw); void mifiwrite_free(t_mifiwrite *mw); #endif cyclone-0.1-alpha55/shared/common/os.c0000644000076500007650000001567111466617452016272 0ustar hanshans/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifdef MSW #include #else #include #include #endif #include #include #include #include "m_pd.h" #include "os.h" static int ospath_doabsolute(char *path, char *cwd, char *result) { if (*path == 0) { if (result) strcpy(result, cwd); else return (strlen(cwd)); } else if (*path == '~') { path++; if (*path == '/' || *path == 0) { #ifdef UNIX char *home = getenv("HOME"); if (home) { if (result) { strcpy(result, home); if (*path) strcat(result, path); } else return (strlen(home) + strlen(path)); } else goto badpath; #else goto badpath; #endif } else goto badpath; } else if (*path == '/') { #ifdef MSW /* path is absolute, drive is implicit, LATER UNC? */ if (*cwd && cwd[1] == ':') { if (result) { *result = *cwd; result[1] = ':'; strcpy(result + 2, path); } else return (2 + strlen(path)); } else goto badpath; #else /* path is absolute */ if (result) strcpy(result, path); else return (strlen(path)); #endif } else { #ifdef MSW if (path[1] == ':') { if (path[2] == '/') { /* path is absolute */ if (result) strcpy(result, path); else return (strlen(path)); } else if (*cwd == *path) { /* path is relative, drive is explicitly current */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path + 2); } else return (strlen(cwd) + strlen(path) - 1); } /* we do not maintain per-drive cwd, LATER rethink */ else goto badpath; } /* LATER devices? */ else { /* path is relative */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path); } else return (strlen(cwd) + 1 + strlen(path)); } #else /* path is relative */ if (result) { int ndx = strlen(cwd); strcpy(result, cwd); result[ndx++] = '/'; strcpy(result + ndx, path); } else return (strlen(cwd) + 1 + strlen(path)); #endif } if (result && *result && *result != '.') { /* clean-up */ char *inptr, *outptr = result; int ndx = strlen(result); if (result[ndx - 1] == '.') { result[ndx] = '/'; /* guarding slash */ result[ndx + 1] = 0; } for (inptr = result + 1; *inptr; inptr++) { if (*inptr == '/') { if (*outptr == '/') continue; else if (*outptr == '.') { if (outptr[-1] == '/') { outptr--; continue; } else if (outptr[-1] == '.' && outptr[-2] == '/') { outptr -= 2; if (outptr == result) continue; else for (outptr--; outptr != result; outptr--) if (*outptr == '/') break; continue; } } } *++outptr = *inptr; } if (*outptr == '/' && outptr != result) *outptr = 0; else outptr[1] = 0; } else bug("ospath_doabsolute 1"); return (0); badpath: if (result) bug("ospath_doabsolute 2"); return (0); } /* Returns an estimated length of an absolute path made up from the first arg. The actual ospath_absolute()'s length may be shorter (since it erases superfluous slashes and dots), but not longer. Both args should be unbashed (system-independent), cwd should be absolute. Returns 0 in case of any error (LATER revisit). */ int ospath_length(char *path, char *cwd) { /* one extra byte used internally (guarding slash) */ return (ospath_doabsolute(path, cwd, 0) + 1); } /* Copies an absolute path to result. Arguments: path and cwd, are the same as in ospath_length(). Caller should first consult ospath_length(), and allocate at least ospath_length() + 1 bytes to the result buffer. Should never fail (failure is a bug). */ char *ospath_absolute(char *path, char *cwd, char *result) { ospath_doabsolute(path, cwd, result); return (result); } FILE *fileread_open(char *filename, t_canvas *cv, int textmode) { int fd; char path[MAXPDSTRING+2], *nameptr; t_symbol *dirsym = (cv ? canvas_getdir(cv) : 0); /* path arg is returned unbashed (system-independent) */ if ((fd = open_via_path((dirsym ? dirsym->s_name : ""), filename, "", path, &nameptr, MAXPDSTRING, 1)) < 0) return (0); /* Closing/reopening dance. This is unnecessary under linux, and we could have tried to convert fd to fp, but under windows open_via_path() returns what seems to be an invalid fd. LATER try to understand what is going on here... */ close(fd); if (path != nameptr) { char *slashpos = path + strlen(path); *slashpos++ = '/'; /* try not to be dependent on current open_via_path() implementation */ if (nameptr != slashpos) strcpy(slashpos, nameptr); } sys_bashfilename(path, path); return (fopen(path, (textmode ? "r" : "rb"))); } FILE *filewrite_open(char *filename, t_canvas *cv, int textmode) { char path[MAXPDSTRING+2]; if (cv) /* path arg is returned unbashed (system-independent) */ canvas_makefilename(cv, filename, path, MAXPDSTRING); else { strncpy(path, filename, MAXPDSTRING); path[MAXPDSTRING-1] = 0; } sys_bashfilename(path, path); return (fopen(path, (textmode ? "w" : "wb"))); } /* FIXME add MSW */ struct _osdir { #ifndef MSW DIR *dir_handle; struct dirent *dir_entry; #endif int dir_flags; }; /* returns 0 on error, a caller is then expected to call loud_syserror(owner, "cannot open \"%s\"", dirname) */ t_osdir *osdir_open(char *dirname) { #ifndef MSW DIR *handle = opendir(dirname); if (handle) { #endif t_osdir *dp = getbytes(sizeof(*dp)); #ifndef MSW dp->dir_handle = handle; dp->dir_entry = 0; #endif dp->dir_flags = 0; return (dp); #ifndef MSW } else return (0); #endif } void osdir_setmode(t_osdir *dp, int flags) { if (dp) dp->dir_flags = flags; } void osdir_close(t_osdir *dp) { if (dp) { #ifndef MSW closedir(dp->dir_handle); #endif freebytes(dp, sizeof(*dp)); } } void osdir_rewind(t_osdir *dp) { if (dp) { #ifndef MSW rewinddir(dp->dir_handle); dp->dir_entry = 0; #endif } } char *osdir_next(t_osdir *dp) { #ifndef MSW if (dp) { while (dp->dir_entry = readdir(dp->dir_handle)) { if (!dp->dir_flags || (dp->dir_entry->d_type == DT_REG && (dp->dir_flags & OSDIR_FILEMODE)) || (dp->dir_entry->d_type == DT_DIR && (dp->dir_flags & OSDIR_DIRMODE))) return (dp->dir_entry->d_name); } } #endif return (0); } int osdir_isfile(t_osdir *dp) { #ifndef MSW return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_REG); #else return (0); #endif } int osdir_isdir(t_osdir *dp) { #ifndef MSW return (dp && dp->dir_entry && dp->dir_entry->d_type == DT_DIR); #else return (0); #endif } cyclone-0.1-alpha55/shared/common/mifi.c0000644000076500007650000011255111466617452016570 0ustar hanshans/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifdef NT #include #else #include #endif #include #include #include #include #include #include "m_pd.h" #include "mifi.h" #ifdef __linux__ #include #ifndef uint32 typedef u_int32_t uint32; #endif #ifndef uint16 typedef u_int16_t uint16; #endif #ifndef uchar typedef u_int8_t uchar; #endif #elif defined(NT) #ifndef uint32 typedef unsigned long uint32; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #elif defined(IRIX) #ifndef uint32 typedef unsigned long uint32; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #elif defined(__FreeBSD__) #include #ifndef uint32 typedef u_int32_t uint32; #endif #ifndef uint16 typedef u_int16_t uint16; #endif #ifndef uchar typedef u_int8_t uchar; #endif #else /* MACOSX */ #ifndef uint32 typedef unsigned int uint32; #endif #ifndef uint16 typedef unsigned short uint16; #endif #ifndef uchar typedef unsigned char uchar; #endif #endif #ifdef KRZYSZCZ # include "loud.h" # define MIFI_DEBUG #else # define loudbug_bug(msg) fprintf(stderr, "BUG: %s\n", msg), bug(msg) #endif #define MIFI_VERBOSE #define MIFI_SHORTESTEVENT 2 /* singlebyte delta and one databyte */ #define MIFI_TICKEPSILON ((double).0001) #define MIFIHARD_HEADERSIZE 14 /* in case t_mifiheader is padded to 16 */ #define MIFIHARD_HEADERDATASIZE 6 #define MIFIHARD_TRACKHEADERSIZE 8 /* midi file standard defaults */ #define MIFIHARD_DEFBEATTICKS 192 #define MIFIHARD_DEFTEMPO 500000 /* 120 bpm in microseconds per beat */ /* user-space defaults */ #define MIFIUSER_DEFWHOLETICKS ((double)241920) /* whole note, 256*27*5*7 */ #define MIFIUSER_DEFTEMPO ((double)120960) /* 120 bpm in ticks/sec */ #define MIFIEVENT_NALLOC 256 /* LATER do some research (average max?) */ #define MIFIEVENT_INISIZE 2 /* always be able to handle channel events */ #define MIFIEVENT_MAXSYSEX 256 /* FIXME */ typedef struct _mifievent { uint32 e_delay; uchar e_status; uchar e_channel; uchar e_meta; /* meta-event type */ uint32 e_length; size_t e_datasize; uchar *e_data; uchar e_dataini[MIFIEVENT_INISIZE]; } t_mifievent; /* midi file header */ typedef struct _mifiheader { char h_type[4]; uint32 h_length; uint16 h_format; uint16 h_ntracks; uint16 h_division; } t_mifiheader; /* midi file track header */ typedef struct _mifitrackheader { char th_type[4]; uint32 th_length; } t_mifitrackheader; typedef struct _mifireadtx { double rt_wholeticks; /* userticks per whole note (set by user) */ double rt_deftempo; /* userticks per second (default, adjusted) */ double rt_tempo; /* userticks per second (current) */ double rt_tickscoef; /* userticks per hardtick */ double rt_mscoef; /* ms per usertick (current) */ double rt_userbar; /* userticks per bar */ uint16 rt_beatticks; /* hardticks per beat or per frame */ double rt_hardbar; /* hardticks per bar */ } t_mifireadtx; struct _mifiread { t_pd *mr_owner; FILE *mr_fp; t_mifiheader mr_header; t_mifievent mr_event; uint32 mr_scoretime; /* current time in hardticks */ uint32 mr_tempo; /* microseconds per beat */ uint32 mr_meternum; uint32 mr_meterden; uchar mr_status; uchar mr_channel; int mr_nevents; int mr_ntempi; uint16 mr_hdtracks; /* ntracks, as declared in the file header */ uint16 mr_ntracks; /* as actually contained in a file */ uint16 mr_trackndx; t_symbol **mr_tracknames; uchar mr_nframes; /* fps if nonzero, else use metrical time */ uint16 mr_format; /* anything > 0 handled as 1, FIXME */ uint32 mr_bytesleft; /* nbytes remaining to be read from a track */ int mr_pass; int mr_eof; /* set in case of early eof (error) */ int mr_newtrack; /* reset after reading track's first event */ t_mifireadtx mr_ticks; }; typedef struct _mifiwritetx { double wt_wholeticks; /* userticks per whole note (set by user) */ double wt_deftempo; /* userticks per second (default, adjusted) */ double wt_tempo; /* userticks per second (set by user, quantized) */ double wt_tickscoef; /* hardticks per usertick */ uint16 wt_beatticks; /* hardticks per beat or per frame (set by user) */ double wt_mscoef; /* hardticks per ms */ } t_mifiwritetx; struct _mifiwrite { t_pd *mw_owner; FILE *mw_fp; t_mifiheader mw_header; t_mifievent mw_event; uint32 mw_tempo; /* microseconds per beat */ uint32 mw_meternum; uint32 mw_meterden; uchar mw_status; uchar mw_channel; int mw_ntempi; uint16 mw_ntracks; uint16 mw_trackndx; t_symbol **mw_tracknames; uchar mw_nframes; /* fps if nonzero, else use metrical time */ uint16 mw_format; /* anything > 0 handled as 1, FIXME */ uint32 mw_trackbytes; /* nbytes written to a track so far */ int mw_trackdirty; /* after opentrack, before adjusttrack */ t_mifiwritetx mw_ticks; }; static int mifi_swapping = 1; static void mifi_initialize(void) { unsigned short s = 1; unsigned char c = *(char *)(&s); mifi_swapping = (c != 0); } static void mifi_error(t_pd *x, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); if (x) { startpost("%s's ", class_getname(*x)); pd_error(x, buf); } else post("mifi error: %s", buf); va_end(ap); } static void mifi_warning(t_pd *x, char *fmt, ...) { char buf[MAXPDSTRING]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); if (x) post("%s's warning: %s", class_getname(*x), buf); else post("mifi warning: %s", buf); va_end(ap); } static uint32 mifi_swap4(uint32 n) { if (mifi_swapping) return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); else return (n); } static uint16 mifi_swap2(uint16 n) { if (mifi_swapping) return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); else return (n); } static int mifievent_initialize(t_mifievent *ep, size_t nalloc) { ep->e_length = 0; if (ep->e_data = getbytes(nalloc)) { ep->e_datasize = nalloc; return (1); } else { ep->e_data = ep->e_dataini; ep->e_datasize = MIFIEVENT_INISIZE; return (0); } } static int mifievent_setlength(t_mifievent *ep, size_t length) { if (length > ep->e_datasize) { size_t newsize = ep->e_datasize; while (newsize < length) newsize *= 2; if (ep->e_data = resizebytes(ep->e_data, ep->e_datasize, newsize)) ep->e_datasize = newsize; else { ep->e_length = 0; /* rather hopeless... */ newsize = MIFIEVENT_NALLOC; if (ep->e_data = getbytes(newsize)) ep->e_datasize = newsize; else { ep->e_data = ep->e_dataini; ep->e_datasize = MIFIEVENT_INISIZE; } return (0); } } ep->e_length = (uint32)length; return (1); } static int mifievent_settext(t_mifievent *ep, unsigned type, char *text) { if (type > 127) { loudbug_bug("mifievent_settext"); return (0); } if (mifievent_setlength(ep, strlen(text) + 1)) { ep->e_status = MIFIEVENT_META; ep->e_meta = (uchar)type; strcpy(ep->e_data, text); return (1); } else { ep->e_status = 0; return (0); } } #ifdef MIFI_DEBUG static void mifi_printsysex(int length, uchar *buf) { loudbug_startpost("sysex:"); while (length--) loudbug_startpost(" %d", (int)*buf++); loudbug_endpost(); } static void mifievent_printsysex(t_mifievent *ep) { mifi_printsysex(ep->e_length, ep->e_data); } #endif static void mifievent_printmeta(t_mifievent *ep) { static int isprintable[MIFIMETA_MAXPRINTABLE+1] = { #ifdef MIFI_DEBUG 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 #elif defined MIFI_VERBOSE 0, 0, 1, 1, 1, 1, 1, 1 #endif }; static char *printformat[MIFIMETA_MAXPRINTABLE+1] = { "", "text: %s", "copyright: %s", "track name: %s", "instrument name: %s", "lyric: %s", "marker: %s", "cue point: %s" }; if (ep->e_meta <= MIFIMETA_MAXPRINTABLE) { #if 0 if (isprintable[ep->e_meta] && printformat[ep->e_meta]) post(printformat[ep->e_meta], ep->e_data); #endif } #ifdef MIFI_DEBUG else if (ep->e_meta == MIFIMETA_TEMPO) { int tempo = mifi_swap4(*(uint32 *)ep->e_data); loudbug_post("tempo (hard) %d after %d", tempo, ep->e_delay); } else if (ep->e_meta == MIFIMETA_TIMESIG) { loudbug_post("meter %d/%d after %d", ep->e_data[0], (1 << ep->e_data[1]), ep->e_delay); } #endif } static void mifiread_earlyeof(t_mifiread *mr) { mr->mr_bytesleft = 0; mr->mr_eof = 1; } /* Get next byte from track data. On error: return 0 (which is a valid result) and set mr->mr_eof. */ static uchar mifiread_getbyte(t_mifiread *mr) { if (mr->mr_bytesleft) { int c; if ((c = fgetc(mr->mr_fp)) == EOF) { mifiread_earlyeof(mr); return (0); } else { mr->mr_bytesleft--; return ((uchar)c); } } else return (0); } static uint32 mifiread_getbytes(t_mifiread *mr, uchar *buf, uint32 size) { size_t res; if (size > mr->mr_bytesleft) size = mr->mr_bytesleft; if ((res = fread(buf, 1, (size_t)size, mr->mr_fp)) == size) mr->mr_bytesleft -= res; else mifiread_earlyeof(mr); return (res); } static int mifiread_skipbytes(t_mifiread *mr, uint32 size) { if (size > mr->mr_bytesleft) size = mr->mr_bytesleft; if (size) { int res = fseek(mr->mr_fp, size, SEEK_CUR); if (res < 0) mifiread_earlyeof(mr); else mr->mr_bytesleft -= size; return res; } else return (0); } static uint32 mifiread_getvarlen(t_mifiread *mr) { uint32 n = 0; uchar c; uint32 count = mr->mr_bytesleft; if (count > 4) count = 4; while (count--) { n = (n << 7) + ((c = mifiread_getbyte(mr)) & 0x7f); if ((c & 0x80) == 0) break; } return (n); } static size_t mifiwrite_putvarlen(t_mifiwrite *mw, uint32 n) { uint32 buf = n & 0x7f; size_t length = 1; while ((n >>= 7) > 0) { buf <<= 8; buf |= 0x80; buf += n & 0x7f; length++; } return ((fwrite(&buf, 1, length, mw->mw_fp) == length) ? length : 0); } static void mifiread_updateticks(t_mifiread *mr) { if (mr->mr_nframes) { mr->mr_ticks.rt_userbar = mr->mr_ticks.rt_wholeticks; /* LATER ntsc */ mr->mr_ticks.rt_tickscoef = mr->mr_ticks.rt_deftempo / (mr->mr_nframes * mr->mr_ticks.rt_beatticks); mr->mr_ticks.rt_hardbar = mr->mr_ticks.rt_userbar / mr->mr_ticks.rt_tickscoef; mr->mr_ticks.rt_tempo = mr->mr_ticks.rt_deftempo; } else { mr->mr_ticks.rt_userbar = (mr->mr_ticks.rt_wholeticks * mr->mr_meternum) / mr->mr_meterden; mr->mr_ticks.rt_hardbar = (mr->mr_ticks.rt_beatticks * 4. * mr->mr_meternum) / mr->mr_meterden; mr->mr_ticks.rt_tickscoef = mr->mr_ticks.rt_wholeticks / (mr->mr_ticks.rt_beatticks * 4.); mr->mr_ticks.rt_tempo = ((double)MIFIHARD_DEFTEMPO * mr->mr_ticks.rt_deftempo) / ((double)mr->mr_tempo); if (mr->mr_ticks.rt_tempo < MIFI_TICKEPSILON) { loudbug_bug("mifiread_updateticks"); mr->mr_ticks.rt_tempo = mr->mr_ticks.rt_deftempo; } } mr->mr_ticks.rt_mscoef = 1000. / mr->mr_ticks.rt_tempo; } static void mifiread_resetticks(t_mifiread *mr) { mr->mr_ticks.rt_wholeticks = MIFIUSER_DEFWHOLETICKS; mr->mr_ticks.rt_deftempo = MIFIUSER_DEFTEMPO; mr->mr_ticks.rt_beatticks = MIFIHARD_DEFBEATTICKS; } static void mifiread_reset(t_mifiread *mr) { mr->mr_eof = 0; mr->mr_newtrack = 0; mr->mr_fp = 0; mr->mr_format = 0; mr->mr_nframes = 0; mr->mr_tempo = MIFIHARD_DEFTEMPO; mr->mr_meternum = 4; mr->mr_meterden = 4; mr->mr_ntracks = 0; mr->mr_status = 0; mr->mr_channel = 0; mr->mr_bytesleft = 0; mr->mr_pass = 0; mr->mr_hdtracks = 1; mr->mr_tracknames = 0; mifiread_updateticks(mr); } /* Calling this is optional. The obligatory part is supplied elsewhere: in the constructor (owner), and in the doit() call (hook function). */ void mifiread_setuserticks(t_mifiread *mr, double wholeticks) { mr->mr_ticks.rt_wholeticks = (wholeticks > MIFI_TICKEPSILON ? wholeticks : MIFIUSER_DEFWHOLETICKS); mr->mr_ticks.rt_deftempo = mr->mr_ticks.rt_wholeticks * (MIFIUSER_DEFTEMPO / MIFIUSER_DEFWHOLETICKS); mifiread_updateticks(mr); } /* open a file and read its header */ static int mifiread_startfile(t_mifiread *mr, const char *filename, const char *dirname, int complain) { char errmess[MAXPDSTRING], path[MAXPDSTRING], *fnameptr; int fd; mr->mr_fp = 0; if ((fd = open_via_path(dirname, filename, "", path, &fnameptr, MAXPDSTRING, 1)) < 0) { strcpy(errmess, "cannot open"); goto rstartfailed; } close(fd); if (path != fnameptr) { char *slashpos = path + strlen(path); *slashpos++ = '/'; /* try not to be dependent on current open_via_path() implementation */ if (fnameptr != slashpos) strcpy(slashpos, fnameptr); } sys_bashfilename(path, path); if (!(mr->mr_fp = fopen(path, "rb"))) { strcpy(errmess, "cannot open"); goto rstartfailed; } if (fread(&mr->mr_header, 1, MIFIHARD_HEADERSIZE, mr->mr_fp) < MIFIHARD_HEADERSIZE) { strcpy(errmess, "missing header of"); goto rstartfailed; } return (1); rstartfailed: if (complain) mifi_error(mr->mr_owner, "%s file \"%s\" (errno %d: %s)", errmess, filename, errno, strerror(errno)); if (mr->mr_fp) { fclose(mr->mr_fp); mr->mr_fp = 0; } return (0); } static int mifiread_starttrack(t_mifiread *mr) { t_mifitrackheader th; long skip; int notyet = 1; do { if (fread(&th, 1, MIFIHARD_TRACKHEADERSIZE, mr->mr_fp) < MIFIHARD_TRACKHEADERSIZE) goto nomoretracks; th.th_length = mifi_swap4(th.th_length); if (strncmp(th.th_type, "MTrk", 4)) { char buf[8]; strncpy(buf, th.th_type, 4); buf[4] = 0; if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "unknown chunk %s in midi file... skipped", buf); } else if (th.th_length < MIFI_SHORTESTEVENT) { if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "empty track in midi file... skipped"); } else notyet = 0; if (notyet && (skip = th.th_length) && fseek(mr->mr_fp, skip, SEEK_CUR) < 0) goto nomoretracks; } while (notyet); mr->mr_scoretime = 0; mr->mr_newtrack = 1; mr->mr_status = mr->mr_channel = 0; mr->mr_bytesleft = th.th_length; return (1); nomoretracks: if (mr->mr_ntracks == 0 && mr->mr_pass == 1) mifi_warning(mr->mr_owner, "no valid miditracks"); return (0); } static int mifiread_nextevent(t_mifiread *mr) { t_mifievent *ep = &mr->mr_event; uchar status, channel; uint32 length; mr->mr_newtrack = 0; nextattempt: if (mr->mr_bytesleft < MIFI_SHORTESTEVENT && !mifiread_starttrack(mr)) return (MIFIREAD_EOF); mr->mr_scoretime += (mr->mr_event.e_delay = mifiread_getvarlen(mr)); if ((status = mifiread_getbyte(mr)) < 0x80) { if (MIFI_ISCHANNEL(mr->mr_status)) { ep->e_data[0] = status; ep->e_length = 1; status = mr->mr_status; ep->e_channel = mr->mr_channel; } else { if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "missing running status in midi file... skip to end of track"); goto endoftrack; } } else ep->e_length = 0; /* channel message */ if (status < 0xf0) { if (ep->e_length == 0) { ep->e_data[0] = mifiread_getbyte(mr); ep->e_length = 1; mr->mr_status = status & 0xf0; mr->mr_channel = ep->e_channel = status & 0x0f; status = mr->mr_status; } if (!MIFI_ONEDATABYTE(status)) { ep->e_data[1] = mifiread_getbyte(mr); ep->e_length = 2; } } /* system exclusive */ else if (status == MIFISYSEX_FIRST || status == MIFISYSEX_NEXT) { length = mifiread_getvarlen(mr); if (length > MIFIEVENT_MAXSYSEX) /* FIXME optional read */ { if (mifiread_skipbytes(mr, length) < 0) return (MIFIREAD_FATAL); } else { uchar *tempbuf = getbytes(length); if (mifiread_getbytes(mr, tempbuf, length) != length) return (MIFIREAD_FATAL); #ifdef MIFI_DEBUG mifi_printsysex(length, tempbuf); #endif freebytes(tempbuf, length); } goto nextattempt; } /* meta-event */ else if (status == MIFIEVENT_META) { ep->e_meta = mifiread_getbyte(mr); length = mifiread_getvarlen(mr); if (ep->e_meta > 127) { /* try to skip corrupted meta-event (quietly) */ #ifdef MIFI_VERBOSE if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "bad meta: %d > 127", ep->e_meta); #endif if (mifiread_skipbytes(mr, length) < 0) return (MIFIREAD_FATAL); goto nextattempt; } switch (ep->e_meta) { case MIFIMETA_EOT: if (length) { /* corrupted eot: ignore and skip to the real end of track */ #ifdef MIFI_VERBOSE if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "corrupted eot, length %d", length); #endif goto endoftrack; } break; case MIFIMETA_TEMPO: if (length != 3) { if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "corrupted tempo event in midi file... skip to end of track"); goto endoftrack; } if (mifiread_getbytes(mr, ep->e_data + 1, 3) != 3) return (MIFIREAD_FATAL); ep->e_data[0] = 0; mr->mr_tempo = mifi_swap4(*(uint32 *)ep->e_data); if (!mr->mr_tempo) mr->mr_tempo = MIFIHARD_DEFTEMPO; mifiread_updateticks(mr); break; case MIFIMETA_TIMESIG: if (length != 4) { if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "corrupted time signature event in midi file... skip to end of track"); goto endoftrack; } if (mifiread_getbytes(mr, ep->e_data, 4) != 4) return (MIFIREAD_FATAL); mr->mr_meternum = ep->e_data[0]; mr->mr_meterden = (1 << ep->e_data[1]); if (!mr->mr_meternum || !mr->mr_meterden) mr->mr_meternum = mr->mr_meterden = 4; mifiread_updateticks(mr); #ifdef MIFI_DEBUG if (mr->mr_pass == 1) loudbug_post("barspan (hard) %g", mr->mr_ticks.rt_hardbar); #endif break; default: if (length + 1 > MIFIEVENT_NALLOC) { if (mifiread_skipbytes(mr, length) < 0) return (MIFIREAD_FATAL); goto nextattempt; } if (mifiread_getbytes(mr, ep->e_data, length) != length) return (MIFIREAD_FATAL); ep->e_length = length; if (ep->e_meta && ep->e_meta <= MIFIMETA_MAXPRINTABLE) ep->e_data[length] = '\0'; /* text meta-event nultermination */ } } else { if (mr->mr_pass == 1) mifi_warning(mr->mr_owner, "unknown event type in midi file... skip to end of track"); goto endoftrack; } return ((ep->e_status = status) == MIFIEVENT_META ? ep->e_meta : status); endoftrack: if (mifiread_skipbytes(mr, mr->mr_bytesleft) < 0) return (MIFIREAD_FATAL); else return (MIFIREAD_SKIP); } static int mifiread_restart(t_mifiread *mr, int complain) { mr->mr_eof = 0; mr->mr_newtrack = 0; mr->mr_status = 0; mr->mr_channel = 0; mr->mr_bytesleft = 0; mr->mr_pass = 0; if (fseek(mr->mr_fp, 0, SEEK_SET)) { if (complain) mifi_error(mr->mr_owner, "file error (errno %d: %s)", errno, strerror(errno)); return (0); } else return (1); } static int mifiread_doopen(t_mifiread *mr, const char *filename, const char *dirname, int complain) { long skip; mifiread_reset(mr); if (!mifiread_startfile(mr, filename, dirname, complain)) return (0); if (strncmp(mr->mr_header.h_type, "MThd", 4)) goto badheader; mr->mr_header.h_length = mifi_swap4(mr->mr_header.h_length); if (mr->mr_header.h_length < MIFIHARD_HEADERDATASIZE) goto badheader; if (skip = mr->mr_header.h_length - MIFIHARD_HEADERDATASIZE) { mifi_warning(mr->mr_owner, "%ld extra bytes of midi file header... skipped", skip); if (fseek(mr->mr_fp, skip, SEEK_CUR) < 0) goto badstart; } mr->mr_format = mifi_swap2(mr->mr_header.h_format); mr->mr_hdtracks = mifi_swap2(mr->mr_header.h_ntracks); if (mr->mr_hdtracks > 1000) /* a sanity check */ mifi_warning(mr->mr_owner, "%d tracks declared in midi file \"%s\"", mr->mr_hdtracks, filename); mr->mr_tracknames = getbytes(mr->mr_hdtracks * sizeof(*mr->mr_tracknames)); mr->mr_ticks.rt_beatticks = mifi_swap2(mr->mr_header.h_division); if (mr->mr_ticks.rt_beatticks & 0x8000) { mr->mr_nframes = (mr->mr_ticks.rt_beatticks >> 8); mr->mr_ticks.rt_beatticks &= 0xff; } else mr->mr_nframes = 0; if (mr->mr_ticks.rt_beatticks == 0) goto badheader; mifiread_updateticks(mr); #ifdef MIFI_DEBUG if (mr->mr_nframes) loudbug_post( "midi file (format %d): %d tracks, %d ticks (%d smpte frames)", mr->mr_format, mr->mr_hdtracks, mr->mr_ticks.rt_beatticks, mr->mr_nframes); else loudbug_post("midi file (format %d): %d tracks, %d ticks per beat", mr->mr_format, mr->mr_hdtracks, mr->mr_ticks.rt_beatticks); #endif return (1); badheader: if (complain) mifi_error(mr->mr_owner, "\"%s\" is not a valid midi file", filename); badstart: fclose(mr->mr_fp); mr->mr_fp = 0; return (0); } /* Gather statistics (nevents, ntracks, ntempi), pick track names, and allocate the maps. To be called in the first pass of reading. LATER consider optional reading of nonchannel events. */ /* FIXME complaining */ static int mifiread_analyse(t_mifiread *mr, int complain) { t_mifievent *ep = &mr->mr_event; int i, evtype, isnewtrack = 0; char tnamebuf[MAXPDSTRING]; t_symbol **tnamep = 0; mr->mr_pass = 1; *tnamebuf = '\0'; mr->mr_ntracks = 0; mr->mr_nevents = 0; mr->mr_ntempi = 0; while ((evtype = mifiread_nextevent(mr)) >= MIFIREAD_SKIP) { if (evtype == MIFIREAD_SKIP) continue; if (mr->mr_newtrack) { #ifdef MIFI_DEBUG loudbug_post("track %d", mr->mr_ntracks); #endif isnewtrack = 1; *tnamebuf = '\0'; tnamep = 0; /* set to nonzero for nonempty tracks only */ } if (MIFI_ISCHANNEL(evtype)) { if (isnewtrack) { isnewtrack = 0; tnamep = mr->mr_tracknames + mr->mr_ntracks; mr->mr_ntracks++; if (mr->mr_ntracks > mr->mr_hdtracks) { if (complain) mifi_error(mr->mr_owner, "midi file has more tracks than header-declared %d", mr->mr_hdtracks); /* FIXME grow? */ goto anafail; } if (*tnamebuf) { *tnamep = gensym(tnamebuf); #ifdef MIFI_DEBUG loudbug_post("nonempty track name %s", (*tnamep)->s_name); #endif } else *tnamep = &s_; } mr->mr_nevents++; } /* FIXME sysex */ else if (evtype < 0x80) { mifievent_printmeta(ep); if (evtype == MIFIMETA_TEMPO) mr->mr_ntempi++; else if (evtype == MIFIMETA_TRACKNAME) { char *p1 = ep->e_data; if (*p1 && !*tnamebuf) /* take the first one */ { while (*p1 == ' ') p1++; if (*p1) { char *p2 = ep->e_data + ep->e_length - 1; while (p2 > p1 && *p2 == ' ') *p2-- = '\0'; p2 = p1; do if (*p2 == ' ' || *p2 == ',' || *p2 == ';') *p2 = '-'; while (*++p2); if (tnamep) { if (*tnamep == &s_) /* trackname after channel-event */ *tnamep = gensym(p1); else strcpy(tnamebuf, p1); } } } } } } if (evtype == MIFIREAD_EOF) { for (i = 0, tnamep = mr->mr_tracknames; i < mr->mr_ntracks; i++, tnamep++) { if (!*tnamep || *tnamep == &s_) { sprintf(tnamebuf, "%d-track", i); *tnamep = gensym(tnamebuf); } } #ifdef MIFI_VERBOSE post("got %d midi tracks (out of %d)", mr->mr_ntracks, mr->mr_hdtracks); #endif return (MIFIREAD_EOF); } else return (evtype); anafail: return (MIFIREAD_FATAL); } /* to be called in the second pass of reading */ int mifiread_doit(t_mifiread *mr, t_mifireadhook hook, void *hookdata) { int evtype, ntracks = 0, isnewtrack = 0; mr->mr_pass = 2; mr->mr_trackndx = 0; while ((evtype = mifiread_nextevent(mr)) >= MIFIREAD_SKIP) { if (evtype == MIFIREAD_SKIP) continue; if (mr->mr_newtrack) isnewtrack = 1; if (isnewtrack && MIFI_ISCHANNEL(evtype)) { isnewtrack = 0; mr->mr_trackndx = ntracks++; if (ntracks > mr->mr_ntracks) { loudbug_bug("mifiread_doit: too many tracks"); goto doitfail; } if (!mr->mr_tracknames[mr->mr_trackndx] || mr->mr_tracknames[mr->mr_trackndx] == &s_) { loudbug_bug("mifiread_doit: empty track name"); mr->mr_tracknames[mr->mr_trackndx] = gensym("bug-track"); } } if (!hook(mr, hookdata, evtype)) goto doitfail; } if (evtype == MIFIREAD_EOF) { #ifdef MIFI_DEBUG if (evtype == MIFIREAD_EOF) loudbug_post("finished reading %d events from midi file", mr->mr_nevents); #endif return (MIFIREAD_EOF); } doitfail: return (MIFIREAD_FATAL); } /* mifiread_get... calls to be used in the main read routine */ int mifiread_getnevents(t_mifiread *mr) { return (mr->mr_nevents); } int mifiread_getntempi(t_mifiread *mr) { return (mr->mr_ntempi); } int mifiread_gethdtracks(t_mifiread *mr) { return (mr->mr_hdtracks); } int mifiread_getformat(t_mifiread *mr) { return (mr->mr_format); } int mifiread_getnframes(t_mifiread *mr) { return (mr->mr_nframes); } int mifiread_getbeatticks(t_mifiread *mr) { return (mr->mr_ticks.rt_beatticks); } double mifiread_getdeftempo(t_mifiread *mr) { return (mr->mr_ticks.rt_deftempo); } /* mifiread_get... calls to be used in a mifireadhook */ int mifiread_getbarindex(t_mifiread *mr) { return (mr->mr_scoretime / (int)mr->mr_ticks.rt_hardbar); } double mifiread_getbarspan(t_mifiread *mr) { return (mr->mr_ticks.rt_userbar); } double mifiread_gettick(t_mifiread *mr) { return (mr->mr_ticks.rt_tickscoef * (mr->mr_scoretime % (int)mr->mr_ticks.rt_hardbar)); } double mifiread_getscoretime(t_mifiread *mr) { return (mr->mr_ticks.rt_tickscoef * mr->mr_scoretime); } double mifiread_gettempo(t_mifiread *mr) { return (mr->mr_ticks.rt_tempo); } double mifiread_getmscoef(t_mifiread *mr) { return (mr->mr_ticks.rt_mscoef); } t_symbol *mifiread_gettrackname(t_mifiread *mr) { if (mr->mr_pass == 2 && mr->mr_tracknames && mr->mr_trackndx < mr->mr_ntracks) return (mr->mr_tracknames[mr->mr_trackndx]); else { loudbug_bug("mifiread_gettrackname"); return (0); } } unsigned mifiread_getstatus(t_mifiread *mr) { if (mr->mr_pass != 2) loudbug_bug("mifiread_getstatus"); return (mr->mr_event.e_status); } unsigned mifiread_getdata1(t_mifiread *mr) { if (mr->mr_pass != 2) loudbug_bug("mifiread_getdata1"); return (mr->mr_event.e_data[0]); } unsigned mifiread_getdata2(t_mifiread *mr) { if (mr->mr_pass != 2) loudbug_bug("mifiread_getdata2"); if (mr->mr_event.e_length < 2) loudbug_bug("mifiread_getdata2"); return (mr->mr_event.e_data[1]); } unsigned mifiread_getchannel(t_mifiread *mr) { if (mr->mr_pass != 2) loudbug_bug("mifiread_getchannel"); return (mr->mr_event.e_channel); } t_pd *mifiread_getowner(t_mifiread *mr) { return (mr->mr_owner); } int mifiread_open(t_mifiread *mr, const char *filename, const char *dirname, int complain) { return (mifiread_doopen(mr, filename, dirname, complain) && (mifiread_analyse(mr, complain) == MIFIREAD_EOF) && mifiread_restart(mr, complain)); } void mifiread_close(t_mifiread *mr) { mr->mr_pass = 0; if (mr->mr_fp) { fclose(mr->mr_fp); mr->mr_fp = 0; } if (mr->mr_tracknames) freebytes(mr->mr_tracknames, mr->mr_hdtracks * sizeof(*mr->mr_tracknames)); } void mifiread_free(t_mifiread *mr) { mifiread_close(mr); if (mr->mr_event.e_data != mr->mr_event.e_dataini) freebytes(mr->mr_event.e_data, mr->mr_event.e_datasize); freebytes(mr, sizeof(*mr)); } t_mifiread *mifiread_new(t_pd *owner) { t_mifiread *mr = getbytes(sizeof(*mr)); mifi_initialize(); mr->mr_owner = owner; mifievent_initialize(&mr->mr_event, MIFIEVENT_NALLOC); mifiread_resetticks(mr); mifiread_reset(mr); return (mr); } static void mifiwrite_updateticks(t_mifiwrite *mw) { if (mw->mw_nframes) { /* LATER ntsc */ mw->mw_ticks.wt_tickscoef = (mw->mw_nframes * mw->mw_ticks.wt_beatticks) / mw->mw_ticks.wt_deftempo; mw->mw_ticks.wt_tempo = mw->mw_ticks.wt_deftempo; mw->mw_ticks.wt_mscoef = .001 * (mw->mw_nframes * mw->mw_ticks.wt_beatticks); } else { mw->mw_ticks.wt_tickscoef = (mw->mw_ticks.wt_beatticks * 4.) / mw->mw_ticks.wt_wholeticks; mw->mw_ticks.wt_tempo = ((double)MIFIHARD_DEFTEMPO * mw->mw_ticks.wt_deftempo) / ((double)mw->mw_tempo); if (mw->mw_ticks.wt_tempo < MIFI_TICKEPSILON) { loudbug_bug("mifiwrite_updateticks"); mw->mw_ticks.wt_tempo = mw->mw_ticks.wt_deftempo; } mw->mw_ticks.wt_mscoef = (1000. * mw->mw_ticks.wt_beatticks) / mw->mw_tempo; } } static void mifiwrite_resetticks(t_mifiwrite *mw) { mw->mw_ticks.wt_wholeticks = MIFIUSER_DEFWHOLETICKS; mw->mw_ticks.wt_deftempo = MIFIUSER_DEFTEMPO; mw->mw_ticks.wt_beatticks = MIFIHARD_DEFBEATTICKS; } static void mifiwrite_reset(t_mifiwrite *mw) { mw->mw_trackndx = 0; mw->mw_trackdirty = 0; mw->mw_fp = 0; mw->mw_format = 1; /* LATER settable parameter */ mw->mw_nframes = 0; mw->mw_meternum = 4; mw->mw_meterden = 4; mw->mw_status = 0; mw->mw_channel = 0; mw->mw_trackbytes = 0; mifiwrite_updateticks(mw); } void mifiwrite_sethardticks(t_mifiwrite *mw, int beatticks) { mw->mw_ticks.wt_beatticks = (beatticks > 0 && beatticks < MIFI_MAXBEATTICKS ? beatticks : MIFIHARD_DEFBEATTICKS); mifiwrite_updateticks(mw); } void mifiwrite_setuserticks(t_mifiwrite *mw, double wholeticks) { mw->mw_ticks.wt_wholeticks = (wholeticks > MIFI_TICKEPSILON ? wholeticks : MIFIUSER_DEFWHOLETICKS); mw->mw_ticks.wt_deftempo = mw->mw_ticks.wt_wholeticks * (MIFIUSER_DEFTEMPO / MIFIUSER_DEFWHOLETICKS); mifiwrite_updateticks(mw); } void mifiwrite_setusertempo(t_mifiwrite *mw, double tickspersec) { mw->mw_tempo = (tickspersec > MIFI_TICKEPSILON ? ((double)MIFIHARD_DEFTEMPO * mw->mw_ticks.wt_deftempo) / tickspersec : MIFIHARD_DEFTEMPO); mifiwrite_updateticks(mw); } /* LATER analyse shrinking effect caused by truncation */ static int mifiwrite_putnextevent(t_mifiwrite *mw, t_mifievent *ep) { uchar buf[3], *ptr = buf; size_t size = mifiwrite_putvarlen(mw, ep->e_delay); if (!size) return (0); mw->mw_trackbytes += size; if (MIFI_ISCHANNEL(ep->e_status)) { if ((*ptr = ep->e_status | ep->e_channel) == mw->mw_status) size = 1; else { mw->mw_status = *ptr++; size = 2; } *ptr++ = ep->e_data[0]; if (!MIFI_ONEDATABYTE(ep->e_status)) { *ptr = ep->e_data[1]; size++; } ptr = buf; } else if (ep->e_status == MIFIEVENT_META) { mw->mw_status = 0; /* sysex and meta cancel any running status */ buf[0] = ep->e_status; buf[1] = ep->e_meta; if (fwrite(buf, 1, 2, mw->mw_fp) != 2) return (0); mw->mw_trackbytes += 2; size = mifiwrite_putvarlen(mw, ep->e_length); if (!size) return (0); mw->mw_trackbytes += size; size = ep->e_length; ptr = ep->e_data; } else return (0); if (size) { if (fwrite(ptr, 1, size, mw->mw_fp) != size) return (0); mw->mw_trackbytes += size; } return (1); } /* open a midi file for saving, write the header */ int mifiwrite_open(t_mifiwrite *mw, const char *filename, const char *dirname, int ntracks, int complain) { char errmess[MAXPDSTRING], fnamebuf[MAXPDSTRING]; if (ntracks < 1 || ntracks > MIFI_MAXTRACKS) { loudbug_bug("mifiwrite_open 1"); complain = 0; goto wopenfailed; } mw->mw_ntracks = ntracks; mifiwrite_reset(mw); if (mw->mw_format == 0) { if (mw->mw_ntracks != 1) { /* LATER consider replacing with a warning */ loudbug_bug("mifiwrite_open 2"); complain = 0; goto wopenfailed; } #ifdef MIFI_VERBOSE post("writing single-track midi file \"%s\"", filename); #endif } #ifdef MIFI_VERBOSE else post("writing midi file \"%s\" (%d tracks)", filename, mw->mw_ntracks); #endif strncpy(mw->mw_header.h_type, "MThd", 4); mw->mw_header.h_length = mifi_swap4(MIFIHARD_HEADERDATASIZE); mw->mw_header.h_format = mifi_swap2(mw->mw_format); mw->mw_header.h_ntracks = mifi_swap2(mw->mw_ntracks); if (mw->mw_nframes) mw->mw_header.h_division = ((mw->mw_nframes << 8) | mw->mw_ticks.wt_beatticks) | 0x8000; else mw->mw_header.h_division = mw->mw_ticks.wt_beatticks & 0x7fff; mw->mw_header.h_division = mifi_swap2(mw->mw_header.h_division); fnamebuf[0] = 0; if (*dirname) strcat(fnamebuf, dirname), strcat(fnamebuf, "/"); strcat(fnamebuf, filename); sys_bashfilename(fnamebuf, fnamebuf); if (!(mw->mw_fp = fopen(fnamebuf, "wb"))) { strcpy(errmess, "cannot open"); goto wopenfailed; } if (fwrite(&mw->mw_header, 1, MIFIHARD_HEADERSIZE, mw->mw_fp) < MIFIHARD_HEADERSIZE) { strcpy(errmess, "cannot write header of"); goto wopenfailed; } return (1); wopenfailed: if (complain) mifi_error(mw->mw_owner, "%s file \"%s\" (errno %d: %s)", errmess, filename, errno, strerror(errno)); if (mw->mw_fp) { fclose(mw->mw_fp); mw->mw_fp = 0; } return (0); } /* append eot meta and update length field in a track header */ static int mifiwrite_adjusttrack(t_mifiwrite *mw, uint32 eotdelay, int complain) { t_mifievent *ep = &mw->mw_event; long skip; uint32 length; mw->mw_trackdirty = 0; ep->e_delay = eotdelay; ep->e_status = MIFIEVENT_META; ep->e_meta = MIFIMETA_EOT; ep->e_length = 0; if (!mifiwrite_putnextevent(mw, ep)) return (0); skip = mw->mw_trackbytes + 4; length = mifi_swap4(mw->mw_trackbytes); #ifdef MIFI_DEBUG loudbug_post("adjusting track size to %d", mw->mw_trackbytes); #endif /* LATER add sanity check (compare to saved filepos) */ if (skip > 4 && fseek(mw->mw_fp, -skip, SEEK_CUR) < 0 || fwrite(&length, 1, 4, mw->mw_fp) != 4 || fseek(mw->mw_fp, 0, SEEK_END) < 0) { if (complain) mifi_error(mw->mw_owner, "unable to adjust length field to %d in a midi file\ track header (errno %d: %s)", mw->mw_trackbytes, errno, strerror(errno)); return (0); } return (1); } int mifiwrite_opentrack(t_mifiwrite *mw, char *trackname, int complain) { t_mifitrackheader th; if (mw->mw_trackdirty && !mifiwrite_adjusttrack(mw, 0, complain)) return (0); if (mw->mw_trackndx > mw->mw_ntracks) return (0); else if (mw->mw_trackndx++ == mw->mw_ntracks) { loudbug_bug("mifiwrite_opentrack"); return (0); } strncpy(th.th_type, "MTrk", 4); th.th_length = 0; mw->mw_status = mw->mw_channel = 0; mw->mw_trackbytes = 0; if (fwrite(&th, 1, MIFIHARD_TRACKHEADERSIZE, mw->mw_fp) != MIFIHARD_TRACKHEADERSIZE) { if (complain) mifi_error(mw->mw_owner, "unable to write midi file header (errno %d: %s)", errno, strerror(errno)); return (0); } if (trackname) { if (!mifiwrite_textevent(mw, 0., MIFIMETA_TRACKNAME, trackname)) { if (complain) mifi_error(mw->mw_owner, "unable to write midi file track name \"%s\" (errno %d: %s)", trackname, errno, strerror(errno)); return (0); } } mw->mw_trackdirty = 1; return (1); } /* calling this is optional (if skipped, enddelay defaults to 0.) */ int mifiwrite_closetrack(t_mifiwrite *mw, double enddelay, int complain) { if (mw->mw_trackdirty) { uint32 eotdelay = (uint32)(enddelay * mw->mw_ticks.wt_mscoef); return (mifiwrite_adjusttrack(mw, eotdelay, complain)); } else { loudbug_bug("mifiwrite_closetrack"); return (0); } } int mifiwrite_textevent(t_mifiwrite *mw, double delay, unsigned type, char *text) { t_mifievent *ep = &mw->mw_event; if (!mifievent_settext(ep, type, text)) return (0); ep->e_delay = (uint32)(delay * mw->mw_ticks.wt_mscoef); return (mifiwrite_putnextevent(mw, ep)); } int mifiwrite_channelevent(t_mifiwrite *mw, double delay, unsigned status, unsigned channel, unsigned data1, unsigned data2) { t_mifievent *ep = &mw->mw_event; int shorter = MIFI_ONEDATABYTE(status); if (!MIFI_ISCHANNEL(status) || channel > 15 || data1 > 127 || (!shorter && data2 > 127)) { loudbug_bug("mifiwrite_channelevent"); return (0); } ep->e_delay = (uint32)(delay * mw->mw_ticks.wt_mscoef); ep->e_status = (uchar)(status & 0xf0); ep->e_channel = (uchar)channel; ep->e_data[0] = (uchar)data1; if (shorter) ep->e_length = 1; else { ep->e_data[1] = (uchar)data2; ep->e_length = 2; } return (mifiwrite_putnextevent(mw, ep)); } void mifiwrite_close(t_mifiwrite *mw) { if (mw->mw_trackdirty) mifiwrite_adjusttrack(mw, 0, 0); if (mw->mw_fp) { fclose(mw->mw_fp); mw->mw_fp = 0; } } void mifiwrite_free(t_mifiwrite *mw) { mifiwrite_close(mw); if (mw->mw_event.e_data != mw->mw_event.e_dataini) freebytes(mw->mw_event.e_data, mw->mw_event.e_datasize); freebytes(mw, sizeof(*mw)); } t_mifiwrite *mifiwrite_new(t_pd *owner) { t_mifiwrite *mw = getbytes(sizeof(*mw)); mifi_initialize(); mw->mw_owner = owner; mw->mw_ntracks = 0; mw->mw_tempo = MIFIHARD_DEFTEMPO; mifievent_initialize(&mw->mw_event, MIFIEVENT_NALLOC); mifiwrite_resetticks(mw); mifiwrite_reset(mw); return (mw); } cyclone-0.1-alpha55/shared/common/loud.h0000644000076500007650000000401511466617452016607 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __LOUD_H__ #define __LOUD_H__ #define LOUD_CLIP 1 #define LOUD_WARN 2 enum { LOUD_ARGOK, LOUD_ARGUNDER, LOUD_ARGOVER, LOUD_ARGTYPE, LOUD_ARGMISSING }; EXTERN_STRUCT _loudcontext; #define t_loudcontext struct _loudcontext int shared_matchignorecase(char *test, char *pattern); char *loud_ordinal(int n); void loud_error(t_pd *x, char *fmt, ...); void loud_errand(t_pd *x, char *fmt, ...); void loud_syserror(t_pd *x, char *fmt, ...); void loud_nomethod(t_pd *x, t_symbol *s); void loud_messarg(t_pd *x, t_symbol *s); int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess); void loud_classarg(t_class *c); void loud_warning(t_pd *x, char *who, char *fmt, ...); void loud_notimplemented(t_pd *x, char *name); int loud_floatarg(t_class *c, int which, int ac, t_atom *av, t_float *vp, t_float minval, t_float maxval, int underaction, int overaction, char *what); void loudx_error(t_loudcontext *lc, char *fmt, ...); void loudx_errand(t_loudcontext *lc, char *fmt, ...); void loudx_nomethod(t_loudcontext *lc, t_symbol *s); void loudx_messarg(t_loudcontext *lc, t_symbol *s); void loudx_warning(t_loudcontext *lc, char *fmt, ...); void loudx_setcontext(t_loudcontext *lc, t_pd *caller, char *callername, t_symbol *s, int ac, t_atom *av); void loudx_setcaller(t_loudcontext *lc, t_pd *caller, char *callerfmt, ...); t_symbol *loudx_getselector(t_loudcontext *lc); t_atom *loudx_getarguments(t_loudcontext *lc, int *acp); void loudx_freecontext(t_loudcontext *lc); t_loudcontext *loudx_newcontext(t_pd *caller, char *callername, t_symbol *s, int ac, t_atom *av); void loudbug_post(char *fmt, ...); void loudbug_startpost(char *fmt, ...); void loudbug_stringpost(char *s); void loudbug_endpost(void); void loudbug_postatom(int ac, t_atom *av); void loudbug_postbinbuf(t_binbuf *bb); void loudbug_bug(char *fmt, ...); #endif cyclone-0.1-alpha55/shared/common/Makefile0000644000076500007650000000010611466617452017130 0ustar hanshansROOT_DIR = ../.. include $(ROOT_DIR)/Makefile.common all: $(OBJECTS) cyclone-0.1-alpha55/shared/common/props.c0000644000076500007650000003765011466617452017015 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" #include "props.h" #ifdef KRZYSZCZ //#define PROPS_DEBUG #endif #define PROPS_INISIZE 32 /* LATER rethink */ #define PROPS_MAXMIXUPS 32 /* return values of props_iskey() */ enum { PROPS_NONE = 0, PROPS_THIS, PROPS_MIXUP }; /* 'mode' argument values of props_iskey() and props_update() */ enum { PROPS_SINGLEMODE = 0, PROPS_MULTIMODE }; typedef struct _propelem { char *e_key; char *e_value; struct _propelem *e_next; } t_propelem; struct _props { char p_thisescape; char *p_thisinitial; char *p_name; int p_size; /* as allocated */ int p_natoms; /* as used */ t_atom *p_buffer; t_atom p_bufini[PROPS_INISIZE]; int p_nextindex; t_pd *p_owner; t_propsresolver p_resolver; t_propelem *p_dict; t_propelem *p_nextelem; int p_badupdate; char p_mixupescapes[PROPS_MAXMIXUPS]; t_props *p_firstmixup; /* points to the props list's head */ t_props *p_next; }; /* Dictionary of properties, p_dict, meant to be nothing more, but an optimization detail, is handled implicitly, through its owning t_props. This optimization has to be enabled by passing a nonzero 'resolver' argument to props_new(). Since p_dict stores resolved strings, it is a secondary, `shallow' storage, which has to be synced to its master, p_buffer of atoms. Currently, p_dict is implemented as an unsorted linked list, which should be fine in most cases (but might need revisiting LATER). */ static t_propelem *propelem_new(char *key, char *value) { t_propelem *ep = (t_propelem *)getbytes(sizeof(*ep)); ep->e_key = getbytes(strlen(key) + 1); strcpy(ep->e_key, key); ep->e_value = getbytes(strlen(value) + 1); strcpy(ep->e_value, value); ep->e_next = 0; return (ep); } static void propelem_free(t_propelem *ep) { if (ep->e_key) freebytes(ep->e_key, strlen(ep->e_key) + 1); if (ep->e_value) freebytes(ep->e_value, strlen(ep->e_value) + 1); freebytes(ep, sizeof(*ep)); } /* Returns zero if the key was found (and value replaced), nonzero if a new element was added. */ static t_propelem *propelem_add(t_propelem *ep, char *key, char *value) { while (ep) { if (strcmp(ep->e_key, key)) ep = ep->e_next; else break; } if (ep) { if (strcmp(ep->e_value, value)) { if (ep->e_value) ep->e_value = resizebytes(ep->e_value, strlen(ep->e_value) + 1, strlen(value) + 1); else ep->e_value = getbytes(strlen(value) + 1); strcpy(ep->e_value, value); } return (0); } else return (propelem_new(key, value)); } static void props_dictadd(t_props *pp, t_symbol *s, int ac, t_atom *av) { if (s && *s->s_name && s->s_name[1] && ac) { t_propelem *ep; char *value = pp->p_resolver(pp->p_owner, ac, av); if (value && (ep = propelem_add(pp->p_dict, s->s_name + 1, value))) { ep->e_next = pp->p_dict; pp->p_dict = ep; } } } /* API calls for lookup (getvalue) and traversal (firstvalue, nextvalue), and non-api calls (removevalue) of resolved properties. Only dictionary-enabled properties handle these calls. Plain 'key', without escape, is expected. Traversal is not thread-safe (will we need threaded props, LATER?) */ char *props_getvalue(t_props *pp, char *key) { if (pp->p_resolver) { t_propelem *ep = pp->p_dict; while (ep) { if (strcmp(ep->e_key, key)) ep = ep->e_next; else return (ep->e_value); } } return (0); } char *props_nextvalue(t_props *pp, char **keyp) { if (pp->p_nextelem) { char *value = pp->p_nextelem->e_value; *keyp = pp->p_nextelem->e_key; pp->p_nextelem = pp->p_nextelem->e_next; return (value); } return (0); } char *props_firstvalue(t_props *pp, char **keyp) { if (pp->p_nextelem) loudbug_bug("props_firstvalue"); if (pp->p_resolver) pp->p_nextelem = pp->p_dict; return (props_nextvalue(pp, keyp)); } static void props_removevalue(t_props *pp, char *key) { if (pp->p_resolver && *key) { t_propelem *ep = pp->p_dict, *epp = 0; while (ep) { if (strcmp(ep->e_key, key)) { epp = ep; ep = ep->e_next; } else { if (epp) epp->e_next = ep->e_next; else pp->p_dict = ep->e_next; propelem_free(ep); break; } } } } void props_clearvalues(t_props *pp) { while (pp->p_dict) { t_propelem *ep = pp->p_dict->e_next; propelem_free(pp->p_dict); pp->p_dict = ep; } } /* LATER think about 'deep' cloning, i.e. propagating source atoms into the destination buffer. Since cloning, unless requested by the user, should never be persistent (source atoms should not stick to the destination object in a .pd file), deep cloning requires introducing a two-buffer scheme. There is no reason for deep cloning of arguments, or handlers, but options could benefit. */ void props_clonevalues(t_props *to, t_props *from) { if (to->p_resolver) { int ac; t_atom *ap = props_getfirst(from, &ac); while (ap) { props_dictadd(to, ap->a_w.w_symbol, ac - 1, ap + 1); ap = props_getnext(from, &ac); } } } static char *props_mixupinitial(t_props *pp, char c) { t_props *pp1 = pp->p_firstmixup; while (pp1) { if (pp1 != pp && pp1->p_thisescape == c) return (pp1->p_thisinitial); pp1 = pp1->p_next; } loudbug_bug("props_mixupinitial"); loudbug_post("(%c \"%s\")", c, pp->p_mixupescapes); return (0); } /* If buf is pp's key, returns PROPS_THIS; otherwise, if PROPS_MULTIMODE was passed and buf is a key of one of pp's mixups, returns PROPS_MIXUP; otherwise, returns PROPS_NONE. */ static int props_iskey(t_props *pp, int mode, char *buf) { char *mixupinitial; if (*buf == pp->p_thisescape) { char c = buf[1]; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (pp->p_thisinitial && strchr(pp->p_thisinitial, c))) return (PROPS_THIS); } else if (mode == PROPS_MULTIMODE && *pp->p_mixupescapes && strchr(pp->p_mixupescapes, *buf)) { char c = buf[1]; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || ((mixupinitial = props_mixupinitial(pp, *buf)) && *mixupinitial && strchr(mixupinitial, c))) return (PROPS_MIXUP); } return (PROPS_NONE); } /* Lookup (getone) and traversal (getfirst, getnext) of unresolved properties. These calls return a pointer to the key atom (the contents follows it), unlike the get/first/nextvalue calls, which return the (resolved) value. Traversal is not thread-safe (will we need threaded props, LATER?) */ t_atom *props_getone(t_props *pp, t_symbol *keysym, int *npp) { if (keysym && props_iskey(pp, PROPS_SINGLEMODE, keysym->s_name) != PROPS_NONE) { int ibeg, iend = 0; t_atom *ap; for (ibeg = 0, ap = pp->p_buffer; ibeg < pp->p_natoms; ibeg++, ap++) { if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == keysym) { for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; break; } } if (iend > ibeg) { *npp = iend - ibeg; return (pp->p_buffer + ibeg); } } *npp = 0; return (0); } t_atom *props_getnext(t_props *pp, int *npp) { if (pp->p_nextindex >= 0) { int ibeg = pp->p_nextindex; t_atom *ap; for (ap = pp->p_buffer + ibeg; ibeg < pp->p_natoms; ibeg++, ap++) if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; if (ibeg < pp->p_natoms) { int iend; for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; if (iend < pp->p_natoms) pp->p_nextindex = iend; else pp->p_nextindex = -1; *npp = iend - ibeg; return (pp->p_buffer + ibeg); } else pp->p_nextindex = -1; } *npp = 0; return (0); } t_atom *props_getfirst(t_props *pp, int *npp) { if (pp->p_nextindex >= 0) loudbug_bug("props_getfirst"); pp->p_nextindex = 0; return (props_getnext(pp, npp)); } t_atom *props_getall(t_props *pp, int *npp) { *npp = pp->p_natoms; return (pp->p_buffer); } char *props_getname(t_props *pp) { return (pp ? pp->p_name : "property"); } /* Search for a property, replace its value if found, otherwise add. If 'filter' contains an exact copy, do nothing. Assuming 'keysym' is valid. Returning nafter - nbefore. */ static int props_update(t_props *pp, int mode, t_props *filter, t_symbol *keysym, int ac, t_atom *av, int doit) { int nadd, ndiff, ibeg, iend = 0; t_atom *ap; for (nadd = 0, ap = av; nadd < ac; nadd++, ap++) if (ap->a_type == A_SYMBOL && props_iskey(pp, mode, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; if (!nadd) { pp->p_badupdate = 1; return (0); } pp->p_badupdate = 0; nadd++; if (filter) { int acf; t_atom *apf = props_getone(filter, keysym, &acf); if (acf == nadd) { int i; #ifdef PROPS_DEBUG loudbug_startpost("checking %s", keysym->s_name); loudbug_postatom(nadd - 1, av); #endif for (i = 1, ap = av, apf++; i < nadd; i++, ap++, apf++) if (ap->a_type != apf->a_type || ap->a_w.w_symbol != apf->a_w.w_symbol) break; if (i == nadd) #ifndef PROPS_DEBUG return (0); #else { loudbug_post(" ... filtered"); return (0); } else loudbug_post(" ... updated"); #endif } } for (ibeg = 0, ap = pp->p_buffer; ibeg < pp->p_natoms; ibeg++, ap++) { if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == keysym) { for (iend = ibeg + 1, ap++; iend < pp->p_natoms; iend++, ap++) if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) break; break; } } ndiff = (iend > ibeg ? nadd - (iend - ibeg) : nadd); if (doit) { int i, newnatoms = pp->p_natoms + ndiff; if (newnatoms > pp->p_size) { loudbug_bug("props_update"); return (0); } #ifdef PROPS_DEBUG loudbug_post("%s %s, [%d..%d), ndiff %d", (iend > ibeg ? "replacing" : "adding"), keysym->s_name, ibeg, iend, ndiff); #endif if (iend > ibeg) { if (ndiff > 0) { t_atom *ap2 = pp->p_buffer + newnatoms; t_atom *ap1 = ap2 - ndiff; for (i = iend; i < pp->p_natoms; i++) *--ap2 = *--ap1; } else if (ndiff < 0) { t_atom *ap2 = pp->p_buffer + iend; t_atom *ap1 = ap2 + ndiff; for (i = iend; i < pp->p_natoms; i++) *ap1++ = *ap2++; } ap = pp->p_buffer + ibeg; } else { ap = pp->p_buffer + pp->p_natoms; SETSYMBOL(ap, keysym); } ap++; nadd--; if (pp->p_resolver) props_dictadd(pp, keysym, nadd, av); for (i = 0; i < nadd; i++) *ap++ = *av++; pp->p_natoms = newnatoms; } return (ndiff); } /* Carve out all properties of a given kind from a message. If in a single mode, ignore `mixup' properties -- their keys are parsed through as values. If there is an empty property, which is not to be ignored, do not parse beyond. Return an offending key symbol, if any. */ t_symbol *props_add(t_props *pp, int single, t_props *filter, t_symbol *s, int ac, t_atom *av) { t_symbol *empty = 0; t_atom *av1, *ap; int mode = (single ? PROPS_SINGLEMODE : PROPS_MULTIMODE); int ac1, i, ngrown = 0; if (!s || props_iskey(pp, PROPS_SINGLEMODE, s->s_name) == PROPS_NONE) { s = 0; while (ac) { s = (av->a_type == A_SYMBOL ? av->a_w.w_symbol : 0); ac--; av++; if (s && props_iskey(pp, PROPS_SINGLEMODE, s->s_name) != PROPS_NONE) break; s = 0; } } if (!s || !ac) { empty = s; goto done; } ngrown += props_update(pp, mode, filter, s, ac, av, 0); if (pp->p_badupdate) empty = s; else for (i = 0, ap = av; i < ac; i++, ap++) { if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) { ngrown += props_update(pp, mode, filter, ap->a_w.w_symbol, ac - i - 1, ap + 1, 0); if (pp->p_badupdate) { empty = ap->a_w.w_symbol; break; } } } ngrown += pp->p_natoms; if (ngrown > pp->p_size) { int nrequested = ngrown; pp->p_buffer = grow_withdata(&nrequested, &pp->p_natoms, &pp->p_size, pp->p_buffer, PROPS_INISIZE, pp->p_bufini, sizeof(*pp->p_buffer)); if (nrequested != ngrown) goto done; } props_update(pp, mode, filter, s, ac, av, 1); if (pp->p_badupdate) empty = s; else for (i = 0, ap = av; i < ac; i++, ap++) { if (ap->a_type == A_SYMBOL && props_iskey(pp, PROPS_SINGLEMODE, ap->a_w.w_symbol->s_name) != PROPS_NONE) { props_update(pp, mode, filter, ap->a_w.w_symbol, ac - i - 1, ap + 1, 1); if (pp->p_badupdate) { empty = ap->a_w.w_symbol; break; } } } done: return (empty); } int props_remove(t_props *pp, t_symbol *keysym) { int ac; t_atom *av = props_getone(pp, keysym, &ac); if (keysym && *keysym->s_name) props_removevalue(pp, keysym->s_name + 1); if (av) { int i; t_atom *ap = av + ac; t_atom *guard = pp->p_buffer + pp->p_natoms; while (ap < guard) *av++ = *ap++; pp->p_natoms -= ac; return (1); } else return (0); } static void props_clearone(t_props *pp) { pp->p_natoms = 0; props_clearvalues(pp); } void props_clearall(t_props *pp) { if (pp && (pp = pp->p_firstmixup)) { while (pp) { props_clearone(pp); pp = pp->p_next; } } else loudbug_bug("props_clearall"); } /* Compute pp0 = pp1 - pp2, using key-only equivalence. */ void props_diff(t_props *pp0, t_props *pp1, t_props *pp2) { int ac1; t_atom *ap1 = props_getfirst(pp1, &ac1); props_clearone(pp0); while (ap1) { int ac2; if (!props_getone(pp2, ap1->a_w.w_symbol, &ac2)) props_add(pp0, 0, 0, 0, ac1, ap1); ap1 = props_getnext(pp1, &ac1); } } static void props_freeone(t_props *pp) { if (pp->p_buffer != pp->p_bufini) freebytes(pp->p_buffer, pp->p_size * sizeof(*pp->p_buffer)); props_clearvalues(pp); freebytes(pp, sizeof(*pp)); } void props_freeall(t_props *pp) { if (pp && (pp = pp->p_firstmixup)) { while (pp) { t_props *pp1 = pp->p_next; props_freeone(pp); pp = pp1; } } else loudbug_bug("props_freeall"); } static void props_setupmixups(t_props *pp, t_props *mixup) { t_props *pp1; pp->p_next = (mixup ? mixup->p_firstmixup : 0); for (pp1 = pp; pp1; pp1 = pp1->p_next) { t_props *pp2; char *bp = pp1->p_mixupescapes; int i; pp1->p_firstmixup = pp; for (pp2 = pp, i = 1; pp2 && i < PROPS_MAXMIXUPS; pp2 = pp2->p_next, i++) if (pp2 != pp1) *bp++ = pp2->p_thisescape; *bp = 0; #ifdef PROPS_DEBUG loudbug_startpost("%c \"%s\" ", pp1->p_thisescape, pp1->p_mixupescapes); #endif } #ifdef PROPS_DEBUG loudbug_endpost(); #endif } /* nonzero resolver requires the owner to be nonzero */ t_props *props_new(t_pd *owner, char *name, char *thisdelim, t_props *mixup, t_propsresolver resolver) { t_props *pp = getbytes(sizeof(*pp)); if (pp) { pp->p_name = name; if (thisdelim && *thisdelim) { pp->p_thisescape = *thisdelim++; pp->p_thisinitial = (*thisdelim ? thisdelim : 0); } else { loudbug_bug("props_new (no escape)"); pp->p_thisescape = '-'; pp->p_thisinitial = 0; } props_setupmixups(pp, mixup); pp->p_size = PROPS_INISIZE; pp->p_natoms = 0; pp->p_buffer = pp->p_bufini; pp->p_nextindex = -1; if (pp->p_owner = owner) pp->p_resolver = resolver; else { if (resolver) loudbug_bug("props_new (no owner)"); pp->p_resolver = 0; } pp->p_dict = 0; pp->p_nextelem = 0; } return (pp); } cyclone-0.1-alpha55/shared/common/props.h0000644000076500007650000000227611466617452017016 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __PROPS_H__ #define __PROPS_H__ EXTERN_STRUCT _props; #define t_props struct _props typedef char *(*t_propsresolver)(t_pd *, int, t_atom *); char *props_getvalue(t_props *pp, char *key); char *props_firstvalue(t_props *pp, char **keyp); char *props_nextvalue(t_props *pp, char **keyp); void props_clearvalues(t_props *pp); void props_clonevalues(t_props *to, t_props *from); t_atom *props_getone(t_props *pp, t_symbol *keysym, int *npp); t_atom *props_getfirst(t_props *pp, int *npp); t_atom *props_getnext(t_props *pp, int *npp); t_atom *props_getall(t_props *pp, int *npp); char *props_getname(t_props *pp); t_symbol *props_add(t_props *pp, int single, t_props *filter, t_symbol *s, int ac, t_atom *av); int props_remove(t_props *pp, t_symbol *keysym); void props_diff(t_props *pp0, t_props *pp1, t_props *pp2); void props_clearall(t_props *pp); void props_freeall(t_props *pp); t_props *props_new(t_pd *owner, char *name, char *thisdelim, t_props *mixup, t_propsresolver resolver); #endif cyclone-0.1-alpha55/shared/common/rand.c0000644000076500007650000000403111466617452016561 0ustar hanshans/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" EXTERN double sys_getrealtime(void); /* used to be in m_imp.h */ #include "rand.h" /* borrowed from x_misc.c, LATER rethink */ void rand_seed(unsigned int *statep, unsigned int seed) { if (seed) *statep = (seed & 0x7fffffff); else { /* LATER consider using time elapsed from system startup, (or login -- in linux we might call getutent) */ static unsigned int failsafe = 1489853723; static int shift = 0; static unsigned int lastticks = 0; /* LATER rethink -- it might fail on faster machine than mine (but does it matter?) */ unsigned int newticks = (unsigned int)(sys_getrealtime() * 1000000.); if (newticks == lastticks) { failsafe = failsafe * 435898247 + 938284287; *statep = (failsafe & 0x7fffffff); #ifdef RAND_DEBUG post("rand_seed failed (newticks %d)", newticks); #endif } else { if (!shift) shift = (int)time(0); /* LATER deal with error return (-1) */ *statep = ((newticks + shift) & 0x7fffffff); #if 0 post("rand_seed: newticks %d, shift %d", newticks, shift); #endif } lastticks = newticks; } } /* borrowed from x_misc.c, LATER rethink */ int rand_int(unsigned int *statep, int range) { int result; *statep = *statep * 472940017 + 832416023; result = ((double)range) * ((double)*statep) * (1./4294967296.); return (result < range ? result : range - 1); } float rand_unipolar(unsigned int *statep) { float result; *statep = *statep * 472940017 + 832416023; result = (float)((double)*statep * (1./4294967296.)); return (result); } /* borrowed from d_osc.c, LATER rethink */ float rand_bipolar(unsigned int *statep) { float result = ((float)(((int)*statep & 0x7fffffff) - 0x40000000)) * (float)(1.0 / 0x40000000); *statep = (unsigned)((int)*statep * 435898247 + 382842987); return (result); } cyclone-0.1-alpha55/shared/common/qtree.c0000644000076500007650000005614211466617452016767 0ustar hanshans/* Copyright (c) 2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "loud.h" #include "qtree.h" /* Since there is no sentinel node, the deletion routine has to have a few extra checks. LATER rethink. */ /* LATER freelist */ typedef t_qnode *(*t_qtree_inserthook)(t_qnode *); #ifdef QTREE_DEBUG /* returns black-height or 0 if failed */ static int qnode_verify(t_qnode *np) { if (np) { int bhl, bhr; if (((bhl = qnode_verify(np->n_left)) == 0) || ((bhr = qnode_verify(np->n_right)) == 0)) return (0); if (bhl != bhr) { /* failure: two paths rooted in the same node contain different number of black nodes */ loudbug_bug("qnode_verify: not balanced"); return (0); } if (np->n_black) return (bhl + 1); else { if ((np->n_left && !np->n_left->n_black) || (np->n_right && !np->n_right->n_black)) { loudbug_bug("qnode_verify: adjacent red nodes"); return (0); } return (bhl); } } else return (1); } /* returns black-height or 0 if failed */ static int qtree_verify(t_qtree *tree) { return (qnode_verify(tree->t_root)); } static int qnode_checkmulti(t_qnode *np1, t_qnode *np2) { if (np1 && np2 && np1->n_key == np2->n_key) { if (np1 == np2) loudbug_bug("qnode_checkmulti"); else return (1); } return (0); } static void qnode_post(t_qtree *tree, t_qnode *np, t_qnode_vshowhook hook, char *message) { loudbug_startpost("%g ", np->n_key); if (tree->t_valuetype == QTREETYPE_FLOAT) loudbug_startpost("%g ", QNODE_GETFLOAT(np)); else if (tree->t_valuetype == QTREETYPE_SYMBOL) loudbug_startpost("%s ", QNODE_GETSYMBOL(np)->s_name); else if (tree->t_valuetype == QTREETYPE_ATOM) { t_atom *ap = QNODE_GETATOMPTR(np); if (ap->a_type == A_FLOAT) loudbug_startpost("%g ", ap->a_w.w_float); else if (ap->a_type == A_SYMBOL) loudbug_startpost("%s ", ap->a_w.w_symbol->s_name); } else if (hook) { char buf[MAXPDSTRING]; (*hook)(np, buf, MAXPDSTRING); loudbug_startpost("%s ", buf); } else loudbug_startpost("0x%08x ", (int)QNODE_GETSYMBOL(np)); loudbug_startpost("%s ", (np->n_black ? "black" : "red")); if (qnode_checkmulti(np, np->n_parent) || qnode_checkmulti(np, np->n_left) || qnode_checkmulti(np, np->n_right) || qnode_checkmulti(np->n_parent, np->n_left) || qnode_checkmulti(np->n_parent, np->n_right) || qnode_checkmulti(np->n_left, np->n_right)) loudbug_startpost("multi "); if (np->n_parent) loudbug_startpost("(%g -> ", np->n_parent->n_key); else loudbug_startpost("(nul -> "); if (np->n_left) loudbug_startpost("%g, ", np->n_left->n_key); else loudbug_startpost("nul, "); if (np->n_right) loudbug_startpost("%g)", np->n_right->n_key); else loudbug_startpost("nul)"); if (message) loudbug_post(": %s", message); else loudbug_endpost(); } /* Assert a standard stackless traversal producing the same sequence, as the auxiliary list. */ static int qtree_checktraversal(t_qtree *tree) { t_qnode *treewalk = tree->t_root; t_qnode *listwalk = tree->t_first; int count = 0; while (treewalk) { t_qnode *prev = treewalk->n_left; if (prev) { while (prev->n_right && prev->n_right != treewalk) prev = prev->n_right; if (prev->n_right) { prev->n_right = 0; count++; if (treewalk == listwalk) listwalk = listwalk->n_next; else { loudbug_bug("qtree_checktraversal 1"); qnode_post(tree, treewalk, 0, "treewalk"); if (listwalk) qnode_post(tree, listwalk, 0, "listwalk"); else loudbug_post("empty listwalk pointer"); listwalk = treewalk; } treewalk = treewalk->n_right; } else { prev->n_right = treewalk; treewalk = treewalk->n_left; } } else { count++; if (treewalk == listwalk) listwalk = listwalk->n_next; else { loudbug_bug("qtree_checktraversal 2"); qnode_post(tree, treewalk, 0, "treewalk"); if (listwalk) qnode_post(tree, listwalk, 0, "listwalk"); else loudbug_post("empty listwalk pointer"); listwalk = treewalk; } treewalk = treewalk->n_right; } } return (count); } static int qnode_height(t_qnode *np) { if (np) { int lh = qnode_height(np->n_left); int rh = qnode_height(np->n_right); return (lh > rh ? lh + 1 : rh + 1); } else return (0); } void qtree_debug(t_qtree *tree, int level, t_qnode_vshowhook hook) { t_qnode *np; int count; loudbug_post("------------------------"); count = qtree_checktraversal(tree); if (level) { for (np = tree->t_first; np; np = np->n_next) qnode_post(tree, np, hook, 0); if (level > 1) { loudbug_post("************"); for (np = tree->t_last; np; np = np->n_prev) loudbug_startpost("%g ", np->n_key); loudbug_endpost(); } } if (tree->t_root) { t_qnode *first = tree->t_root, *last = tree->t_root; while (first->n_left && first->n_left != tree->t_root) first = first->n_left; while (last->n_right && last->n_right != tree->t_root) last = last->n_right; loudbug_post("count %d, height %d, root %g", count, qnode_height(tree->t_root), tree->t_root->n_key); loudbug_post("first %g, root->left* %g, last %g, root->right* %g", (tree->t_first ? tree->t_first->n_key : 0), first->n_key, (tree->t_last ? tree->t_last->n_key : 0), last->n_key); } else loudbug_post("empty"); loudbug_post("...verified (black-height is %d)", qtree_verify(tree)); loudbug_post("------------------------"); } #endif /* assuming that target node (np->n_right) exists */ static void qtree_lrotate(t_qtree *tree, t_qnode *np) { t_qnode *target = np->n_right; if (np->n_right = target->n_left) np->n_right->n_parent = np; if (!(target->n_parent = np->n_parent)) tree->t_root = target; else if (np == np->n_parent->n_left) np->n_parent->n_left = target; else np->n_parent->n_right = target; target->n_left = np; np->n_parent = target; } /* assuming that target node (np->n_left) exists */ static void qtree_rrotate(t_qtree *tree, t_qnode *np) { t_qnode *target = np->n_left; if (np->n_left = target->n_right) np->n_left->n_parent = np; if (!(target->n_parent = np->n_parent)) tree->t_root = target; else if (np == np->n_parent->n_left) np->n_parent->n_left = target; else np->n_parent->n_right = target; target->n_right = np; np->n_parent = target; } static t_qnode *qtree_preinserthook(t_qnode *np) { while (np->n_prev && np->n_prev->n_key == np->n_key) np = np->n_prev; if (np->n_left) { np = np->n_prev; if (np->n_right) { /* LATER revisit */ loudbug_bug("qtree_preinserthook"); return (0); /* do nothing */ } } return (np); } static t_qnode *qtree_postinserthook(t_qnode *np) { while (np->n_next && np->n_next->n_key == np->n_key) np = np->n_next; if (np->n_right) { np = np->n_next; if (np->n_left) { /* LATER revisit */ loudbug_bug("qtree_postinserthook"); return (0); /* do nothing */ } } return (np); } /* Returns a newly inserted or already existing node (or 0 if allocation failed). A caller is responsible for assigning a value. If hook is supplied, it is called iff key is found. In case of key being found (which means foundp returns 1), a new node is inserted, unless hook is either empty, or returns null. Hook's nonempty return is the parent for the new node. It is expected to have no more than one child. */ static t_qnode *qtree_doinsert(t_qtree *tree, double key, t_qnode *preexisting, t_qtree_inserthook hook, int *foundp) { t_qnode *np, *parent, *result; int leftchild; *foundp = 0; if (!(np = tree->t_root)) { if (!(np = (tree->t_nodesize > 0 ? getbytes(tree->t_nodesize) : preexisting))) { if (tree->t_nodesize == 0) loudbug_bug("qtree_insert, node not supplied"); return (0); } np->n_key = key; np->n_black = 1; np->n_left = np->n_right = np->n_parent = 0; tree->t_root = tree->t_first = tree->t_last = np; np->n_prev = np->n_next = 0; return (np); } do { if (np->n_key == key) { *foundp = 1; if (hook && (parent = (*hook)(np))) { if (parent->n_left && parent->n_right) { loudbug_bug("qtree_insert, callback return 1"); parent = parent->n_next; } if (leftchild = (key < parent->n_key)) { if (parent->n_left) { loudbug_bug("qtree_insert, callback return 2"); leftchild = 0; } } else if (parent->n_right) leftchild = 1; goto addit; } else return (np); /* a caller may then keep or replace the value */ } else parent = np; } while (np = (key < np->n_key ? np->n_left : np->n_right)); leftchild = (key < parent->n_key); addit: /* parent has no more than one child, new node becomes parent's immediate successor or predecessor */ if (!(np = (tree->t_nodesize > 0 ? getbytes(tree->t_nodesize) : preexisting))) { if (tree->t_nodesize == 0) loudbug_bug("qtree_insert, node not supplied"); return (0); } np->n_key = key; np->n_parent = parent; if (leftchild) { parent->n_left = np; /* update the auxiliary linked list structure */ np->n_next = parent; if (np->n_prev = parent->n_prev) np->n_prev->n_next = np; else tree->t_first = np; parent->n_prev = np; } else { parent->n_right = np; /* update the auxiliary linked list structure */ np->n_prev = parent; if (np->n_next = parent->n_next) np->n_next->n_prev = np; else tree->t_last = np; parent->n_next = np; } result = np; /* balance the tree -- LATER clean this if possible... */ np->n_black = 0; while (np != tree->t_root && !np->n_parent->n_black) { t_qnode *uncle; /* np->n_parent->n_parent exists (we always paint root node in black) */ if (np->n_parent == np->n_parent->n_parent->n_left) { uncle = np->n_parent->n_parent->n_right; if (!uncle /* (sentinel not used) */ || uncle->n_black) { if (np == np->n_parent->n_right) { np = np->n_parent; qtree_lrotate(tree, np); } np->n_parent->n_black = 1; np->n_parent->n_parent->n_black = 0; qtree_rrotate(tree, np->n_parent->n_parent); } else { np->n_parent->n_black = 1; uncle->n_black = 1; np = np->n_parent->n_parent; np->n_black = 0; } } else { uncle = np->n_parent->n_parent->n_left; if (!uncle /* (sentinel not used) */ || uncle->n_black) { if (np == np->n_parent->n_left) { np = np->n_parent; qtree_rrotate(tree, np); } np->n_parent->n_black = 1; np->n_parent->n_parent->n_black = 0; qtree_lrotate(tree, np->n_parent->n_parent); } else { np->n_parent->n_black = 1; uncle->n_black = 1; np = np->n_parent->n_parent; np->n_black = 0; } } } tree->t_root->n_black = 1; return (result); } /* assuming that requested node exists */ void qtree_delete(t_qtree *tree, t_qnode *gone) { t_qnode *parent; /* parent of gone, after relinking */ t_qnode *child; /* gone's only child (or null), after relinking */ /* gone has to be the parent of no more than one child */ if (gone->n_left && gone->n_right) { /* Successor is the new parent of gone's children, and a new child of gone's parent (if any). Successor always exists in this context, and it has no left child. The simplistic scheme is to replace gone's fields with successor's fields, and delete the successor. We cannot do so, however, because 1. nodes may be caller-owned (nodesize == 0), 2. successor may be pointed at... */ t_qnode *successor = gone->n_next; child = successor->n_right; successor->n_left = gone->n_left; successor->n_left->n_parent = successor; if (successor == gone->n_right) parent = successor; else { /* successor's parent always exists in this context, successor is the left child of its parent */ parent = successor->n_parent; parent->n_left = child; if (child) /* (sentinel not used) */ child->n_parent = parent; successor->n_right = gone->n_right; successor->n_right->n_parent = successor; } if (gone->n_parent) { int swp; if (gone == gone->n_parent->n_left) gone->n_parent->n_left = successor; else gone->n_parent->n_right = successor; successor->n_parent = gone->n_parent; swp = gone->n_black; gone->n_black = successor->n_black; successor->n_black = swp; } else { tree->t_root = successor; successor->n_parent = 0; gone->n_black = successor->n_black; successor->n_black = 1; /* LATER rethink */ } /* update the auxiliary linked list structure */ if (successor->n_prev = gone->n_prev) gone->n_prev->n_next = successor; else tree->t_first = successor; } else { /* update the auxiliary linked list structure */ if (gone->n_prev) gone->n_prev->n_next = gone->n_next; else tree->t_first = gone->n_next; if (gone->n_next) gone->n_next->n_prev = gone->n_prev; else tree->t_last = gone->n_prev; /* connect gone's child with gone's parent */ if (gone->n_left) child = gone->n_left; else child = gone->n_right; if (parent = gone->n_parent) { if (child) /* (sentinel not used) */ child->n_parent = parent; if (gone == parent->n_left) parent->n_left = child; else parent->n_right = child; } else { if (tree->t_root = child) { child->n_parent = 0; child->n_black = 1; /* LATER rethink */ } goto done; } } if (gone->n_black) { /* balance the tree -- LATER clean this if possible... */ /* on entry: tree is not empty, parent always exists, child not necessarily... */ while (child != tree->t_root && (!child || /* (sentinel not used) */ child->n_black)) { t_qnode *other; /* another child of the same parent */ if (child == parent->n_left) { other = parent->n_right; if (other && /* (sentinel not used) */ !other->n_black) { other->n_black = 1; parent->n_black = 0; qtree_lrotate(tree, parent); other = parent->n_right; } if (!other || /* (sentinel not used) */ (!other->n_left || other->n_left->n_black) && (!other->n_right || other->n_right->n_black)) { if (other) /* (sentinel not used) */ other->n_black = 0; child = parent; parent = parent->n_parent; } else { if (!other || /* (sentinel not used) */ !other->n_right || other->n_right->n_black) { if (other) /* (sentinel not used) */ { if (other->n_left) other->n_left->n_black = 1; other->n_black = 0; qtree_rrotate(tree, other); other = parent->n_right; } } if (other) /* (sentinel not used) */ { if (other->n_right) other->n_right->n_black = 1; other->n_black = parent->n_black; } parent->n_black = 1; qtree_lrotate(tree, parent); tree->t_root->n_black = 1; /* LATER rethink */ goto done; } } else /* right child */ { other = parent->n_left; if (other && /* (sentinel not used) */ !other->n_black) { other->n_black = 1; parent->n_black = 0; qtree_rrotate(tree, parent); other = parent->n_left; } if (!other || /* (sentinel not used) */ (!other->n_left || other->n_left->n_black) && (!other->n_right || other->n_right->n_black)) { if (other) /* (sentinel not used) */ other->n_black = 0; child = parent; parent = parent->n_parent; } else { if (!other || /* (sentinel not used) */ !other->n_left || other->n_left->n_black) { if (other) /* (sentinel not used) */ { if (other->n_right) other->n_right->n_black = 1; other->n_black = 0; qtree_lrotate(tree, other); other = parent->n_left; } } if (other) /* (sentinel not used) */ { if (other->n_left) other->n_left->n_black = 1; other->n_black = parent->n_black; } parent->n_black = 1; qtree_rrotate(tree, parent); tree->t_root->n_black = 1; /* LATER rethink */ goto done; } } } if (child) /* (sentinel not used) */ child->n_black = 1; } done: if (tree->t_nodesize) freebytes(gone, tree->t_nodesize); #ifdef QTREE_DEBUG qtree_verify(tree); #endif } t_qnode *qtree_search(t_qtree *tree, double key) { t_qnode *np = tree->t_root; while (np && np->n_key != key) np = (key < np->n_key ? np->n_left : np->n_right); return (np); } /* Returns the greatest node <= key, if any (may return null). If deltap is not null, it will hold the abs diff (key - node.n_key). */ t_qnode *qtree_closestunder(t_qtree *tree, double key, double *deltap) { t_qnode *np, *parent; if (!(np = tree->t_root)) return (0); do if (np->n_key == key) { if (deltap) *deltap = 0.; return (np); } else parent = np; while (np = (key < np->n_key ? np->n_left : np->n_right)); if (np = (key < parent->n_key ? parent->n_prev : parent)) { if (deltap) *deltap = key - np->n_key; return (np); } else return (0); } /* Returns the smallest node >= key, if any (may return null). If deltap is not null, it will hold the abs diff (node.n_key - key). */ t_qnode *qtree_closestover(t_qtree *tree, double key, double *deltap) { t_qnode *np, *parent; if (!(np = tree->t_root)) return (0); do if (np->n_key == key) { if (deltap) *deltap = 0.; return (np); } else parent = np; while (np = (key < np->n_key ? np->n_left : np->n_right)); if (np = (key > parent->n_key ? parent->n_next : parent)) { if (deltap) *deltap = np->n_key - key; return (np); } else return (0); } /* Returns the smallest node >= key or the greatest node <= key, whichever makes the smallest abs diff, |key - node.n_key|. Returns null only for an empty tree. If deltap is not null, it will hold the signed diff (negative for an undernode, i.e. when node < key). */ t_qnode *qtree_closest(t_qtree *tree, double key, double *deltap) { t_qnode *np, *parent; if (!(np = tree->t_root)) return (0); do if (np->n_key == key) { if (deltap) *deltap = 0.; return (np); } else parent = np; while (np = (key < np->n_key ? np->n_left : np->n_right)); if (key > parent->n_key) { if (np = parent->n_next) { double delta1 = key - parent->n_key; double delta2 = np->n_key - key; if (delta1 < delta2) { if (deltap) *deltap = -delta1; return (parent); } else { if (deltap) *deltap = delta2; return (np); } } else { if (deltap) *deltap = parent->n_key - key; return (parent); } } else { if (np = parent->n_prev) { double delta1 = key - np->n_key; double delta2 = parent->n_key - key; if (delta1 < delta2) { if (deltap) *deltap = -delta1; return (np); } else { if (deltap) *deltap = delta2; return (parent); } } else { if (deltap) *deltap = parent->n_key - key; return (parent); } } } t_qnode *qtree_insert(t_qtree *tree, double key, t_qnode *preexisting, int *foundp) { int found; return (qtree_doinsert(tree, key, preexisting, 0, (foundp ? foundp : &found))); } t_qnode *qtree_multiinsert(t_qtree *tree, double key, t_qnode *preexisting, int fifoflag) { int found; return (qtree_doinsert(tree, key, preexisting, (fifoflag ? qtree_postinserthook : qtree_preinserthook), &found)); } t_qnode *qtree_override(t_qtree *tree, t_qnode *oldnode, t_qnode *newnode) { if (tree->t_nodesize) { loudbug_bug("qtree_override 1"); return (0); } else { newnode->n_key = oldnode->n_key; newnode->n_black = oldnode->n_black; if (newnode->n_left = oldnode->n_left) newnode->n_left->n_parent = newnode; if (newnode->n_right = oldnode->n_right) newnode->n_right->n_parent = newnode; if (newnode->n_parent = oldnode->n_parent) { if (oldnode == newnode->n_parent->n_left) newnode->n_parent->n_left = newnode; else if (oldnode == newnode->n_parent->n_right) newnode->n_parent->n_right = newnode; else loudbug_bug("qtree_override 2"); } if (newnode->n_prev = oldnode->n_prev) newnode->n_prev->n_next = newnode; if (newnode->n_next = oldnode->n_next) newnode->n_next->n_prev = newnode; if (tree->t_root == oldnode) tree->t_root = newnode; if (tree->t_first == oldnode) tree->t_first = newnode; if (tree->t_last == oldnode) tree->t_last = newnode; return (newnode); } } t_qnode *qtree_insertfloat(t_qtree *tree, double key, t_float f, int replaceflag) { int found; t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_FLOAT) { t_qnode_float *npf = (t_qnode_float *)np; npf->nf_value = f; } else if (tree->t_valuetype == QTREETYPE_ATOM) { t_qnode_atom *npa = (t_qnode_atom *)np; t_atom *ap = &npa->na_value; SETFLOAT(ap, f); } else loudbug_bug("qtree_insertfloat"); } return (np); } t_qnode *qtree_insertsymbol(t_qtree *tree, double key, t_symbol *s, int replaceflag) { int found; t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_SYMBOL) { t_qnode_symbol *nps = (t_qnode_symbol *)np; nps->ns_value = s; } else if (tree->t_valuetype == QTREETYPE_ATOM) { t_qnode_atom *npa = (t_qnode_atom *)np; t_atom *ap = &npa->na_value; SETSYMBOL(ap, s); } else loudbug_bug("qtree_insertsymbol"); } return (np); } t_qnode *qtree_insertatom(t_qtree *tree, double key, t_atom *ap, int replaceflag) { int found; t_qnode *np = qtree_doinsert(tree, key, 0, 0, &found); if (np && (!found || replaceflag)) { if (tree->t_valuetype == QTREETYPE_ATOM) { t_qnode_atom *npa = (t_qnode_atom *)np; npa->na_value = *ap; } else loudbug_bug("qtree_insertatom"); } return (np); } /* LATER preallocate 'freecount' nodes */ static void qtree_doinit(t_qtree *tree, t_qtreetype vtype, size_t nodesize, int freecount) { tree->t_root = tree->t_first = tree->t_last = 0; tree->t_valuetype = vtype; tree->t_nodesize = nodesize; } void qtree_inittyped(t_qtree *tree, t_qtreetype vtype, int freecount) { size_t nsize; switch (vtype) { case QTREETYPE_FLOAT: nsize = sizeof(t_qnode_float); break; case QTREETYPE_SYMBOL: nsize = sizeof(t_qnode_symbol); break; case QTREETYPE_ATOM: nsize = sizeof(t_qnode_atom); break; default: loudbug_bug("qtree_inittyped"); vtype = QTREETYPE_ILLEGAL; nsize = sizeof(t_qnode); } qtree_doinit(tree, vtype, nsize, freecount); } void qtree_initcustom(t_qtree *tree, size_t nodesize, int freecount) { qtree_doinit(tree, QTREETYPE_CUSTOM, nodesize, freecount); } /* LATER keep and/or preallocate 'freecount' nodes (if negative, keep all) */ void qtree_clear(t_qtree *tree, int freecount) { t_qnode *np, *next = tree->t_first; while (np = next) { next = next->n_next; if (tree->t_nodesize) freebytes(np, tree->t_nodesize); } qtree_doinit(tree, tree->t_valuetype, tree->t_nodesize, 0); } cyclone-0.1-alpha55/shared/common/lex.c0000644000076500007650000001357511466617452016442 0ustar hanshans/* Copyright (c) 1997-2004 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include #ifdef MIXED_STANDALONE #include "unstable/standalone.h" #else #include "m_pd.h" #endif #include "lex.h" static int lex_nextbyte(t_lex *lx, unsigned char *buf) { int ich; if (lx->l_fp) { if ((ich = fgetc(lx->l_fp)) == EOF) return (0); } else if (lx->l_buf) { if (lx->l_bufndx < lx->l_bufsize) ich = lx->l_buf[lx->l_bufndx++]; else return (0); } else return (0); if (ich) { *buf = (unsigned char)ich; return (1); } else { lx->l_errbinary = 1; return (0); } } static void lex_ungetbyte(t_lex *lx, unsigned char ch) { if (lx->l_fp) { ungetc(ch, lx->l_fp); } else if (lx->l_buf) { if (lx->l_bufndx > 0) lx->l_buf[--lx->l_bufndx] = ch; } } /* single pass of binbuf_text(), optionally int-preserving version */ int lex_nextatom(t_lex *lx, t_atom *ap) { char buf[1001], *bufp, *ebuf = buf + 1000; int ready; unsigned char ch; ap->a_type = A_NULL; while ((ready = lex_nextbyte(lx, &ch)) && (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')); if (!ready) { /* ??? */ if (lx->l_lasttype == A_SEMI) return (0); else ap->a_type = A_SEMI; } else if (ch == ';') ap->a_type = A_SEMI; else if (ch == ',') ap->a_type = A_COMMA; else { int floatstate = 0, slash = 0, lastslash = 0, firstslash = (ch == '\\'); bufp = buf; do { *bufp = ch; lastslash = slash; slash = (ch == '\\'); if (floatstate >= 0) { int digit = (ch >= '0' && ch <= '9'), dot = (ch == '.'), minus = (ch == '-'), plusminus = (minus || (ch == '+')), expon = (ch == 'e' || ch == 'E'); if (floatstate == 0) /* beginning */ { if (minus) floatstate = 1; else if (digit) floatstate = 2; else if (dot) floatstate = 3; else floatstate = -1; } else if (floatstate == 1) /* got minus */ { if (digit) floatstate = 2; else if (dot) floatstate = 3; else floatstate = -1; } else if (floatstate == 2) /* got digits */ { if (dot) floatstate = 4; else if (expon) floatstate = 6; else if (!digit) floatstate = -1; } else if (floatstate == 3) /* got '.' without digits */ { if (digit) floatstate = 5; else floatstate = -1; } else if (floatstate == 4) /* got '.' after digits */ { if (digit) floatstate = 5; else if (expon) floatstate = 6; else floatstate = -1; } else if (floatstate == 5) /* got digits after . */ { if (expon) floatstate = 6; else if (!digit) floatstate = -1; } else if (floatstate == 6) /* got 'e' */ { if (plusminus) floatstate = 7; else if (digit) floatstate = 8; else floatstate = -1; } else if (floatstate == 7) /* got plus or minus */ { if (digit) floatstate = 8; else floatstate = -1; } else if (floatstate == 8) /* got digits */ { if (!digit) floatstate = -1; } } if (!slash) bufp++; } while ((ready = lex_nextbyte(lx, &ch)) && bufp != ebuf && (slash || (ch != ' ' && ch != '\n' && ch != '\r' && ch != '\t' && ch != ',' && ch != ';'))); if (ready && (ch == ',' || ch == ';')) lex_ungetbyte(lx, ch); *bufp = 0; #if 0 fprintf(stderr, "buf %s\n", buf); #endif if (*buf == '$' && buf[1] >= '0' && buf[1] <= '9' && !firstslash) { for (bufp = buf+2; *bufp; bufp++) { if (*bufp < '0' || *bufp > '9') { ap->a_type = A_DOLLSYM; ap->a_w.w_symbol = gensym(buf+1); break; } } if (ap->a_type == A_NULL) { ap->a_type = A_DOLLAR; ap->a_w.w_index = atoi(buf+1); } } else if (floatstate == 2) { if (lx->l_inttype == A_FLOAT) { ap->a_type = A_FLOAT; ap->a_w.w_float = (float)atof(buf); } else { ap->a_type = lx->l_inttype; ap->a_w.w_index = atoi(buf); } } else if (floatstate == 4 || floatstate == 5 || floatstate == 8) { ap->a_type = A_FLOAT; ap->a_w.w_float = (float)atof(buf); } else { ap->a_type = A_SYMBOL; ap->a_w.w_symbol = gensym(buf); } } lx->l_lasttype = ap->a_type; return (1); } void lex_atomstring(t_atom *ap, char *buf, int bufsize, t_atomtype inttype) { char *sp, *bp, *ep; switch(ap->a_type) { case A_SEMI: strcpy(buf, ";"); break; case A_COMMA: strcpy(buf, ","); break; case A_FLOAT: sprintf(buf, "%#f", ap->a_w.w_float); ep = buf + strlen(buf) - 1; while (ep > buf && *ep == '0') *ep-- = 0; break; case A_SYMBOL: sp = ap->a_w.w_symbol->s_name; bp = buf; ep = buf + (bufsize-5); while (bp < ep && *sp) { if (*sp == ';' || *sp == ',' || *sp == '\\' || (*sp == '$' && bp == buf && sp[1] >= '0' && sp[1] <= '9')) *bp++ = '\\'; if ((unsigned char)*sp < 127) *bp++ = *sp++; else /* FIXME this is temporary -- codepage horror */ sprintf(bp, "\\%.3o", (unsigned char)*sp++), bp += 4; } if (*sp) *bp++ = '*'; *bp = 0; break; case A_DOLLAR: sprintf(buf, "$%d", ap->a_w.w_index); break; case A_DOLLSYM: sprintf(buf, "$%s", ap->a_w.w_symbol->s_name); break; default: if (ap->a_type == inttype) sprintf(buf, "%d", ap->a_w.w_index); else { #ifdef MIXED_STANDALONE fprintf(stderr, "BUG (lex): bad atom type\n"); #else bug("lex_atomstring (bad atom type)"); #endif strcpy(buf, "???"); } } } int lex_isbinary(t_lex *lx) { return (lx->l_errbinary); } void lex_free(t_lex *lx) { freebytes(lx, sizeof(*lx)); } t_lex *lex_new(FILE *fp, t_atomtype inttype) { t_lex *lx = (t_lex *)getbytes(sizeof(*lx)); lx->l_fp = fp; lx->l_buf = 0; /* FIXME */ lx->l_inttype = inttype; lx->l_lasttype = A_SEMI; lx->l_errbinary = 0; return (lx); } cyclone-0.1-alpha55/shared/common/patchvalue.c0000644000076500007650000001404211466617452017774 0ustar hanshans/* Copyright (c) 2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include "m_pd.h" #include "g_canvas.h" #include "patchvalue.h" #ifdef KRZYSZCZ # include "loud.h" # define PATCHVALUE_DEBUG #else # define loudbug_bug(msg) fprintf(stderr, "BUG: %s\n", msg), bug(msg) #endif typedef struct _patchstorage { t_glist *ps_glist; t_patchvalue *ps_values; struct _patchstorage *ps_next; } t_patchstorage; typedef struct _patchboard { t_pd pb_pd; t_symbol *pb_category; t_patchstorage *pb_contents; } t_patchboard; static t_class *patchboard_class = 0; /* assuming there is no 'name' in the storage */ static t_patchvalue *patchstorage_addvalue( t_patchstorage *ps, t_patchvalue *prv, t_class *cls, t_symbol *name) { t_patchvalue *pv = (t_patchvalue *)pd_new(cls); pv->pv_name = name; pv->pv_refcount = 0; if (prv) { pv->pv_next = prv->pv_next; prv->pv_next = pv; } else { pv->pv_next = ps->ps_values; ps->ps_values = pv; } return (pv); } /* assuming there is no 'glist' on the board */ static t_patchstorage *patchboard_addstorage( t_patchboard *pb, t_patchstorage *prv, t_glist *glist) { t_patchstorage *ps = getbytes(sizeof(*ps)); ps->ps_glist = glist; ps->ps_values = 0; if (prv) { ps->ps_next = prv->ps_next; prv->ps_next = ps; } else { ps->ps_next = pb->pb_contents; pb->pb_contents = ps; } return (ps); } /* not used (LATER find a gc scheme) */ static void patchstorage_removevalue( t_patchstorage *ps, t_patchvalue *prv, t_patchvalue *pv, int force) { if (force || pv->pv_refcount < 1) { if (prv) prv->pv_next = pv->pv_next; else ps->ps_values = pv->pv_next; pd_free((t_pd *)pv); } } /* not used (LATER find a gc scheme) */ static void patchboard_removestorage( t_patchboard *pb, t_patchstorage *prv, t_patchstorage *ps, int force) { if (prv) prv->ps_next = ps->ps_next; else pb->pb_contents = ps->ps_next; if (force) { t_patchvalue *pv, *pvnext = ps->ps_values; while (pv = pvnext) { pvnext = pv->pv_next; pd_free((t_pd *)pv); } } else if (ps->ps_values) return; freebytes(ps, sizeof(*ps)); } static t_patchvalue *patchstorage_findvalue( t_patchstorage *ps, t_symbol *name) { t_patchvalue *pv; for (pv = ps->ps_values; pv; pv = pv->pv_next) if (pv->pv_name == name) break; return (pv); } static t_patchstorage *patchboard_findstorage( t_patchboard *pb, t_glist *glist) { t_patchstorage *ps; for (ps = pb->pb_contents; ps; ps = ps->ps_next) if (ps->ps_glist == glist) break; return (ps); } static t_patchboard *patchboard_find(t_symbol *category) { if (!patchboard_class) patchboard_class = patchvalue_classnew(gensym("_patchboard"), sizeof(t_patchboard)); return ((t_patchboard *)pd_findbyclass(category, patchboard_class)); } static t_patchboard *patchboard_use(t_symbol *category) { if (!patchboard_class) patchboard_class = patchvalue_classnew(gensym("_patchboard"), sizeof(t_patchboard)); if (category && *category->s_name == '#') { t_patchboard *pb; if (!(pb = (t_patchboard *)pd_findbyclass(category, patchboard_class))) { pb = (t_patchboard *)pd_new(patchboard_class); pb->pb_category = category; pd_bind((t_pd *)pb, category); /* never unbound */ pb->pb_contents = 0; } return (pb); } else { loudbug_bug("patchboard_use"); return (0); } } static t_patchstorage *patchstorage_use(t_symbol *category, t_glist *glist) { t_patchboard *pb; if (pb = patchboard_use(category)) { t_patchstorage *ps; if (!(ps = patchboard_findstorage(pb, glist))) ps = patchboard_addstorage(pb, 0, glist); return (ps); } else return (0); } /* The class might have been created by another dll... This is public, because apart from the "_patchboard" class above, it is called for the "_raftentry" class too. LATER rethink. */ t_class *patchvalue_classnew(t_symbol *cname, size_t size) { t_class *cls; t_symbol *bindsym; char buf[MAXPDSTRING]; sprintf(buf, "#%s", cname->s_name); bindsym = gensym(buf); if (bindsym->s_thing) { t_pd *pd = bindsym->s_thing; char *name = class_getname(*pd); if (strcmp(name, cname->s_name)) { /* FIXME handle this properly... */ loudbug_bug("patchvalue_classnew"); } else return (*pd); } cls = class_new(cname, 0, 0, size, CLASS_PD | CLASS_NOINLET, 0); pd_bind(pd_new(cls), bindsym); /* never unbound */ return (cls); } t_patchvalue *patchvalue_use(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name) { t_patchstorage *ps; if (ps = patchstorage_use(category, glist)) { t_patchvalue *pv; if (pv = patchstorage_findvalue(ps, name)) { if (*(t_pd *)pv != cls) { loudbug_bug("patchvalue_use"); return (0); } } else pv = patchstorage_addvalue(ps, 0, cls, name); return (pv); } else return (0); } t_patchvalue *patchvalue_get(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name) { t_patchboard *pb; t_patchstorage *ps; t_patchvalue *pv; if ((pb = patchboard_find(category)) && (ps = patchboard_findstorage(pb, glist)) && (pv = patchstorage_findvalue(ps, name))) { if (*(t_pd *)pv == cls) return (pv); else loudbug_bug("patchvalue_get"); } return (0); } t_patchvalue *patchvalue_resolve(t_symbol *category, t_glist *glist, t_class *cls, t_symbol *name) { t_patchboard *pb; if (pb = patchboard_find(category)) { t_patchstorage *ps; t_patchvalue *pv; while (glist) { if ((ps = patchboard_findstorage(pb, glist)) && (pv = patchstorage_findvalue(ps, name))) { if (*(t_pd *)pv == cls) return (pv); else loudbug_bug("patchvalue_resolve"); } else if (canvas_isabstraction(glist)) break; else glist = glist->gl_owner; } } return (0); } cyclone-0.1-alpha55/shared/common/Makefile.sources0000644000076500007650000000025511466617452020617 0ustar hanshansOTHER_SOURCES = \ binport.c \ clc.c \ dict.c \ fitter.c \ grow.c \ lex.c \ loud.c \ messtree.c \ mifi.c \ os.c \ patchvalue.c \ port.c \ props.c \ qtree.c \ rand.c \ vefl.c cyclone-0.1-alpha55/shared/common/port.c0000644000076500007650000012314211466617452016626 0ustar hanshans/* Copyright (c) 1997-2005 Miller Puckette, krzYszcz, and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER think about abstractions */ /* LATER sort out escaping rules (also revisit binport.c) */ /* LATER quoting */ /* LATER rethink inlet/inlet~ case */ #ifdef UNIX #include #endif #ifdef NT #include #endif #include #include #include #include "m_pd.h" #include "g_canvas.h" #include "unstable/forky.h" #include "unstable/fragile.h" #include "unstable/fringe.h" #include "common/loud.h" #include "common/grow.h" #include "common/binport.h" #include "port.h" #ifdef KRZYSZCZ //#define PORT_DEBUG #endif #define PORT_LOG #define PORT_DUMP /* fill separate files with ignored data, e.g. pictures */ #define PORT_INISTACK 256 /* LATER rethink */ #define PORT_INISIZE 512 /* LATER rethink */ /* FIXME use messtree api */ enum { PORT_OK, /* MESSTREE_CONTINUE */ PORT_NEXT, /* next line, please: MESSTREE_OK */ PORT_UNKNOWN, PORT_CORRUPT, PORT_FATAL }; /* cf binport.c */ #define A_INT A_DEFFLOAT /* without access to sys_defaultfont, we just mimic defs from s_main.c */ #ifdef MSW #define PORT_DEFFONTSIZE 12. #else #define PORT_DEFFONTSIZE 10. #endif #define PORT_XSTRETCH 1.25 #define PORT_YSTRETCH 1.1 #define PORT_WSTRETCH 1.25 typedef struct _port { t_binbuf *x_outbb; int x_messcount; int x_illmess; int x_lastunexpected; int x_lastbroken; int x_lastinconsistent; int x_nobj; int x_withbogus; int x_inatoms; t_atom *x_inmess; int x_outsize; int x_outatoms; t_atom *x_outmess; t_atom x_outini[PORT_INISIZE]; int x_stacksize; int x_stackdepth; int *x_stack; int x_stackini[PORT_INISTACK]; t_symbol *x_emstate; t_binbuf *x_embb; t_symbol *x_emname; int x_emsize; int x_emcount; int x_dumping; /* class-specifics, LATER find a better way */ FILE *x_pictfp; int x_pictno; } t_port; static t_symbol *portps_bogus; static t_symbol *portps_cleanup; static t_symbol *portps_inlet; static t_symbol *portps_outlet; static t_symbol *portps_vtable; static t_symbol *portps_coll; static t_symbol *portps_funbuff; static t_symbol *portps_prob; static t_symbol *portps_picture; static char *import_defmapping[] = { /* clashing clones */ "append", "Append", "b", "bangbang", "clip", "Clip", "clip~", "Clip~", "line~", "Line~", "scope~", "Scope~", "snapshot~", "Snapshot~", /* clashing dummies */ "biquad~", "Biquad~", "change", "Change", "key", "Key", "keyup", "Keyup", "line", "Line", "poly", "Poly", /* doomed dummies */ "appledvd", "c74.appledvd", "plugconfig", "c74.plugconfig", "plugin~", "c74.plugin~", "plugmidiin", "c74.plugmidiin", "plugmidiout", "c74.plugmidiout", "plugmod", "c74.plugmod", "plugmorph", "c74.plugmorph", "plugmultiparam", "c74.plugmultiparam", "plugout~", "c74.plugout~", "plugphasor~", "c74.plugphasor~", "plugreceive~", "c74.plugreceive~", "plugsend~", "c74.plugsend~", "plugstore", "c74.plugstore", "plugsync~", "c74.plugsync~", "pp", "c74.pp", "pptempo", "c74.pptempo", "pptime", "c74.pptime", "rewire~", "c74.rewire~", "sndmgrin~", "c74.sndmgrin~", "vdp", "c74.vdp", "vst~", "c74.vst~" }; static int import_mapsize = 0; static char **import_mapping = 0; static void import_setdefmapping(void) { import_mapsize = sizeof(import_defmapping)/(2 * sizeof(*import_defmapping)); import_mapping = import_defmapping; } void import_setmapping(int size, char **mapping) { import_mapsize = size; import_mapping = mapping; } char **import_getmapping(int *sizep) { if (!import_mapping) import_setdefmapping(); *sizep = import_mapsize; return (import_mapping); } char *port_usemapping(char *from, int mapsize, char **mapping) { while (mapsize--) { if (strcmp(*mapping, from)) mapping += 2; else return (mapping[1]); } return (0); } static t_int port_getint(t_port *x, int ndx) { if (ndx < x->x_inatoms) { t_atom *av = &x->x_inmess[ndx]; if (av->a_type == A_INT) return (av->a_w.w_index); else if (av->a_type == A_FLOAT) { loud_warning(0, "import", "[%d] float atom %d, int expected", x->x_messcount, ndx); return ((t_int)av->a_w.w_float); } } return (0); } static t_float port_getfloat(t_port *x, int ndx) { if (ndx < x->x_inatoms) { t_atom *av = &x->x_inmess[ndx]; return (av->a_type == A_FLOAT ? av->a_w.w_float : 0); } else return (0); } static t_symbol *port_getsymbol(t_port *x, int ndx) { if (ndx < x->x_inatoms) { t_atom *av = &x->x_inmess[ndx]; return (av->a_type == A_SYMBOL ? av->a_w.w_symbol : &s_); } else return (&s_); } static t_symbol *port_getanysymbol(t_port *x, int ndx) { t_symbol *sel = &s_; if (ndx < x->x_inatoms) { t_atom *av = &x->x_inmess[ndx]; if (av->a_type == A_SYMBOL) sel = av->a_w.w_symbol; else if (av->a_type == A_INT) sel = gensym("int"); else if (av->a_type == A_FLOAT) sel = &s_float; } return (sel); } static t_symbol *port_gettarget(t_port *x) { t_symbol *sel = port_getsymbol(x, 0); if (sel == &s_) loudbug_bug("port_gettarget"); return (sel); } static t_symbol *port_getselector(t_port *x) { t_symbol *sel = port_getanysymbol(x, 1); if (sel == &s_) loudbug_bug("port_getselector"); return (sel); } static int port_xstretch(float f) { return ((int)(f * PORT_XSTRETCH + 0.5)); } static int port_ystretch(float f) { return ((int)(f * PORT_YSTRETCH + 0.5)); } static int port_wstretch(float f) { return ((int)(f * PORT_WSTRETCH + 0.5)); } static t_float port_getx(t_port *x, int ndx) { return ((t_float)port_xstretch(port_getint(x, ndx))); } static t_float port_gety(t_port *x, int ndx) { return ((t_float)port_ystretch(port_getint(x, ndx))); } static t_float port_getwidth(t_port *x, int ndx) { return ((t_float)port_wstretch(port_getint(x, ndx))); } static void port_setxy(t_port *x, int ndx, t_atom *ap) { float f = port_getx(x, ndx); SETFLOAT(ap, f); ndx++; ap++; f = port_gety(x, ndx); SETFLOAT(ap, f); } static t_atom *import_copyatoms(t_atom *out, t_atom *in, int ac) { while (ac-- > 0) { if (in->a_type == A_INT) { out->a_type = A_FLOAT; out++->a_w.w_float = (float)in++->a_w.w_index; } else *out++ = *in++; } return (out); } static void import_unexpected(t_port *x) { if (x->x_lastunexpected < x->x_messcount) /* ignore redundant calls */ { x->x_lastunexpected = x->x_messcount; loud_warning(0, "import", "[%d] unexpected \"%s %s\"", x->x_messcount, port_gettarget(x)->s_name, port_getselector(x)->s_name); } } static void import_illegal(t_port *x) { x->x_illmess++; } static void import_flushillegal(t_port *x) { if (x->x_illmess) { if (x->x_illmess == 1) loud_warning(0, "import", "[%d] illegal line", x->x_messcount); else loud_warning(0, "import", "[%d] %d illegal lines", x->x_messcount, x->x_illmess); x->x_illmess = 0; } } static void import_embroken(t_port *x, char *cause) { if (x->x_lastbroken < x->x_messcount) /* ignore redundant calls */ { x->x_lastbroken = x->x_messcount; loud_warning(0, "import", "[%d] %s embedding broken by %s", x->x_messcount, x->x_emstate->s_name, cause); } } static int import_emcheck(t_port *x, t_symbol *state) { if (x->x_emstate == state) return (1); else if (x->x_emstate) import_embroken(x, state->s_name); else import_unexpected(x); return (0); } static void import_eminconsistent(t_port *x, t_symbol *state) { if (import_emcheck(x, state) && x->x_lastinconsistent < x->x_messcount) /* ignore redundant calls */ { x->x_lastinconsistent = x->x_messcount; loud_warning(0, "import", "[%d] %s embedding ended inconsistently", x->x_messcount, state->s_name); } } static int import_emcheckend(t_port *x, t_symbol *state, t_symbol *name) { if (import_emcheck(x, state)) { if (x->x_emcount /* empty ok for vtable, CHECKME other cases */ && x->x_emsize != x->x_emcount) loud_warning(0, "import", "[%d] corrupt %s (%d atoms declared, %d provided)", x->x_messcount, state->s_name, x->x_emsize, x->x_emcount); else { if (name != x->x_emname) /* warn and accept, LATER rethink */ import_eminconsistent(x, state); return (1); } } return (0); } static void import_emstart(t_port *x, t_symbol *state, t_symbol *name, int size) { if (x->x_emstate) import_embroken(x, state->s_name); x->x_emstate = state; binbuf_clear(x->x_embb); x->x_emname = name; x->x_emsize = size; x->x_emcount = 0; } static void import_emend(t_port *x, t_symbol *state, t_symbol *name) { import_emcheckend(x, state, name); x->x_emstate = 0; x->x_emname = 0; x->x_emsize = 0; x->x_emcount = 0; binbuf_clear(x->x_embb); } static void import_emflush(t_port *x, t_symbol *state, t_symbol *name) { int ac = binbuf_getnatom(x->x_embb); if (import_emcheckend(x, state, name) && ac) binbuf_add(x->x_outbb, ac, binbuf_getvec(x->x_embb)); x->x_emstate = 0; x->x_emname = 0; x->x_emsize = 0; x->x_emcount = 0; if (ac) binbuf_clear(x->x_embb); binbuf_addv(x->x_outbb, "ss;", gensym("#C"), gensym("restore")); } static int import_emcopy(t_port *x, t_symbol *state) { if (import_emcheck(x, state)) { t_atom *out = x->x_outmess; SETSYMBOL(out, gensym("#C")); out++; out = import_copyatoms(out, x->x_inmess + 1, x->x_inatoms - 1); SETSEMI(out); binbuf_add(x->x_embb, x->x_inatoms + 1, x->x_outmess); return (1); } else return (0); } static int import_emadd(t_port *x, t_symbol *state, int ac, t_atom *av) { if (import_emcheck(x, state)) { t_atom at; SETSYMBOL(&at, gensym("#C")); binbuf_add(x->x_embb, 1, &at); binbuf_add(x->x_embb, ac, av); binbuf_addsemi(x->x_embb); return (1); } else return (0); } static int import_emaddv(t_port *x, t_symbol *state, char *fmt, ...) { va_list ap; t_atom arg[64], *at = arg; int nargs = 0; char *fp = fmt; va_start(ap, fmt); SETSYMBOL(at, gensym("#C")); at++; nargs++; if (import_emcheck(x, state)) while (1) { switch(*fp++) { case 'i': SETFLOAT(at, va_arg(ap, t_int)); break; case 'f': SETFLOAT(at, va_arg(ap, double)); break; case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break; case ';': SETSEMI(at); break; case 0: goto done; default: nargs = 0; goto done; } at++; nargs++; } done: va_end(ap); if (nargs > 1) { binbuf_add(x->x_embb, nargs, arg); return (1); } else return (0); } static void import_addclassname(t_port *x, char *outname, t_atom *inatom) { t_atom at; if (outname) SETSYMBOL(&at, gensym(outname)); else { t_symbol *insym = 0; if (inatom->a_type == A_SYMBOL) { /* LATER bash inatom to lowercase (CHECKME first) */ insym = inatom->a_w.w_symbol; if (import_mapping && import_mapsize) { char **fromp = import_mapping, **top = import_mapping + 1; int cnt = import_mapsize; while (cnt--) { if (strcmp(*fromp, insym->s_name)) { fromp += 2; top += 2; } else { insym = gensym(*top); inatom = 0; break; } } } if (insym != &s_bang && insym != &s_float && insym != &s_symbol && insym != &s_list && (insym == portps_inlet || insym == portps_outlet || zgetfn(&pd_objectmaker, insym) == 0)) { x->x_withbogus = 1; SETSYMBOL(&at, portps_bogus); binbuf_add(x->x_outbb, 1, &at); } } if (inatom) import_copyatoms(&at, inatom, 1); else if (insym) SETSYMBOL(&at, insym); else { loudbug_bug("import_addclassname"); SETSYMBOL(&at, gensym("???")); } } binbuf_add(x->x_outbb, 1, &at); } static int import_obj(t_port *x, char *name) { int ndx = (x->x_inmess[1].a_w.w_symbol == gensym("user") ? 3 : 2); binbuf_addv(x->x_outbb, "ssff", gensym("#X"), gensym("obj"), port_getx(x, ndx), port_gety(x, ndx + 1)); import_addclassname(x, name, &x->x_inmess[ndx == 2 ? 6 : 2]); binbuf_addsemi(x->x_outbb); x->x_nobj++; return (PORT_NEXT); } static int import_objarg(t_port *x, char *name) { int ndx = (x->x_inmess[1].a_w.w_symbol == gensym("user") ? 3 : 2); if (x->x_inatoms > 6 || (ndx == 3 && x->x_inatoms > 4)) { t_atom *out = x->x_outmess; SETSYMBOL(out, gensym("#X")); out++; SETSYMBOL(out, gensym("obj")); out++; port_setxy(x, ndx, out); binbuf_add(x->x_outbb, 4, x->x_outmess); import_addclassname(x, name, &x->x_inmess[ndx == 2 ? 6 : 2]); out = import_copyatoms(x->x_outmess, x->x_inmess + 7, x->x_inatoms - 7); SETSEMI(out); binbuf_add(x->x_outbb, x->x_inatoms - 6, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } else return (PORT_CORRUPT); } static int imaction_N1_vpatcher(t_port *x, char *arg) { if (x->x_stackdepth >= x->x_stacksize) { int rqsz = x->x_stackdepth + 1; int sz = rqsz; x->x_stack = grow_withdata(&rqsz, &x->x_stackdepth, &x->x_stacksize, x->x_stack, PORT_INISTACK, x->x_stackini, sizeof(*x->x_stack)); if (rqsz != sz) { post("too many embedded patches"); return (PORT_FATAL); } } x->x_stack[x->x_stackdepth++] = x->x_nobj; x->x_nobj = 0; binbuf_addv(x->x_outbb, "ssfffff;", gensym("#N"), gensym("canvas"), port_getx(x, 2), port_gety(x, 3), (float)port_xstretch(port_getint(x, 4) - port_getint(x, 2)), (float)port_ystretch(port_getint(x, 5) - port_getint(x, 3)), PORT_DEFFONTSIZE); return (PORT_NEXT); } static int imaction_N1_vtable(t_port *x, char *arg) { int range = port_getint(x, 8), left = port_getint(x, 3), top = port_getint(x, 4), right = port_getint(x, 5), bottom = port_getint(x, 6), flags = port_getint(x, 7); import_emstart(x, portps_vtable, port_getsymbol(x, 9), port_getint(x, 2)); #ifdef PORT_DEBUG loudbug_post( "vtable \"%s\": size %d, range %d, coords %d %d %d %d, flags %d", x->x_emname->s_name, x->x_emsize, range, left, top, right, bottom, flags); #endif import_emaddv(x, portps_vtable, "si;", gensym("size"), x->x_emsize); import_emaddv(x, portps_vtable, "siiii;", gensym("flags"), /* CHECKED */ (flags & 16) != 0, (flags & 4) != 0, (flags & 8) != 0, (flags & 2) != 0); import_emaddv(x, portps_vtable, "si;", gensym("tabrange"), range); import_emaddv(x, portps_vtable, "siiiii;", gensym("_coords"), left, top, right, bottom, flags & 1); return (PORT_NEXT); } static int imaction_N1_coll(t_port *x, char *arg) { import_emstart(x, portps_coll, port_getsymbol(x, 2), 0); return (PORT_NEXT); } static int imaction_N1_funbuff(t_port *x, char *arg) { import_emstart(x, portps_funbuff, &s_, 0); import_emaddv(x, portps_funbuff, "si;", gensym("embed"), port_getint(x, 2) != 0); return (PORT_NEXT); } static int imaction_N1_prob(t_port *x, char *arg) { import_emstart(x, portps_prob, &s_, 0); return (PORT_NEXT); } static int imaction_N1_picture(t_port *x, char *arg) { import_emstart(x, portps_picture, 0, 0); if (x->x_pictfp) { import_unexpected(x); if (x->x_dumping) fclose(x->x_pictfp); x->x_pictfp = 0; } return (PORT_NEXT); } static int imaction_P6_patcher(t_port *x, char *arg) { if (x->x_withbogus) binbuf_addv(x->x_outbb, "ss;", portps_cleanup, portps_cleanup); binbuf_addv(x->x_outbb, "ssffss;", gensym("#X"), gensym("restore"), port_getx(x, 2), port_gety(x, 3), gensym("pd"), port_getsymbol(x, 7)); if (x->x_stackdepth) /* LATER consider returning PORT_FATAL otherwise */ x->x_stackdepth--; x->x_nobj = x->x_stack[x->x_stackdepth]; x->x_nobj++; return (PORT_NEXT); } static int imaction_P6_table(t_port *x, char *arg) { t_symbol *tablename = port_getsymbol(x, 7); binbuf_addv(x->x_outbb, "ssffs", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3), gensym("Table")); if (tablename != &s_) { t_atom at; SETSYMBOL(&at, tablename); binbuf_add(x->x_outbb, 1, &at); } binbuf_addsemi(x->x_outbb); import_emflush(x, portps_vtable, tablename); x->x_nobj++; return (PORT_NEXT); } static int imaction_P6_coll(t_port *x, char *arg) { t_symbol *collname = port_getsymbol(x, 7); binbuf_addv(x->x_outbb, "ssffs", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3), portps_coll); if (collname != &s_) { t_atom at; SETSYMBOL(&at, collname); binbuf_add(x->x_outbb, 1, &at); } binbuf_addsemi(x->x_outbb); import_emflush(x, portps_coll, collname); x->x_nobj++; return (PORT_NEXT); } static int imaction_P6_funbuff(t_port *x, char *arg) { binbuf_addv(x->x_outbb, "ssffs;", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3), portps_funbuff); import_emflush(x, portps_funbuff, &s_); x->x_nobj++; return (PORT_NEXT); } static int imaction_P6_prob(t_port *x, char *arg) { binbuf_addv(x->x_outbb, "ssffs;", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3), portps_prob); import_emflush(x, portps_prob, &s_); x->x_nobj++; return (PORT_NEXT); } /* LATER use hammer replacements */ static int imaction_P6_pack(t_port *x, char *arg) { int i; for (i = 7; i < x->x_inatoms; i++) { if (x->x_inmess[i].a_type == A_SYMBOL) { t_symbol *s = x->x_inmess[i].a_w.w_symbol; if (s->s_name[1]) { loud_warning(0, "import", "%s's argument '%s' bashed to 's'", port_getsymbol(x, 6)->s_name, s->s_name); x->x_inmess[i].a_w.w_symbol = gensym("s"); } else switch (*s->s_name) { case 'b': case 'f': case 's': case 'l': break; case 'i': x->x_inmess[i].a_w.w_symbol = gensym("f"); break; default: x->x_inmess[i].a_w.w_symbol = gensym("s"); } } } return (PORT_OK); } /* LATER consider using hammer replacements */ static int imaction_P6_midi(t_port *x, char *arg) { x->x_inatoms = 7; /* ugly, LATER rethink */ return (PORT_OK); } static int imaction_P2_scope(t_port *x, char *name) { if (x->x_inatoms > 6) { t_atom *out = x->x_outmess; int i, xpix, ypix; SETSYMBOL(out, gensym("#X")); out++; SETSYMBOL(out, gensym("obj")); out++; port_setxy(x, 3, out); xpix = (int)out++->a_w.w_float; ypix = (int)out->a_w.w_float; binbuf_add(x->x_outbb, 4, x->x_outmess); import_addclassname(x, name, &x->x_inmess[2]); out = x->x_outmess; port_setxy(x, 5, out); out++->a_w.w_float -= xpix; out++->a_w.w_float -= ypix; out = import_copyatoms(out, x->x_inmess + 7, x->x_inatoms - 7); SETSEMI(out); binbuf_add(x->x_outbb, x->x_inatoms - 4, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } else return (PORT_CORRUPT); } /* width fontsize fontfamily encoding fontprops red green blue text... */ static int imaction_P1_comment(t_port *x, char *arg) { int outatoms; SETSYMBOL(x->x_outmess, gensym("#X")); SETSYMBOL(x->x_outmess + 1, gensym("obj")); port_setxy(x, 2, x->x_outmess + 2); SETSYMBOL(x->x_outmess + 4, gensym("comment")); if (x->x_inatoms > 5) { int i, fontsize, fontprops; float width = port_getwidth(x, 4); t_atom *ap = x->x_inmess + 5; SETFLOAT(x->x_outmess + 5, width); if (ap->a_type == A_INT) { fontsize = ap->a_w.w_index & 0x0ff; fontprops = ap->a_w.w_index >> 8; } else if (ap->a_type == A_FLOAT) /* FIXME */ { fontsize = ((int)ap->a_w.w_float) & 0x0ff; fontprops = ((int)ap->a_w.w_float) >> 8; } else fontsize = 10, fontprops = 0; SETFLOAT(x->x_outmess + 6, fontsize); SETSYMBOL(x->x_outmess + 7, gensym("helvetica")); SETSYMBOL(x->x_outmess + 8, gensym("?")); SETFLOAT(x->x_outmess + 9, fontprops); SETFLOAT(x->x_outmess + 10, 0); SETFLOAT(x->x_outmess + 11, 0); SETFLOAT(x->x_outmess + 12, 0); outatoms = x->x_inatoms + 7; import_copyatoms(x->x_outmess + 13, x->x_inmess + 6, x->x_inatoms - 6); } else outatoms = 5; SETSEMI(x->x_outmess + outatoms); binbuf_add(x->x_outbb, outatoms + 1, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } static int imaction_P1_message(t_port *x, char *arg) { int i; t_atom *out; SETSYMBOL(x->x_outmess, gensym("#X")); SETSYMBOL(x->x_outmess + 1, gensym("msg")); port_setxy(x, 2, x->x_outmess + 2); out = import_copyatoms(x->x_outmess + 4, x->x_inmess + 6, x->x_inatoms - 6); SETSEMI(out); binbuf_add(x->x_outbb, x->x_inatoms - 1, x->x_outmess); x->x_nobj++; return (PORT_NEXT); } static int imaction_P1_io(t_port *x, char *arg) { binbuf_addv(x->x_outbb, "ssff", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3)); if (x->x_inmess[1].a_w.w_symbol == portps_inlet || x->x_inmess[1].a_w.w_symbol == portps_outlet) { t_atom at; SETSYMBOL(&at, portps_bogus); binbuf_add(x->x_outbb, 1, &at); } binbuf_add(x->x_outbb, 1, &x->x_inmess[1]); binbuf_addsemi(x->x_outbb); x->x_nobj++; return (PORT_NEXT); } static int imaction_P1_number(t_port *x, char *arg) { binbuf_addv(x->x_outbb, "ssff;", gensym("#X"), gensym("floatatom"), port_getx(x, 2), port_gety(x, 3)); x->x_nobj++; return (PORT_NEXT); } static int imaction_P1_vpicture(t_port *x, char *arg) { import_emend(x, portps_picture, 0); if (x->x_pictfp) { if (x->x_dumping) fclose(x->x_pictfp); x->x_pictfp = 0; } else import_unexpected(x); binbuf_addv(x->x_outbb, "ssffs;", gensym("#X"), gensym("obj"), port_getx(x, 2), port_gety(x, 3), gensym("vpicture")); x->x_nobj++; return (PORT_NEXT); } static int imaction_P1_connect(t_port *x, char *arg) { binbuf_addv(x->x_outbb, "ssiiii;", gensym("#X"), gensym("connect"), x->x_nobj - port_getint(x, 2) - 1, port_getint(x, 3), x->x_nobj - port_getint(x, 4) - 1, port_getint(x, 5)); return (PORT_NEXT); } static int imaction_T1_int(t_port *x, char *arg) { if (x->x_emstate == portps_coll) import_emcopy(x, portps_coll); else if (x->x_emstate == portps_prob) import_emcopy(x, portps_prob); else import_unexpected(x); return (PORT_NEXT); } static int imaction_T1_flags(t_port *x, char *arg) { import_emcopy(x, portps_coll); return (PORT_NEXT); } static int imaction_T1_set(t_port *x, char *arg) { if (x->x_emstate == portps_vtable) { if (import_emcopy(x, portps_vtable)) { int count = port_getint(x, 2); if (count != x->x_emcount) loud_warning(0, "import", "[%d] bad vtable chunk index %d (%d already taken)", x->x_messcount, count, x->x_emcount); x->x_emcount += x->x_inatoms - 3; } } else if (x->x_emstate == portps_funbuff) import_emcopy(x, portps_funbuff); else import_unexpected(x); return (PORT_NEXT); } static int imaction_T1_reset(t_port *x, char *arg) { import_emcopy(x, portps_prob); return (PORT_NEXT); } static int imaction_T1_embed(t_port *x, char *arg) { import_emcopy(x, portps_prob); return (PORT_NEXT); } static int imaction_K1_replace(t_port *x, char *arg) { if (x->x_pictfp) { import_unexpected(x); if (x->x_dumping) fclose(x->x_pictfp); x->x_pictfp = 0; } else if (import_emcheck(x, portps_picture)) { char buf[32]; x->x_emsize = port_getint(x, 2); x->x_emcount = 0; sprintf(buf, "port-%02d.pict", ++x->x_pictno); if (x->x_dumping) { if (x->x_pictfp = fopen(buf, "wb")) { int i; for (i = 0; i < 512; i++) fputc(0, x->x_pictfp); } } else x->x_pictfp = (FILE *)1; } return (PORT_NEXT); } static int imaction_K1_set(t_port *x, char *arg) { if (!x->x_pictfp) import_unexpected(x); else if (import_emcheck(x, portps_picture)) { int i, count = port_getint(x, 2); if (count != x->x_emcount) loud_warning(0, "import", "[%d] bad picture chunk index %d (%d already taken)", x->x_messcount, count, x->x_emcount); x->x_emcount += x->x_inatoms - 3; if (x->x_dumping) { for (i = 3; i < x->x_inatoms; i++) { int v = port_getint(x, i); fputc(v >> 24, x->x_pictfp); fputc((v >> 16) & 0x0ff, x->x_pictfp); fputc((v >> 8) & 0x0ff, x->x_pictfp); fputc(v & 0x0ff, x->x_pictfp); } } } return (PORT_NEXT); } typedef int (*t_portaction)(t_port *, char *arg); typedef struct _portslot { char *s_name; t_portaction s_action; char *s_actionarg; struct _portnode *s_subtree; t_symbol *s_symbol; } t_portslot; typedef struct _portnode /* a parser's symbol definition, sort of... */ { t_portslot *n_table; int n_nslots; int n_index; } t_portnode; #define PORT_NSLOTS(slots) (sizeof(slots)/sizeof(*(slots))) static t_portslot imslots__N[] = { { "vpatcher", imaction_N1_vpatcher, 0, 0, 0 }, { "vtable", imaction_N1_vtable, 0, 0, 0 }, { "coll", imaction_N1_coll, 0, 0, 0 }, { "funbuff", imaction_N1_funbuff, 0, 0, 0 }, { "prob", imaction_N1_prob, 0, 0, 0 }, { "picture", imaction_N1_picture, 0, 0, 0 } }; static t_portnode imnode__N = { imslots__N, PORT_NSLOTS(imslots__N), 1 }; static t_portslot imslots_newobj[] = { { "patcher", imaction_P6_patcher, 0, 0, 0 }, { "p", imaction_P6_patcher, 0, 0, 0 }, { "table", imaction_P6_table, 0, 0, 0 }, { "coll", imaction_P6_coll, 0, 0, 0 }, { "funbuff", imaction_P6_funbuff, 0, 0, 0 }, { "prob", imaction_P6_prob, 0, 0, 0 } }; static t_portnode imnode_newobj = { imslots_newobj, PORT_NSLOTS(imslots_newobj), 6 }; /* LATER consider merging newobj and newex */ static t_portslot imslots_newex[] = { { "key", import_obj, "Key", 0, 0 }, { "keyup", import_obj, "Keyup", 0, 0 }, { "pack", imaction_P6_pack, 0, 0, 0 }, { "unpack", imaction_P6_pack, 0, 0, 0 }, { "trigger", imaction_P6_pack, 0, 0, 0 }, { "t", imaction_P6_pack, 0, 0, 0 }, { "midiin", imaction_P6_midi, 0, 0, 0 }, { "midiout", imaction_P6_midi, 0, 0, 0 }, { "notein", imaction_P6_midi, 0, 0, 0 }, { "noteout", imaction_P6_midi, 0, 0, 0 }, { "pgmin", imaction_P6_midi, 0, 0, 0 }, { "pgmout", imaction_P6_midi, 0, 0, 0 }, { "ctlin", imaction_P6_midi, 0, 0, 0 }, { "ctlout", imaction_P6_midi, 0, 0, 0 }, { "bendin", imaction_P6_midi, 0, 0, 0 }, { "bendout", imaction_P6_midi, 0, 0, 0 }, /* LATER rethink */ { "Borax", import_objarg, "Borax", 0, 0 }, { "Bucket", import_objarg, "Bucket", 0, 0 }, { "Decode", import_objarg, "Decode", 0, 0 }, { "Histo", import_objarg, "Histo", 0, 0 }, { "MouseState", import_objarg, "MouseState", 0, 0 }, { "Peak", import_objarg, "Peak", 0, 0 }, { "TogEdge", import_objarg, "TogEdge", 0, 0 }, { "Trough", import_objarg, "Trough", 0, 0 }, { "Uzi", import_objarg, "Uzi", 0, 0 } }; static t_portnode imnode_newex = { imslots_newex, PORT_NSLOTS(imslots_newex), 6 }; static t_portslot imslots_user[] = { { "GSwitch", import_objarg, "Gswitch", 0, 0 }, { "GSwitch2", import_objarg, "Ggate", 0, 0 }, { "number~", import_obj, 0, 0, 0 }, { "scope~", imaction_P2_scope, "Scope~", 0, 0 }, { "uslider", import_obj, "vsl", 0, 0 } /* LATER range and offset */ }; static t_portnode imnode_user = { imslots_user, PORT_NSLOTS(imslots_user), 2 }; static t_portslot imslots__P[] = { { "comment", imaction_P1_comment, 0, 0, 0 }, { "message", imaction_P1_message, 0, 0, 0 }, { "newobj", import_objarg, 0, &imnode_newobj, 0 }, { "newex", import_objarg, 0, &imnode_newex, 0 }, { "inlet", imaction_P1_io, 0, 0, 0 }, { "inlet~", imaction_P1_io, 0, 0, 0 }, { "outlet", imaction_P1_io, 0, 0, 0 }, { "outlet~", imaction_P1_io, 0, 0, 0 }, { "number", imaction_P1_number, 0, 0, 0 }, { "flonum", imaction_P1_number, 0, 0, 0 }, { "button", import_obj, "bng", 0, 0 }, { "slider" , import_obj, "vsl", 0, 0 }, /* LATER range and offset */ { "hslider", import_obj, "hsl", 0, 0 }, /* LATER range and offset */ { "toggle", import_obj, "tgl", 0, 0 }, { "user", import_objarg, 0, &imnode_user, 0 }, /* state is embedded in #N vpreset ; #X append... */ { "preset", import_obj, "preset", 0, 0 }, /* an object created from the "Paste Picture" menu, state is embedded in #N picture; #K...; */ { "vpicture", imaction_P1_vpicture, 0, 0, 0 }, { "connect", imaction_P1_connect, 0, 0, 0 }, { "fasten", imaction_P1_connect, 0, 0, 0 } }; static t_portnode imnode__P = { imslots__P, PORT_NSLOTS(imslots__P), 1 }; static t_portslot imslots__T[] = { { "int", imaction_T1_int, 0, 0, 0 }, { "flags", imaction_T1_flags, 0, 0, 0 }, { "set", imaction_T1_set, 0, 0, 0 }, { "reset", imaction_T1_reset, 0, 0, 0 }, { "embed", imaction_T1_embed, 0, 0, 0 } }; static t_portnode imnode__T = { imslots__T, PORT_NSLOTS(imslots__T), 1 }; static t_portslot imslots__K[] = { { "replace", imaction_K1_replace, 0, 0, 0 }, { "set", imaction_K1_set, 0, 0, 0 } }; static t_portnode imnode__K = { imslots__K, PORT_NSLOTS(imslots__K), 1 }; static t_portslot imslots_[] = { { "#N", 0, 0, &imnode__N, 0 }, { "#P", 0, 0, &imnode__P, 0 }, { "#T", 0, 0, &imnode__T, 0 }, { "#K", 0, 0, &imnode__K, 0 } }; static t_portnode imnode_ = { imslots_, PORT_NSLOTS(imslots_), 0 }; static int port_doparse(t_port *x, t_portnode *node) { int nslots = node->n_nslots; if (nslots > 0) { t_portslot *slot = node->n_table; t_symbol *insym = port_getanysymbol(x, node->n_index); char *inname = 0; secondpass: while (nslots--) { if (slot->s_symbol == insym || (inname && shared_matchignorecase(inname, slot->s_name))) { if (slot->s_subtree) { int nobj = x->x_nobj; int result = port_doparse(x, slot->s_subtree); if (result == PORT_FATAL || result == PORT_CORRUPT || result == PORT_NEXT) return (result); } if (slot->s_action) return (slot->s_action(x, slot->s_actionarg)); else return (PORT_OK); /* LATER rethink */ } slot++; } if (!inname) { inname = insym->s_name; nslots = node->n_nslots; slot = node->n_table; goto secondpass; } } else loudbug_bug("port_doparse"); return (PORT_UNKNOWN); } static int port_parsemessage(t_port *x) { import_flushillegal(x); x->x_messcount++; return (port_doparse(x, &imnode_)); } static void port_startparsing(t_port *x) { #ifdef PORT_DEBUG loudbug_post("parsing..."); #endif x->x_messcount = 0; x->x_illmess = 0; x->x_lastunexpected = -1; x->x_lastbroken = -1; x->x_lastinconsistent = -1; x->x_nobj = 0; x->x_emstate = 0; binbuf_clear(x->x_embb); x->x_pictno = 0; x->x_pictfp = 0; } static void port_endparsing(t_port *x) { import_flushillegal(x); if (x->x_emstate) { import_embroken(x, "end of file"); x->x_emstate = 0; } binbuf_clear(x->x_embb); if (x->x_pictfp) { loud_warning(0, "import", "incomplete picture"); if (x->x_dumping) fclose(x->x_pictfp); x->x_pictfp = 0; } #ifdef PORT_DEBUG loudbug_post("end of parsing"); #endif } static void port_dochecksetup(t_portnode *node) { t_portslot *slots = node->n_table; int i, nslots = node->n_nslots; for (i = 0; i < nslots; i++) { t_portnode *subtree = slots[i].s_subtree; slots[i].s_symbol = gensym(slots[i].s_name); if (subtree) port_dochecksetup(subtree); } import_setdefmapping(); } #define BOGUS_NINLETS 23 #define BOGUS_NOUTLETS 24 typedef struct _bogus { t_object x_ob; t_glist *x_glist; /* used also as 'dirty' flag */ int x_bound; t_inlet *x_inlets[BOGUS_NINLETS]; t_outlet *x_outlets[BOGUS_NOUTLETS]; t_clock *x_clock; } t_bogus; typedef struct _bogushook { t_pd x_pd; t_pd *x_who; t_glist *x_glist; /* used also as 'dirty' flag */ t_clock *x_clock; } t_bogushook; static t_class *bogus_class; static t_class *bogushook_class; static void bogus_tick(t_bogus *x) { if (x->x_bound) { #ifdef PORT_DEBUG loudbug_post("bogus_tick: unbinding '%x'", (int)x); #endif pd_unbind((t_pd *)x, portps_cleanup); x->x_bound = 0; } } static void bogushook_tick(t_bogushook *x) { pd_free((t_pd *)x); } static void bogus_cleanup(t_bogus *x) { if (x->x_glist && x->x_glist == canvas_getcurrent()) { t_text *t = (t_text *)x; int ac = binbuf_getnatom(t->te_binbuf); if (ac) { t_atom *av = binbuf_getvec(t->te_binbuf); t_binbuf *bb = binbuf_new(); t_inlet **ip; t_outlet **op; int i; #ifdef PORT_DEBUG loudbug_startpost("self-adjusting "); loudbug_postbinbuf(t->te_binbuf); #endif binbuf_add(bb, ac - 1, av + 1); binbuf_free(t->te_binbuf); t->te_binbuf = bb; for (i = BOGUS_NINLETS, ip = x->x_inlets + BOGUS_NINLETS - 1; i ; i--, ip--) { if (forky_hasfeeders((t_object *)x, x->x_glist, i, 0)) break; else inlet_free(*ip); } #ifdef PORT_DEBUG loudbug_post("%d inlets deleted", BOGUS_NINLETS - i); #endif for (i = 0, op = x->x_outlets + BOGUS_NOUTLETS - 1; i < BOGUS_NOUTLETS; i++, op--) { if (fragile_outlet_connections(*op)) break; else outlet_free(*op); } #ifdef PORT_DEBUG loudbug_post("%d outlets deleted", i); #endif glist_retext(x->x_glist, t); } else loudbug_bug("bogus_cleanup"); x->x_glist = 0; clock_delay(x->x_clock, 0); } } static void bogus_free(t_bogus *x) { if (x->x_bound) pd_unbind((t_pd *)x, portps_cleanup); if (x->x_clock) clock_free(x->x_clock); } static void *bogus_new(t_symbol *s, int ac, t_atom *av) { t_bogus *x = 0; t_glist *glist; if (glist = canvas_getcurrent()) { char buf[80]; int i; if (av->a_type == A_SYMBOL) { t_pd *z; if (z = forky_newobject(av->a_w.w_symbol, ac - 1, av + 1)) { t_bogushook *y = (t_bogushook *)pd_new(bogushook_class); y->x_who = z; y->x_glist = glist; pd_bind((t_pd *)y, portps_cleanup); y->x_clock = clock_new(y, (t_method)bogushook_tick); #ifdef PORT_DEBUG loudbug_post("reclaiming %s", av->a_w.w_symbol->s_name); #endif return (z); } } x = (t_bogus *)pd_new(bogus_class); atom_string(av, buf, 80); loud_error((t_pd *)x, "unknown class '%s'", buf); x->x_glist = glist; for (i = 0; i < BOGUS_NINLETS; i++) x->x_inlets[i] = inlet_new((t_object *)x, (t_pd *)x, 0, 0); for (i = 0; i < BOGUS_NOUTLETS; i++) x->x_outlets[i] = outlet_new((t_object *)x, &s_anything); pd_bind((t_pd *)x, portps_cleanup); x->x_bound = 1; x->x_clock = clock_new(x, (t_method)bogus_tick); } return (x); } static void bogushook_cleanup(t_bogushook *x) { if (x->x_glist) { t_text *t = (t_text *)x->x_who; int ac = binbuf_getnatom(t->te_binbuf); if (ac > 1) { int dorecreate = 0; t_atom *av = binbuf_getvec(t->te_binbuf); t_binbuf *bb = binbuf_new(); #ifdef PORT_DEBUG loudbug_startpost("hook-adjusting "); loudbug_postbinbuf(t->te_binbuf); #endif ac--; av++; if (av->a_type == A_SYMBOL) { if (av->a_w.w_symbol == portps_outlet) { if (forky_hasfeeders((t_object *)x->x_who, x->x_glist, 0, &s_signal)) { t_atom at; SETSYMBOL(&at, gensym("outlet~")); binbuf_add(bb, 1, &at); ac--; av++; dorecreate = 1; } } else if (av->a_w.w_symbol == portps_inlet) { /* LATER */ } } if (ac) binbuf_add(bb, ac, av); if (dorecreate) gobj_recreate(x->x_glist, (t_gobj *)t, bb); else { binbuf_free(t->te_binbuf); t->te_binbuf = bb; glist_retext(x->x_glist, t); } } else loudbug_bug("bogushook_cleanup"); x->x_glist = 0; clock_delay(x->x_clock, 0); } } static void bogushook_free(t_bogushook *x) { #ifdef PORT_DEBUG loudbug_post("destroing the hook of '%s'", class_getname(*x->x_who)); #endif pd_unbind((t_pd *)x, portps_cleanup); if (x->x_clock) clock_free(x->x_clock); } static void port_checksetup(void) { static int done = 0; if (!done) { port_dochecksetup(&imnode_); portps_bogus = gensym("_port.bogus"); portps_cleanup = gensym("_port.cleanup"); portps_inlet = gensym("inlet"); portps_outlet = gensym("outlet"); portps_vtable = gensym("vtable"); portps_coll = gensym("coll"); portps_funbuff = gensym("funbuff"); portps_prob = gensym("prob"); portps_picture = gensym("picture"); if (zgetfn(&pd_objectmaker, portps_bogus) == 0) { bogus_class = class_new(portps_bogus, (t_newmethod)bogus_new, (t_method)bogus_free, sizeof(t_bogus), 0, A_GIMME, 0); class_addmethod(bogus_class, (t_method)bogus_cleanup, portps_cleanup, 0); bogushook_class = class_new(gensym("_port.bogushook"), 0, (t_method)bogushook_free, sizeof(t_bogushook), CLASS_PD, 0); class_addmethod(bogushook_class, (t_method)bogushook_cleanup, portps_cleanup, 0); } done = 1; } } static t_port *port_new(void) { t_port *x = (t_port *)getbytes(sizeof(*x)); x->x_outbb = 0; x->x_withbogus = 0; x->x_outsize = PORT_INISIZE; x->x_outatoms = 0; x->x_outmess = x->x_outini; x->x_stacksize = PORT_INISTACK; x->x_stackdepth = 0; x->x_stack = x->x_stackini; x->x_emstate = 0; x->x_embb = binbuf_new(); #ifdef PORT_DUMP x->x_dumping = 1; #else x->x_dumping = 0; #endif return (x); } static void port_free(t_port *x) { if (portps_cleanup->s_thing) { /* clean up toplevel glist */ typedmess(portps_cleanup->s_thing, portps_cleanup, 0, 0); /* LATER unbind all bogus objects, and destroy all bogushooks by traversing the portps_cleanup's bindlist, instead of using per-object clocks. Need to have bindlist traversal in Pd API first... Otherwise, consider fragilizing this (and fragilizing grab too). */ } if (x->x_outmess != x->x_outini) freebytes(x->x_outmess, x->x_outsize * sizeof(*x->x_outmess)); if (x->x_stack != x->x_stackini) freebytes(x->x_stack, x->x_stacksize * sizeof(*x->x_stack)); if (x->x_embb) binbuf_free(x->x_embb); freebytes(x, sizeof(*x)); } static int import_binbuf(t_port *x, t_binbuf *inbb, t_binbuf *outbb) { int result = PORT_OK; t_atom *av = binbuf_getvec(inbb); int ac = binbuf_getnatom(inbb); int startmess, endmess; x->x_outbb = outbb; port_startparsing(x); for (startmess = 0; startmess < ac; startmess = endmess + 1) { t_atom *mess = av + startmess, *ap; int i; for (endmess = startmess, ap = mess; ap->a_type != A_SEMI; endmess++, ap++) if (endmess == ac) { result = PORT_CORRUPT; /* no final semi */ goto endparsing; } if (endmess == startmess || endmess == startmess + 1 || mess->a_type != A_SYMBOL) { startmess = endmess + 1; import_illegal(x); continue; } if (mess[1].a_type != A_SYMBOL) { if (mess[1].a_type != A_INT && mess[1].a_type != A_FLOAT) { startmess = endmess + 1; import_illegal(x); continue; } } else if (mess[1].a_w.w_symbol == gensym("hidden")) { t_symbol *sel = mess[1].a_w.w_symbol; mess[1].a_w.w_symbol = mess->a_w.w_symbol; startmess++; mess++; if (endmess == startmess + 1 || mess[1].a_type != A_SYMBOL) { startmess = endmess + 1; import_illegal(x); continue; } } x->x_inatoms = endmess - startmess; x->x_inmess = mess; if ((i = x->x_inatoms + 16) > x->x_outsize) /* LATER rethink */ { int sz = i; x->x_outmess = grow_nodata(&sz, &x->x_outsize, x->x_outmess, PORT_INISIZE, x->x_outini, sizeof(*x->x_outmess)); if (sz != i) { startmess = endmess + 1; continue; /* LATER rethink */ } } /* dollar signs in file translate to symbols, LATER rethink, also #-signs */ for (i = 0, ap = x->x_inmess; i < x->x_inatoms; i++, ap++) { if (ap->a_type == A_DOLLAR) { char buf[100]; sprintf(buf, "$%d", ap->a_w.w_index); SETSYMBOL(ap, gensym(buf)); } else if (ap->a_type == A_DOLLSYM) { char buf[100]; sprintf(buf, "$%s", ap->a_w.w_symbol->s_name); SETSYMBOL(ap, gensym(buf)); } } if (port_parsemessage(x) == PORT_FATAL) { result = PORT_FATAL; goto endparsing; } } endparsing: port_endparsing(x); return (result); } int import_max(char *fn, char *dir) { int result; t_port *x; t_binbuf *inbb, *outbb; int fd; char buf[MAXPDSTRING], *bufp; t_pd *stackp = 0; int dspstate = canvas_suspend_dsp(); port_checksetup(); if ((fd = open_via_path(dir, fn, "", buf, &bufp, MAXPDSTRING, 0)) < 0) { loud_error(0, "%s: can't open", fn); return (BINPORT_NOFILE); } else close (fd); x = port_new(); inbb = binbuf_new(); glob_setfilename(0, gensym(bufp), gensym(buf)); result = binport_read(inbb, bufp, buf); if (result == BINPORT_MAXBINARY || result == BINPORT_MAXTEXT || result == BINPORT_MAXOLD) { int bbresult; #ifdef PORT_DEBUG binport_write(inbb, "import-debug.pat", ""); #endif outbb = binbuf_new(); if ((bbresult = import_binbuf(x, inbb, outbb)) != PORT_OK) { loud_error(0, "%s: import failed (%d)", fn, bbresult); if (bbresult == PORT_CORRUPT) result = BINPORT_CORRUPT; else result = BINPORT_FAILED; binbuf_free(outbb); outbb = 0; } binbuf_free(inbb); #ifdef PORT_LOG if (outbb) binbuf_write(outbb, "import-result.pd", "", 0); #endif } else if (result == BINPORT_PDFILE) outbb = inbb; else { perror(fn); /* FIXME */ binbuf_free(inbb); outbb = 0; } if (outbb) { binbuf_eval(outbb, 0, 0, 0); binbuf_free(outbb); } port_free(x); glob_setfilename(0, &s_, &s_); canvas_resume_dsp(dspstate); while ((stackp != s__X.s_thing) && (stackp = s__X.s_thing)) vmess(stackp, gensym("pop"), "i", 1); #if 0 /* LATER */ pd_doloadbang(); #endif return (result); } cyclone-0.1-alpha55/shared/common/os.h0000644000076500007650000000145711466617452016274 0ustar hanshans/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #ifndef __OS_H__ #define __OS_H__ EXTERN_STRUCT _osdir; #define t_osdir struct _osdir #define OSDIR_FILEMODE 1 #define OSDIR_DIRMODE 2 int ospath_length(char *path, char *cwd); char *ospath_absolute(char *path, char *cwd, char *result); FILE *fileread_open(char *filename, t_canvas *cv, int textmode); FILE *filewrite_open(char *filename, t_canvas *cv, int textmode); t_osdir *osdir_open(char *dirname); void osdir_setmode(t_osdir *dp, int flags); void osdir_close(t_osdir *dp); void osdir_rewind(t_osdir *dp); char *osdir_next(t_osdir *dp); int osdir_isfile(t_osdir *dp); int osdir_isdir(t_osdir *dp); #endif cyclone-0.1-alpha55/ViCious/0000755000076500007650000000000011466617442014315 5ustar hanshanscyclone-0.1-alpha55/ViCious/cyclone/0000755000076500007650000000000011466617442015751 5ustar hanshanscyclone-0.1-alpha55/ViCious/cyclone/makefile0000644000076500007650000000466411466617442017463 0ustar hanshanscurrent: cyclone .SUFFIXES: .dll .obj ROOTDIR = ..\..\.. SRCDIR = $(ROOTDIR)\miXed\cyclone BINDIR = $(ROOTDIR)\miXed\bin SHAREDDIR = $(ROOTDIR)\miXed\shared EXTDIR = e:\PureData\externals PDDIR = e:\PureData\pd VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ $(VCLIBDIR)\wsock32.lib \ $(VCLIBDIR)\kernel32.lib \ $(VCLIBDIR)\uuid.lib \ $(PDDIR)\bin\pd.lib !INCLUDE objects !INCLUDE snapfiles !INCLUDE $(SRCDIR)\build_counter cyclone: cyclone.dll hammer.dll sickle.dll dummies.dll maxmode.dll cyclist.exe @cd $(ROOTDIR) @$(ZIPCOMMAND) cyclone-$(CYCLONE_SNAPSHOT)-dll.zip $(SNAPFILES) cyclone.dll: $(CYCLONE_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) hammer.dll: $(HAMMER_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) sickle.dll: $(SICKLE_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) dummies.dll: $(DUMMIES_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) maxmode.dll: $(MAXMODE_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) cyclist.exe: $(SHAREDDIR)\common\binport.c \ $(SHAREDDIR)\common\lex.c $(SHAREDDIR)\unstable\standalone.c -del /S $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\lex.obj $(SHAREDDIR)\unstable\standalone.obj -cl $(CFLAGS) $(INCLUDES) /DMIXED_STANDALONE /o $@ \ $(VCLIBDIR)\libc.lib $(SHAREDDIR)\common\binport.c \ $(SHAREDDIR)\common\lex.c $(SHAREDDIR)\unstable\standalone.c -@move $@ $(BINDIR) -del /S binport.obj lex.obj standalone.obj .c.obj: ; cl /c $(CFLAGS) $(INCLUDES) /Fo$*.obj $*.c clean: for %1 in (hammer shadow sickle) \ do del %1\*.obj for %1 in (hammer shadow sickle) \ do del %1\*.exp for %1 in (hammer shadow sickle) \ do del %1\*.lib for %1 in (hammer shadow sickle) \ do del %1\*.dll cyclone-0.1-alpha55/ViCious/cyclone/objects0000644000076500007650000001653411466617442017336 0ustar hanshansCYCLONE_OBJECTS = \ $(SRCDIR)\shadow\cyclone.obj \ $(SRCDIR)\shadow\nettles.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\common\lex.obj \ $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\port.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\sickle\sic.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\unstable\fragile.obj \ $(SHAREDDIR)\unstable\fringe.obj \ $(SHAREDDIR)\unstable\loader.obj ALL_HAMMERS = \ $(SRCDIR)\hammer\testmess.obj \ $(SRCDIR)\hammer\accum.obj \ $(SRCDIR)\hammer\acos.obj \ $(SRCDIR)\hammer\active.obj \ $(SRCDIR)\hammer\anal.obj \ $(SRCDIR)\hammer\Append.obj \ $(SRCDIR)\hammer\asin.obj \ $(SRCDIR)\hammer\bangbang.obj \ $(SRCDIR)\hammer\bondo.obj \ $(SRCDIR)\hammer\Borax.obj \ $(SRCDIR)\hammer\Bucket.obj \ $(SRCDIR)\hammer\buddy.obj \ $(SRCDIR)\hammer\capture.obj \ $(SRCDIR)\hammer\cartopol.obj \ $(SRCDIR)\hammer\Clip.obj \ $(SRCDIR)\hammer\coll.obj \ $(SRCDIR)\hammer\comment.obj \ $(SRCDIR)\hammer\cosh.obj \ $(SRCDIR)\hammer\counter.obj \ $(SRCDIR)\hammer\cycle.obj \ $(SRCDIR)\hammer\decide.obj \ $(SRCDIR)\hammer\Decode.obj \ $(SRCDIR)\hammer\drunk.obj \ $(SRCDIR)\hammer\flush.obj \ $(SRCDIR)\hammer\forward.obj \ $(SRCDIR)\hammer\fromsymbol.obj \ $(SRCDIR)\hammer\funbuff.obj \ $(SRCDIR)\hammer\funnel.obj \ $(SRCDIR)\hammer\gate.obj \ $(SRCDIR)\hammer\grab.obj \ $(SRCDIR)\hammer\Histo.obj \ $(SRCDIR)\hammer\iter.obj \ $(SRCDIR)\hammer\match.obj \ $(SRCDIR)\hammer\maximum.obj \ $(SRCDIR)\hammer\mean.obj \ $(SRCDIR)\hammer\midiflush.obj \ $(SRCDIR)\hammer\midiformat.obj \ $(SRCDIR)\hammer\midiparse.obj \ $(SRCDIR)\hammer\minimum.obj \ $(SRCDIR)\hammer\mousefilter.obj \ $(SRCDIR)\hammer\MouseState.obj \ $(SRCDIR)\hammer\mtr.obj \ $(SRCDIR)\hammer\next.obj \ $(SRCDIR)\hammer\offer.obj \ $(SRCDIR)\hammer\onebang.obj \ $(SRCDIR)\hammer\past.obj \ $(SRCDIR)\hammer\Peak.obj \ $(SRCDIR)\hammer\poltocar.obj \ $(SRCDIR)\hammer\prepend.obj \ $(SRCDIR)\hammer\prob.obj \ $(SRCDIR)\hammer\pv.obj \ $(SRCDIR)\hammer\seq.obj \ $(SRCDIR)\hammer\sinh.obj \ $(SRCDIR)\hammer\speedlim.obj \ $(SRCDIR)\hammer\spell.obj \ $(SRCDIR)\hammer\split.obj \ $(SRCDIR)\hammer\spray.obj \ $(SRCDIR)\hammer\sprintf.obj \ $(SRCDIR)\hammer\substitute.obj \ $(SRCDIR)\hammer\sustain.obj \ $(SRCDIR)\hammer\switch.obj \ $(SRCDIR)\hammer\Table.obj \ $(SRCDIR)\hammer\tanh.obj \ $(SRCDIR)\hammer\thresh.obj \ $(SRCDIR)\hammer\TogEdge.obj \ $(SRCDIR)\hammer\tosymbol.obj \ $(SRCDIR)\hammer\Trough.obj \ $(SRCDIR)\hammer\universal.obj \ $(SRCDIR)\hammer\urn.obj \ $(SRCDIR)\hammer\Uzi.obj \ $(SRCDIR)\hammer\xbendin.obj \ $(SRCDIR)\hammer\xbendin2.obj \ $(SRCDIR)\hammer\xbendout.obj \ $(SRCDIR)\hammer\xbendout2.obj \ $(SRCDIR)\hammer\xnotein.obj \ $(SRCDIR)\hammer\xnoteout.obj \ $(SRCDIR)\hammer\zl.obj HAMMER_OBJECTS = $(ALL_HAMMERS) \ $(SRCDIR)\hammer\hammer.obj \ $(SRCDIR)\hammer\allhammers.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\common\fitter.obj \ $(SHAREDDIR)\common\rand.obj \ $(SHAREDDIR)\common\vefl.obj \ $(SHAREDDIR)\common\mifi.obj \ $(SHAREDDIR)\common\lex.obj \ $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\port.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\hammer\gui.obj \ $(SHAREDDIR)\hammer\tree.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\unstable\fragile.obj \ $(SHAREDDIR)\unstable\fringe.obj ALL_SICKLES = \ $(SRCDIR)\sickle\abs.obj \ $(SRCDIR)\sickle\acos.obj \ $(SRCDIR)\sickle\acosh.obj \ $(SRCDIR)\sickle\allpass.obj \ $(SRCDIR)\sickle\asin.obj \ $(SRCDIR)\sickle\asinh.obj \ $(SRCDIR)\sickle\atan.obj \ $(SRCDIR)\sickle\atan2.obj \ $(SRCDIR)\sickle\atanh.obj \ $(SRCDIR)\sickle\average.obj \ $(SRCDIR)\sickle\avg.obj \ $(SRCDIR)\sickle\bitand.obj \ $(SRCDIR)\sickle\bitnot.obj \ $(SRCDIR)\sickle\bitor.obj \ $(SRCDIR)\sickle\bitshift.obj \ $(SRCDIR)\sickle\bitxor.obj \ $(SRCDIR)\sickle\buffir.obj \ $(SRCDIR)\sickle\capture.obj \ $(SRCDIR)\sickle\cartopol.obj \ $(SRCDIR)\sickle\change.obj \ $(SRCDIR)\sickle\click.obj \ $(SRCDIR)\sickle\Clip.obj \ $(SRCDIR)\sickle\comb.obj \ $(SRCDIR)\sickle\cosh.obj \ $(SRCDIR)\sickle\cosx.obj \ $(SRCDIR)\sickle\count.obj \ $(SRCDIR)\sickle\curve.obj \ $(SRCDIR)\sickle\cycle.obj \ $(SRCDIR)\sickle\delay.obj \ $(SRCDIR)\sickle\delta.obj \ $(SRCDIR)\sickle\deltaclip.obj \ $(SRCDIR)\sickle\edge.obj \ $(SRCDIR)\sickle\frameaccum.obj \ $(SRCDIR)\sickle\framedelta.obj \ $(SRCDIR)\sickle\index.obj \ $(SRCDIR)\sickle\kink.obj \ $(SRCDIR)\sickle\Line.obj \ $(SRCDIR)\sickle\linedrive.obj \ $(SRCDIR)\sickle\log.obj \ $(SRCDIR)\sickle\lookup.obj \ $(SRCDIR)\sickle\lores.obj \ $(SRCDIR)\sickle\matrix.obj \ $(SRCDIR)\sickle\maximum.obj \ $(SRCDIR)\sickle\minimum.obj \ $(SRCDIR)\sickle\minmax.obj \ $(SRCDIR)\sickle\mstosamps.obj \ $(SRCDIR)\sickle\onepole.obj \ $(SRCDIR)\sickle\overdrive.obj \ $(SRCDIR)\sickle\peakamp.obj \ $(SRCDIR)\sickle\peek.obj \ $(SRCDIR)\sickle\phasewrap.obj \ $(SRCDIR)\sickle\pink.obj \ $(SRCDIR)\sickle\play.obj \ $(SRCDIR)\sickle\poke.obj \ $(SRCDIR)\sickle\poltocar.obj \ $(SRCDIR)\sickle\pong.obj \ $(SRCDIR)\sickle\pow.obj \ $(SRCDIR)\sickle\rand.obj \ $(SRCDIR)\sickle\rampsmooth.obj \ $(SRCDIR)\sickle\record.obj \ $(SRCDIR)\sickle\reson.obj \ $(SRCDIR)\sickle\sah.obj \ $(SRCDIR)\sickle\sampstoms.obj \ $(SRCDIR)\sickle\Scope.obj \ $(SRCDIR)\sickle\sinh.obj \ $(SRCDIR)\sickle\sinx.obj \ $(SRCDIR)\sickle\slide.obj \ $(SRCDIR)\sickle\Snapshot.obj \ $(SRCDIR)\sickle\spike.obj \ $(SRCDIR)\sickle\svf.obj \ $(SRCDIR)\sickle\tanh.obj \ $(SRCDIR)\sickle\tanx.obj \ $(SRCDIR)\sickle\train.obj \ $(SRCDIR)\sickle\trapezoid.obj \ $(SRCDIR)\sickle\triangle.obj \ $(SRCDIR)\sickle\vectral.obj \ $(SRCDIR)\sickle\wave.obj \ $(SRCDIR)\sickle\zerox.obj SICKLE_OBJECTS = $(ALL_SICKLES) \ $(SRCDIR)\sickle\sickle.obj \ $(SRCDIR)\sickle\allsickles.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\common\fitter.obj \ $(SHAREDDIR)\common\vefl.obj \ $(SHAREDDIR)\common\clc.obj \ $(SHAREDDIR)\common\lex.obj \ $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\port.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\sickle\sic.obj \ $(SHAREDDIR)\sickle\arsic.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\unstable\fragile.obj \ $(SHAREDDIR)\unstable\fringe.obj DUMMIES_OBJECTS = \ $(SRCDIR)\shadow\dummies.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\lex.obj \ $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\port.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\unstable\fragile.obj \ $(SHAREDDIR)\unstable\fringe.obj MAXMODE_OBJECTS = \ $(SRCDIR)\shadow\maxmode.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\common\fitter.obj \ $(SHAREDDIR)\common\lex.obj \ $(SHAREDDIR)\common\binport.obj \ $(SHAREDDIR)\common\port.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\unstable\fragile.obj \ $(SHAREDDIR)\unstable\fringe.obj \ $(SHAREDDIR)\unstable\loader.obj cyclone-0.1-alpha55/ViCious/cyclone/snapfiles0000644000076500007650000000101211466617442017652 0ustar hanshansSNAPFILES = \ miXed\bin\cyclone.dll \ miXed\bin\hammer.dll \ miXed\bin\sickle.dll \ miXed\bin\dummies.dll \ miXed\bin\maxmode.dll \ miXed\bin\cyclist.exe \ miXed\bin\Append-help.pd \ miXed\bin\Clip-help.pd \ miXed\bin\Clip~-help.pd \ miXed\bin\Line~-help.pd \ miXed\bin\Scope~-help.pd \ miXed\bin\Snapshot~-help.pd \ miXed\bin\Table-help.pd \ miXed\ViCious\cyclone\makefile \ miXed\ViCious\cyclone\objects \ miXed\ViCious\cyclone\snapfiles \ miXed\LICENSE.txt \ miXed\test\cyclone\*.* cyclone-0.1-alpha55/ViCious/notes.txt0000644000076500007650000000037111466617442016207 0ustar hanshansTODO for ViCious * use a newer default compiler than 6.0 * conditionally use posix features (float versions of math calls, dirent) DONE for ViCious with cyclone alpha55 * /O2 added to all makefiles (why was it not there in the first place?) cyclone-0.1-alpha55/ViCious/pddp/0000755000076500007650000000000011466617442015244 5ustar hanshanscyclone-0.1-alpha55/ViCious/pddp/makefile0000644000076500007650000000246711466617442016755 0ustar hanshanscurrent: pddp .SUFFIXES: .dll .obj ROOTDIR = ..\..\.. SRCDIR = $(ROOTDIR)\miXed\pddp BINDIR = $(ROOTDIR)\miXed\bin SHAREDDIR = $(ROOTDIR)\miXed\shared EXTDIR = e:\PureData\externals PDDIR = e:\PureData\pd VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ $(VCLIBDIR)\wsock32.lib \ $(VCLIBDIR)\kernel32.lib \ $(VCLIBDIR)\uuid.lib \ $(PDDIR)\bin\pd.lib !INCLUDE objects !INCLUDE snapfiles !INCLUDE $(SRCDIR)\build_counter pddp: pddpboot pddplink.dll @cd $(ROOTDIR) @$(ZIPCOMMAND) pddp-$(PDDP_SNAPSHOT)-dll.zip $(SNAPFILES) pddpboot: -@copy $(SRCDIR)\pddpboot.tcl $(EXTDIR) -@copy $(SRCDIR)\pddpclient.tcl $(EXTDIR) -@copy $(SRCDIR)\pddpserver.tcl $(EXTDIR) -@copy $(SRCDIR)\pddpboot.tcl $(BINDIR) -@copy $(SRCDIR)\pddpclient.tcl $(BINDIR) -@copy $(SRCDIR)\pddpserver.tcl $(BINDIR) pddplink.dll: $(PDDPLINK_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) .c.obj: ; cl /c $(CFLAGS) $(INCLUDES) /Fo$*.obj $*.c clean: del *.obj del *.exp del *.lib del *.dll cyclone-0.1-alpha55/ViCious/pddp/objects0000644000076500007650000000015311466617442016617 0ustar hanshansPDDPLINK_OBJECTS = $(SRCDIR)\pddplink.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\os.obj cyclone-0.1-alpha55/ViCious/pddp/snapfiles0000644000076500007650000000041311466617442017151 0ustar hanshansSNAPFILES = \ miXed\bin\pddplink.dll \ miXed\bin\pddpboot.tcl \ miXed\bin\pddpclient.tcl \ miXed\bin\pddpserver.tcl \ miXed\ViCious\pddp\makefile \ miXed\ViCious\pddp\objects \ miXed\ViCious\pddp\snapfiles \ miXed\LICENSE.txt \ miXed\test\pddp\*.* cyclone-0.1-alpha55/ViCious/toxy/0000755000076500007650000000000011466617442015320 5ustar hanshanscyclone-0.1-alpha55/ViCious/toxy/makefile0000644000076500007650000000260111466617442017017 0ustar hanshanscurrent: toxy .SUFFIXES: .dll .obj ROOTDIR = ..\..\.. SRCDIR = $(ROOTDIR)\miXed\toxy BINDIR = $(ROOTDIR)\miXed\bin SHAREDDIR = $(ROOTDIR)\miXed\shared EXTDIR = e:\PureData\externals PDDIR = e:\PureData\pd VCLIBDIR = "e:\Program Files\Microsoft Visual Studio\Vc98\lib" ZIPCOMMAND = d:\dosowe\arc\info-zip\zip INCLUDES = /I. /I$(SHAREDDIR) /I$(PDDIR)\src CFLAGS = /O2 /W3 /WX /DNT /DMSW /DPD /nologo LIBS = $(VCLIBDIR)\libc.lib \ $(VCLIBDIR)\oldnames.lib \ $(VCLIBDIR)\wsock32.lib \ $(VCLIBDIR)\kernel32.lib \ $(VCLIBDIR)\uuid.lib \ $(PDDIR)\bin\pd.lib !INCLUDE objects !INCLUDE snapfiles !INCLUDE $(SRCDIR)\build_counter toxy: tot.dll tow.dll widget.dll @cd $(ROOTDIR) @$(ZIPCOMMAND) toxy-$(TOXY_SNAPSHOT)-dll.zip $(SNAPFILES) tot.dll: $(TOT_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) tow.dll: $(TOW_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) widget.dll: $(WIDGET_OBJECTS) -link /dll /out:$@ $(LIBS) $** /export:$(@:.dll=_setup) -@copy $@ $(EXTDIR) -@move $@ $(BINDIR) -del $(@:.dll=.exp) -del $(@:.dll=.lib) .c.obj: ; cl /c $(CFLAGS) $(INCLUDES) /Fo$*.obj $*.c clean: del *.obj del *.exp del *.lib del *.dll cyclone-0.1-alpha55/ViCious/toxy/objects0000644000076500007650000000141211466617442016672 0ustar hanshansTOT_OBJECTS = $(SRCDIR)\tot.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\hammer\gui.obj \ $(SHAREDDIR)\common\props.obj \ $(SHAREDDIR)\toxy\scriptlet.obj TOW_OBJECTS = $(SRCDIR)\tow.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\unstable\loader.obj WIDGET_OBJECTS = $(SRCDIR)\widget.obj \ $(SRCDIR)\widgettype.obj \ $(SRCDIR)\widgethandlers.obj \ $(SHAREDDIR)\unstable\forky.obj \ $(SHAREDDIR)\common\loud.obj \ $(SHAREDDIR)\common\grow.obj \ $(SHAREDDIR)\common\dict.obj \ $(SHAREDDIR)\common\os.obj \ $(SHAREDDIR)\hammer\file.obj \ $(SHAREDDIR)\common\props.obj \ $(SHAREDDIR)\toxy\scriptlet.obj cyclone-0.1-alpha55/ViCious/toxy/snapfiles0000644000076500007650000000043711466617442017233 0ustar hanshansSNAPFILES = \ miXed\bin\tot.dll \ miXed\bin\tow.dll \ miXed\bin\widget.dll \ miXed\ViCious\toxy\makefile \ miXed\ViCious\toxy\objects \ miXed\ViCious\toxy\snapfiles \ miXed\LICENSE.txt \ miXed\test\toxy\*.* \ miXed\test\toxy\editors\*.* \ miXed\test\toxy\stress\*.* cyclone-0.1-alpha55/cyclone/0000755000076500007650000000000011466617447014375 5ustar hanshanscyclone-0.1-alpha55/cyclone/build_counter0000644000076500007650000000020411466617447017152 0ustar hanshans#define CYCLONE_VERSION "0.1" #define CYCLONE_RELEASE "alpha" #define CYCLONE_BUILD 55 #if 0 CYCLONE_SNAPSHOT = 0.1-alpha55 #endif cyclone-0.1-alpha55/cyclone/Makefile.objects0000644000076500007650000000401211466617447017462 0ustar hanshansHLOUD_OBJECTS = common/loud.o HFITTER_OBJECTS = common/loud.o common/fitter.o HFORKY_OBJECTS = common/loud.o unstable/forky.o HFRAGILE_OBJECTS = common/loud.o unstable/fragile.o HGROW_OBJECTS = common/grow.o common/loud.o HGROWFITTER_OBJECTS = common/grow.o common/loud.o common/fitter.o HFILE_OBJECTS = hammer/file.o common/loud.o common/os.o \ common/fitter.o unstable/forky.o HRAND_OBJECTS = common/rand.o common/loud.o HRANDFILE_OBJECTS = common/rand.o hammer/file.o common/loud.o common/os.o \ common/fitter.o \ unstable/forky.o HRANDGROW_OBJECTS = common/rand.o common/grow.o common/loud.o common/fitter.o HRANDGROWFILE_OBJECTS = common/rand.o common/grow.o hammer/file.o \ common/loud.o common/os.o unstable/forky.o HTREE_OBJECTS = hammer/tree.o common/loud.o HTREEFILEVEFL_OBJECTS = hammer/tree.o hammer/file.o common/vefl.o \ common/loud.o common/os.o unstable/forky.o unstable/fragile.o HGUI_OBJECTS = hammer/gui.o common/loud.o HSEQ_OBJECTS = common/mifi.o hammer/file.o \ common/grow.o common/loud.o common/os.o common/fitter.o unstable/forky.o SPLAINNOTILDE_OBJECTS = common/loud.o common/fitter.o SSIC_OBJECTS = sickle/sic.o common/loud.o SFORKY_OBJECTS = sickle/sic.o common/loud.o unstable/forky.o SFRAGILE_OBJECTS = sickle/sic.o common/loud.o unstable/fragile.o SFRAGILEFITTER_OBJECTS = sickle/sic.o common/loud.o common/fitter.o \ unstable/fragile.o SGROW_OBJECTS = common/grow.o sickle/sic.o common/loud.o SGROWCLC_OBJECTS = common/grow.o common/clc.o sickle/sic.o common/loud.o SGROWFORKY_OBJECTS = common/grow.o sickle/sic.o \ common/loud.o common/fitter.o unstable/forky.o SVEFL_OBJECTS = common/vefl.o sickle/sic.o common/loud.o unstable/fragile.o SARSIC_OBJECTS = sickle/sic.o sickle/arsic.o common/vefl.o \ common/loud.o unstable/fragile.o SARSICFITTER_OBJECTS = sickle/sic.o sickle/arsic.o common/vefl.o \ common/loud.o common/fitter.o unstable/fragile.o SFILE_OBJECTS = hammer/file.o sickle/sic.o common/loud.o common/os.o \ unstable/forky.o RELEASE_LIBS = cyclone hammer sickle dummies maxmode RELEASE_APPS = cyclist cyclone-0.1-alpha55/cyclone/cyclone-vicious.exclude0000644000076500007650000000001511466617447021057 0ustar hanshans*~ old old/* cyclone-0.1-alpha55/cyclone/README.txt0000644000076500007650000000747511466617447016110 0ustar hanshanshttp://suita.chopin.edu.pl/~czaja/miXed/externs/cyclone.html ------- cyclone ------- Cyclone is a library of PureData classes, bringing some level of compatibility between Max/MSP and Pd environments. Although being itself in the early stage of development, it is meant to eventually become part of a much larger project, aiming at unification and standardization of computer musician's tools. In its current form, cyclone is mainly for people using both Max and Pd, and thus wanting to develop cross-platform patches. In this respect, cyclone has much in common with Thomas Grill's flext, and flext-based externals. See Thomas' page. While flext enables developing new cross-platform classes, cyclone makes existing classes cross-platform. Cyclone also comes handy, somewhat, in the task of importing Max/MSP patches into Pd. Do not expect miracles, though, it is usually not an easy task. The entire cyclone library, which might be preloaded with either -lib cyclone or -lib maxmode option, consists of: * the main hammer and sickle sub-libraries, containing Pd versions of, respectively, Max and MSP classes; * cyclone sub-library, taking care of loading hammer and sickle, and which itself contains: a small set of operators (!-, !/, ==~, !=~, <~, <=~, >~, >=~, !-~, !/~, %~, +=~); an importing mechanism provided by the cyclone class. * optional dummies sub-library, which contains a large set of dummy classes, serving as substitutions for Max/MSP classes not (yet) implemented in cyclone; * maxmode sub-library, which imposes strict compatibility mode, and loads all the other components, including dummies. The two main sub-libraries might be loaded separately, by using -lib hammer and/or -lib sickle options. There is also a possibility of loading any single class from hammer or sickle library dynamically (this feature is only available in the linux snapshot). Currently, the hammer part contains: accum, acos, active, anal, Append (more info), asin, bangbang, bondo, Borax, Bucket, buddy, capture, cartopol, Clip, coll, comment, cosh, counter, cycle, decide, Decode, drunk, flush, forward, fromsymbol, funbuff, funnel, gate, grab, Histo, iter, match, maximum, mean, midiflush, midiformat, midiparse, minimum, mousefilter, MouseState, mtr (more info), next, offer, onebang, past, Peak, poltocar, prepend (more info), prob, pv, seq (more info), sinh, speedlim, spell, split, spray, sprintf, substitute, sustain, switch, Table (more info), tanh, thresh, TogEdge, tosymbol, Trough, universal, urn, Uzi, xbendin, xbendout, xnotein, xnoteout, and zl. The sickle part contains: abs~, acos~, acosh~, allpass~, asin~, asinh~, atan~, atan2~, atanh~, average~, avg~, bitand~, bitnot~, bitor~, bitshift~, bitxor~, buffir~, capture~, cartopol~, change~, click~, Clip~, comb~, cosh~, cosx~, count~, curve~, cycle~, delay~, delta~, deltaclip~, edge~, frameaccum~, framedelta~, index~, kink~, Line~, linedrive, log~, lookup~, lores~, matrix~ (more info), maximum~, minimum~, minmax~, mstosamps~, onepole~, peakamp~, peek~, phasewrap~, pink~, play~, poke~, poltocar~, pong~, pow~, rampsmooth~, rand~, record~, reson~, sah~, sampstoms~, Scope~, sinh~, sinx~, slide~, Snapshot~, spike~, svf~, tanh~, tanx~, train~, trapezoid~, triangle~, vectral~, wave~, and zerox~. Cyclone comes without any documentation. All the included patches were created merely for testing. Caveats: * The binaries provided in this snapshot release are not expected to run inside of a pre-0.36 version of Pd, without prior recompiling. * If a single -lib cyclone startup option is used, cyclone in turn loads its two main components: hammer and sickle. If a single -lib maxmode startup option is used, all the remaining library components are going to be loaded: cyclone, hammer, sickle, and dummies. In these cases, all the required libraries should be accessible by Pd. cyclone-0.1-alpha55/cyclone/cyclone-help.include0000644000076500007650000000020311466617447020317 0ustar hanshansbin/Append-help.pd bin/Clip-help.pd bin/Clip~-help.pd bin/Line~-help.pd bin/Scope~-help.pd bin/Snapshot~-help.pd bin/Table-help.pd cyclone-0.1-alpha55/cyclone/notes.txt0000644000076500007650000000471411466617447016274 0ustar hanshansTODO for cyclone * add folder class, so people forget about using tot for that purpose * plug import into file/open DONE for cyclone alpha55 * new class: overdrive~ * seq: . new incompatible message 'tempo': 1-based coef, does not start playback . fix for double-to-float-pair calc in 'scoretime' and 'goto' * abs~: performance fix * slide~, rampsmooth~: bashing denormals alpha54 * comment: fixing namespace bug, reducing traffic * testmess: optionally filling message with symbols (numbers in hex form or names of all registered classes) alpha53 * matrix~: incompatible message 'set' * coll: . fixed descending order of 'sort' (a leaking sentinel bug) . ignoring negative indices in 'min' and 'max' . editor fixes (close by wm, dirty flag, title) * Table: reading from file, reading from editor, editor fixes * seq: editor fixes, editor bound to click (should bind to "open" too...) * prob, capture, capture~: viewer fixes alpha52 * compatibility mode interface in maxmode object: messages 'set', 'get' (reply through the second outlet) * better handling of initial directory in open panels * relative path handling in 'cd' (library objects, seq, more to come) * remote reply to 'pwd' message of library objects (target argument required) * instead, left outlet of library objects sends return code from import (negative value indicates an error) * new class: matrix~ * linedrive: more compatible in maxmode, bipolar otherwise * seq: . paused state fixes (state preserved in 'goto', proper delay in 'start') . 'goto' fix (works in idlemode) . more incompatible messages: 'scoretime', 'cd', 'pwd' alpha51 * dummies loaded by maxmode, not cyclone * setting directory in creation argument replaced with 'cd' message to library objects (cyclone, maxmode, hammer and sickle) * 'pwd' message to library objects sends directory symbol to an outlet * creating cyclone and maxmode library objects possible without loading component libraries * prepend and Append: . bang handling, controlled by maxmode . restored max-like 'set' handling as default for objects with arguments * fix for parsing creation arguments in svf~ * incompatible additions to seq: 'pause', 'continue', 'goto' alpha50 * max-compatibility mode switch for cyclone . turned on by loading cyclone libs through "-lib maxmode" . affects max-compatibility of prepend and Append, controls compatibility warnings cyclone-0.1-alpha55/cyclone/Makefile.libdir0000644000076500007650000001141111466617447017277 0ustar hanshans# this Makefile builds a libdir for cyclone # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib bindir = $(prefix)/bin pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 755 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch EXTENSION = pd_darwin OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer CFLAGS := $(IPHONE_CFLAGS) $(OPT_CFLAGS) $(CFLAGS) LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) LIBS += -lc STRIP = strip -x else # Mac OS X EXTENSION = pd_darwin OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4 else FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 endif CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include LDFLAGS += $(FAT_FLAGS) -bundle -undefined dynamic_lookup -L/sw/lib # if the 'pd' binary exists, check the linking against it to aid with stripping LDFLAGS += $(shell test -e $(PD_PATH)/bin/pd && echo -bundle_loader $(PD_PATH)/bin/pd) LIBS += -lc STRIP = strip -x # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) EXTENSION = pd_linux OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += -fPIC LDFLAGS += -Wl,--export-dynamic -shared -fPIC LIBS += -lc STRIP = strip --strip-unneeded -R .note -R .comment endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) EXTENSION = dll OS = cygwin PD_PATH = $(cygpath $(PROGRAMFILES))/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -Wl,--export-dynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" LIBS += -lc -lpd STRIP = strip --strip-unneeded -R .note -R .comment endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) EXTENSION = dll OS = windows PD_PATH = $(shell cd "$(PROGRAMFILES)"/pd && pwd) OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer CFLAGS += -mms-bitfields LDFLAGS += -s -shared -Wl,--enable-auto-import LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 STRIP = strip --strip-unneeded -R .note -R .comment endif cyclone: $(MAKE) -j4 -f Makefile \ OPT_CFLAGS="-O6 -funroll-loops -fomit-frame-pointer -fno-strict-aliasing -fPIC" install: cyclone $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/cyclone $(INSTALL_DATA) cyclone-meta.pd $(DESTDIR)$(objectsdir)/cyclone $(INSTALL_DATA) ../LICENSE.txt $(DESTDIR)$(objectsdir)/cyclone $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/cyclone # cyclone is compiled straight into $(OUT_DIR), yes a kludge, but the code of # this build system is impenetrable $(MAKE) -j4 OUT_DIR=$(DESTDIR)$(objectsdir)/cyclone $(STRIP) $(DESTDIR)$(objectsdir)/cyclone/*.$(EXTENSION) chmod a-x $(DESTDIR)$(objectsdir)/cyclone/*.$(EXTENSION) # install "maxmode" libraries into subdir, so they don't override the libdir $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/cyclone/maxmode $(INSTALL_DATA) ../bin/cyclone.$(EXTENSION) \ ../bin/hammer.$(EXTENSION) \ ../bin/sickle.$(EXTENSION) \ ../bin/maxmode.$(EXTENSION) \ $(DESTDIR)$(objectsdir)/cyclone/maxmode $(STRIP) $(DESTDIR)$(objectsdir)/cyclone/maxmode/*.$(EXTENSION) $(INSTALL_DATA) ../doc/help/cyclone/*.* \ $(DESTDIR)$(objectsdir)/cyclone $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/cyclone/examples $(INSTALL_DATA) ../test/cyclone/*.* \ $(DESTDIR)$(objectsdir)/cyclone/examples # install "cyclist" command line app with pd $(INSTALL_DIR) $(DESTDIR)$(bindir) $(INSTALL_PROGRAM) ../bin/cyclist $(DESTDIR)$(bindir) $(STRIP) $(DESTDIR)$(bindir)/cyclist clean: -$(MAKE) -f Makefile $(DEST_PATHS) clean -rm -f ../bin/*.pd_linux -rm -f ../bin/cyclist -rm -f Makefile.deps -rm -f shadow/Makefile.deps -rm -f hammer/Makefile.deps -rm -f sickle/Makefile.deps -rm -f ../build-stamp cyclone-0.1-alpha55/cyclone/cyclone-test.exclude0000644000076500007650000000010111466617447020351 0ustar hanshans*~ *.pict import-result.pd import-debug.pd temporary temporary/* cyclone-0.1-alpha55/cyclone/cyclone-all.exclude0000644000076500007650000000007511466617447020154 0ustar hanshans*~ *.o *.gz *.html *.out */*/old */*/old/* */*/ref */*/ref/* cyclone-0.1-alpha55/cyclone/cyclone-shared.include0000644000076500007650000000173311466617447020646 0ustar hanshansshared/shared.c shared/shared.h shared/unstable/forky.c shared/unstable/forky.h shared/unstable/fragile.c shared/unstable/fragile.h shared/unstable/fringe.c shared/unstable/fringe.h shared/unstable/loader.c shared/unstable/loader.h shared/unstable/pd_imp.h shared/unstable/standalone.c shared/unstable/standalone.h shared/common/loud.c shared/common/loud.h shared/common/grow.c shared/common/grow.h shared/common/os.c shared/common/os.h shared/common/fitter.c shared/common/fitter.h shared/common/lex.c shared/common/lex.h shared/common/binport.c shared/common/binport.h shared/common/port.c shared/common/port.h shared/common/rand.c shared/common/rand.h shared/common/vefl.c shared/common/vefl.h shared/common/clc.c shared/common/clc.h shared/common/mifi.c shared/common/mifi.h shared/hammer/file.c shared/hammer/file.h shared/hammer/gui.c shared/hammer/gui.h shared/hammer/tree.c shared/hammer/tree.h shared/sickle/sic.c shared/sickle/sic.h shared/sickle/arsic.c shared/sickle/arsic.h cyclone-0.1-alpha55/cyclone/cyclone-meta.pd0000644000076500007650000000054011466617447017301 0ustar hanshans#N canvas 10 10 200 200 10; #N canvas 20 20 420 300 META 0; #X text 10 10 META this is a prototype of a libdir meta file; #X text 10 30 NAME cyclone; #X text 10 50 AUTHOR Kzrysztof Czaja; #X text 10 70 LICENSE BSD; #X text 10 90 VERSION 0.1; #X text 10 110 DESCRIPTION a library for porting and running Max/MSP patches in Pd; #X restore 10 10 pd META; cyclone-0.1-alpha55/cyclone/Makefile0000644000076500007650000000006211466617447016033 0ustar hanshansROOT_DIR = .. include $(ROOT_DIR)/Makefile.common cyclone-0.1-alpha55/cyclone/Makefile.dirs0000644000076500007650000000010611466617447016772 0ustar hanshansMIXED_DIRS = shadow hammer sickle RELEASE_DIRS = shadow hammer sickle cyclone-0.1-alpha55/cyclone/hammer/0000755000076500007650000000000011466617445015644 5ustar hanshanscyclone-0.1-alpha55/cyclone/hammer/thresh.c0000644000076500007650000000637411466617445017317 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/grow.h" #define THRESH_INISIZE 32 /* LATER rethink */ #define THRESH_MAXSIZE 256 #define THRESH_DEFTHRESH 10 typedef struct _thresh { t_object x_ob; t_float x_thresh; int x_size; /* as allocated */ int x_natoms; /* as used */ t_atom *x_message; t_atom x_messini[THRESH_INISIZE]; t_clock *x_clock; } t_thresh; static t_class *thresh_class; static void thresh_tick(t_thresh *x) { int ac = x->x_natoms; if (ac) { t_atom *av = x->x_message; if (av->a_type == A_FLOAT) /* redundant, but we might need it LATER */ { if (ac > 1) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); } x->x_natoms = 0; } } static void thresh_anything(t_thresh *x, t_symbol *s, int ac, t_atom *av) { int ntotal = x->x_natoms + ac; t_atom *buf; clock_unset(x->x_clock); if (s == &s_) s = 0; if (s) ntotal++; if (ntotal > x->x_size) { /* LATER if (ntotal > THRESH_MAXSIZE)... (cf prepend) */ int nrequested = ntotal; x->x_message = grow_withdata(&nrequested, &x->x_natoms, &x->x_size, x->x_message, THRESH_INISIZE, x->x_messini, sizeof(*x->x_message)); if (nrequested != ntotal) { x->x_natoms = 0; if (ac >= x->x_size) ac = (s ? x->x_size - 1 : x->x_size); } } buf = x->x_message + x->x_natoms; if (s) { SETSYMBOL(buf, s); buf++; x->x_natoms++; } if (ac) { memcpy(buf, av, ac * sizeof(*buf)); x->x_natoms += ac; } clock_delay(x->x_clock, x->x_thresh); } static void thresh_float(t_thresh *x, t_float f) { t_atom at; SETFLOAT(&at, f); thresh_anything(x, 0, 1, &at); } static void thresh_list(t_thresh *x, t_symbol *s, int ac, t_atom *av) { thresh_anything(x, 0, ac, av); } static void thresh_ft1(t_thresh *x, t_floatarg f) { if (f < 0) f = 0; /* CHECKED */ x->x_thresh = f; /* CHECKED: no rearming */ } static void thresh_free(t_thresh *x) { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); if (x->x_clock) clock_free(x->x_clock); } static void *thresh_new(t_floatarg f) { t_thresh *x = (t_thresh *)pd_new(thresh_class); x->x_thresh = (f > 0 ? f : THRESH_DEFTHRESH); x->x_size = THRESH_INISIZE; x->x_natoms = 0; x->x_message = x->x_messini; inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_list); /* LATER rethink: list or float */ x->x_clock = clock_new(x, (t_method)thresh_tick); return (x); } void thresh_setup(void) { thresh_class = class_new(gensym("thresh"), (t_newmethod)thresh_new, (t_method)thresh_free, sizeof(t_thresh), 0, A_DEFFLOAT, 0); class_addfloat(thresh_class, thresh_float); class_addlist(thresh_class, thresh_list); class_addmethod(thresh_class, (t_method)thresh_ft1, gensym("ft1"), A_FLOAT, 0); /* CHECKED: thresh: doesn't understand bang, symbol, anything */ } cyclone-0.1-alpha55/cyclone/hammer/coll.c0000644000076500007650000012124511466617445016746 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" #include "hammer/file.h" /* LATER profile for the bottlenecks of insertion and sorting */ /* LATER make sure that ``reentrancy protection hack'' is really working... */ #ifdef KRZYSZCZ //#define COLL_DEBUG #endif enum { COLL_HEADRESET, COLL_HEADNEXT, COLL_HEADPREV, /* distinction not used, currently */ COLL_HEADDELETED }; typedef struct _collelem { int e_hasnumkey; int e_numkey; t_symbol *e_symkey; struct _collelem *e_prev; struct _collelem *e_next; int e_size; t_atom *e_data; } t_collelem; typedef struct _collcommon { t_pd c_pd; struct _coll *c_refs; /* used in read-banging and dirty flag handling */ int c_increation; int c_volatile; int c_selfmodified; int c_entered; /* a counter, LATER rethink */ int c_embedflag; /* common field (CHECKED in 'TEXT' files) */ t_symbol *c_filename; /* CHECKED common for all, read and write */ t_canvas *c_lastcanvas; t_hammerfile *c_filehandle; t_collelem *c_first; t_collelem *c_last; t_collelem *c_head; int c_headstate; } t_collcommon; typedef struct _coll { t_object x_ob; t_canvas *x_canvas; t_symbol *x_name; t_collcommon *x_common; t_hammerfile *x_filehandle; t_outlet *x_keyout; t_outlet *x_filebangout; t_outlet *x_dumpbangout; struct _coll *x_next; } t_coll; static t_class *coll_class; static t_class *collcommon_class; static t_collelem *collelem_new(int ac, t_atom *av, int *np, t_symbol *s) { t_collelem *ep = (t_collelem *)getbytes(sizeof(*ep)); if (ep->e_hasnumkey = (np != 0)) ep->e_numkey = *np; ep->e_symkey = s; ep->e_prev = ep->e_next = 0; if (ep->e_size = ac) { t_atom *ap = getbytes(ac * sizeof(*ap)); ep->e_data = ap; if (av) while (ac--) *ap++ = *av++; else while (ac--) { SETFLOAT(ap, 0); ap++; } } else ep->e_data = 0; return (ep); } static void collelem_free(t_collelem *ep) { if (ep->e_data) freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data)); freebytes(ep, sizeof(*ep)); } /* CHECKME again... apparently c74 is not able to fix this for good */ /* result: 1 for ep1 < ep2, 0 for ep1 >= ep2, all symbols are < any float */ static int collelem_less(t_collelem *ep1, t_collelem *ep2, int ndx, int swap) { int isless; if (swap) { t_collelem *ep = ep1; ep1 = ep2; ep2 = ep; } if (ndx < 0) { if (ep1->e_symkey) isless = (ep2->e_symkey ? strcmp(ep1->e_symkey->s_name, ep2->e_symkey->s_name) < 0 : 1); /* CHECKED incompatible with 4.07, but consistent */ else if (ep2->e_symkey) isless = 0; /* CHECKED incompatible with 4.07, but consistent */ else isless = (ep1->e_numkey < ep2->e_numkey); /* CHECKED in 4.07 */ } else { t_atom *ap1 = (ndx < ep1->e_size ? ep1->e_data + ndx : ep1->e_data + ep1->e_size - 1); t_atom *ap2 = (ndx < ep2->e_size ? ep2->e_data + ndx : ep2->e_data + ep2->e_size - 1); if (ap1->a_type == A_FLOAT) { if (ap2->a_type == A_FLOAT) isless = (ap1->a_w.w_float < ap2->a_w.w_float); else if (ap2->a_type == A_SYMBOL) isless = 0; else isless = 1; } else if (ap1->a_type == A_SYMBOL) { if (ap2->a_type == A_FLOAT) isless = 1; else if (ap2->a_type == A_SYMBOL) isless = (strcmp(ap1->a_w.w_symbol->s_name, ap2->a_w.w_symbol->s_name) < 0); else isless = 1; } else isless = 0; } return (isless); } static t_collelem *collcommon_numkey(t_collcommon *cc, int numkey) { t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) if (ep->e_hasnumkey && ep->e_numkey == numkey) return (ep); return (0); } static t_collelem *collcommon_symkey(t_collcommon *cc, t_symbol *symkey) { t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) if (ep->e_symkey == symkey) return (ep); return (0); } static void collcommon_takeout(t_collcommon *cc, t_collelem *ep) { if (ep->e_prev) ep->e_prev->e_next = ep->e_next; else cc->c_first = ep->e_next; if (ep->e_next) ep->e_next->e_prev = ep->e_prev; else cc->c_last = ep->e_prev; if (cc->c_head == ep) { cc->c_head = ep->e_next; /* asymmetric, LATER rethink */ cc->c_headstate = COLL_HEADDELETED; } } static void collcommon_modified(t_collcommon *cc, int relinked) { if (cc->c_increation) return; if (relinked) { cc->c_volatile = 1; } if (cc->c_embedflag) { t_coll *x; for (x = cc->c_refs; x; x = x->x_next) if (x->x_canvas && glist_isvisible(x->x_canvas)) canvas_dirty(x->x_canvas, 1); } } /* atomic collcommon modifiers: clearall, remove, replace, putbefore, putafter, swaplinks, swapkeys, changesymkey, renumber, sort */ static void collcommon_clearall(t_collcommon *cc) { if (cc->c_first) { t_collelem *ep1 = cc->c_first, *ep2; do { ep2 = ep1->e_next; collelem_free(ep1); } while (ep1 = ep2); cc->c_first = cc->c_last = 0; cc->c_head = 0; cc->c_headstate = COLL_HEADRESET; collcommon_modified(cc, 1); } } static void collcommon_remove(t_collcommon *cc, t_collelem *ep) { collcommon_takeout(cc, ep); collelem_free(ep); collcommon_modified(cc, 1); } static void collcommon_replace(t_collcommon *cc, t_collelem *ep, int ac, t_atom *av, int *np, t_symbol *s) { if (ep->e_hasnumkey = (np != 0)) ep->e_numkey = *np; ep->e_symkey = s; if (ac) { int i = ac; t_atom *ap; if (ep->e_data) { if (ep->e_size != ac) ap = resizebytes(ep->e_data, ep->e_size * sizeof(*ap), ac * sizeof(*ap)); else ap = ep->e_data; } else ap = getbytes(ac * sizeof(*ap)); ep->e_data = ap; if (av) while (i --) *ap++ = *av++; else while (i --) { SETFLOAT(ap, 0); ap++; } } else { if (ep->e_data) freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data)); ep->e_data = 0; } ep->e_size = ac; collcommon_modified(cc, 0); } static void collcommon_putbefore(t_collcommon *cc, t_collelem *ep, t_collelem *next) { if (next) { ep->e_next = next; if (ep->e_prev = next->e_prev) ep->e_prev->e_next = ep; else cc->c_first = ep; next->e_prev = ep; } else if (cc->c_first || cc->c_last) loudbug_bug("collcommon_putbefore"); else cc->c_first = cc->c_last = ep; collcommon_modified(cc, 1); } static void collcommon_putafter(t_collcommon *cc, t_collelem *ep, t_collelem *prev) { if (prev) { ep->e_prev = prev; if (ep->e_next = prev->e_next) ep->e_next->e_prev = ep; else cc->c_last = ep; prev->e_next = ep; } else if (cc->c_first || cc->c_last) loudbug_bug("collcommon_putafter"); else cc->c_first = cc->c_last = ep; collcommon_modified(cc, 1); } /* LATER consider making it faster, if there is a real need. Now called only in the sort routine, once per sort. */ static void collcommon_swaplinks(t_collcommon *cc, t_collelem *ep1, t_collelem *ep2) { if (ep1 != ep2) { t_collelem *prev1 = ep1->e_prev, *prev2 = ep2->e_prev; if (prev1 == ep2) { collcommon_takeout(cc, ep2); collcommon_putafter(cc, ep2, ep1); } else if (prev2 == ep1) { collcommon_takeout(cc, ep1); collcommon_putafter(cc, ep1, ep2); } else if (prev1) { if (prev2) { collcommon_takeout(cc, ep1); collcommon_takeout(cc, ep2); collcommon_putafter(cc, ep1, prev2); collcommon_putafter(cc, ep2, prev1); } else { t_collelem *next2 = ep2->e_next; collcommon_takeout(cc, ep1); collcommon_takeout(cc, ep2); collcommon_putbefore(cc, ep1, next2); collcommon_putafter(cc, ep2, prev1); } } else if (prev2) { t_collelem *next1 = ep1->e_next; collcommon_takeout(cc, ep1); collcommon_takeout(cc, ep2); collcommon_putafter(cc, ep1, prev2); collcommon_putbefore(cc, ep2, next1); } else loudbug_bug("collcommon_swaplinks"); } } static void collcommon_swapkeys(t_collcommon *cc, t_collelem *ep1, t_collelem *ep2) { int hasnumkey = ep2->e_hasnumkey, numkey = ep2->e_numkey; t_symbol *symkey = ep2->e_symkey; ep2->e_hasnumkey = ep1->e_hasnumkey; ep2->e_numkey = ep1->e_numkey; ep2->e_symkey = ep1->e_symkey; ep1->e_hasnumkey = hasnumkey; ep1->e_numkey = numkey; ep1->e_symkey = symkey; collcommon_modified(cc, 0); } static void collcommon_changesymkey(t_collcommon *cc, t_collelem *ep, t_symbol *s) { ep->e_symkey = s; collcommon_modified(cc, 0); } static void collcommon_renumber(t_collcommon *cc, int startkey) { t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) if (ep->e_hasnumkey) ep->e_numkey = startkey++; collcommon_modified(cc, 0); } /* LATER choose a better algo, after coll's storage structures stabilize. Note, that even the simple insertion sort below (n-square) might prove better for bi-directional lists, than theoretically efficient algo (nlogn) requiring random access emulation. Avoiding recursion is not a bad idea, too. */ static void collcommon_sort(t_collcommon *cc, int descending, int ndx) { t_collelem *min = cc->c_first; t_collelem *ep; if (min && (ep = min->e_next)) { cc->c_increation = 1; /* search for a sentinel element */ do if (collelem_less(ep, min, ndx, descending)) min = ep; while (ep = ep->e_next); /* prepend it */ collcommon_swaplinks(cc, cc->c_first, min); /* sort */ ep = min->e_next->e_next; while (ep) { t_collelem *next = ep->e_next; for (min = ep->e_prev; min && /* LATER remove */ collelem_less(ep, min, ndx, descending); min = min->e_prev); if (!min) /* LATER remove */ loudbug_bug("collcommon_sort"); else if (ep != min->e_next) { collcommon_takeout(cc, ep); collcommon_putafter(cc, ep, min); } ep = next; } cc->c_increation = 0; collcommon_modified(cc, 1); } } static void collcommon_adddata(t_collcommon *cc, t_collelem *ep, int ac, t_atom *av) { if (ac) { t_atom *ap; int newsize = ep->e_size + ac; if (ep->e_data) ap = resizebytes(ep->e_data, ep->e_size * sizeof(*ap), newsize * sizeof(*ap)); else { ep->e_size = 0; /* redundant, hopefully */ ap = getbytes(newsize * sizeof(*ap)); } ep->e_data = ap; ap += ep->e_size; if (av) while (ac--) *ap++ = *av++; else while (ac--) { SETFLOAT(ap, 0); ap++; } ep->e_size = newsize; collcommon_modified(cc, 0); } } static t_collelem *collcommon_tonumkey(t_collcommon *cc, int numkey, int ac, t_atom *av, int replace) { t_collelem *old = collcommon_numkey(cc, numkey), *new; if (old && replace) collcommon_replace(cc, new = old, ac, av, &numkey, 0); else { new = collelem_new(ac, av, &numkey, 0); if (old) { collcommon_putbefore(cc, new, old); do if (old->e_hasnumkey) /* CHECKED incremented up to the last one; incompatible: elements with numkey == 0 not incremented (a bug?) */ old->e_numkey++; while (old = old->e_next); } else { /* CHECKED negative numkey always put before the last element, zero numkey always becomes the new head */ int closestkey = 0; t_collelem *closest = 0, *ep; for (ep = cc->c_first; ep; ep = ep->e_next) { if (ep->e_hasnumkey) { if (numkey >= closestkey && numkey <= ep->e_numkey) { collcommon_putbefore(cc, new, ep); break; } closestkey = ep->e_numkey; } closest = ep; } if (!ep) { if (numkey <= closestkey) collcommon_putbefore(cc, new, closest); else collcommon_putafter(cc, new, closest); } } } return (new); } static t_collelem *collcommon_tosymkey(t_collcommon *cc, t_symbol *symkey, int ac, t_atom *av, int replace) { t_collelem *old = collcommon_symkey(cc, symkey), *new; if (old && replace) collcommon_replace(cc, new = old, ac, av, 0, symkey); else collcommon_putafter(cc, new = collelem_new(ac, av, 0, symkey), cc->c_last); return (new); } static int collcommon_fromatoms(t_collcommon *cc, int ac, t_atom *av) { int hasnumkey = 0, numkey; t_symbol *symkey = 0; int size = 0; t_atom *data = 0; int nlines = 0; cc->c_increation = 1; collcommon_clearall(cc); while (ac--) { if (data) { if (av->a_type == A_SEMI) { t_collelem *ep = collelem_new(size, data, hasnumkey ? &numkey : 0, symkey); collcommon_putafter(cc, ep, cc->c_last); hasnumkey = 0; symkey = 0; data = 0; nlines++; } if (av->a_type == A_COMMA) { /* CHECKED rejecting a comma */ collcommon_clearall(cc); /* LATER rethink */ cc->c_increation = 0; return (-nlines); } else size++; } else if (av->a_type == A_COMMA) { size = 0; data = av + 1; } else if (av->a_type == A_SYMBOL) symkey = av->a_w.w_symbol; else if (av->a_type == A_FLOAT && loud_checkint(0, av->a_w.w_float, &numkey, 0)) hasnumkey = 1; else { loud_error(0, "coll: bad atom"); collcommon_clearall(cc); /* LATER rethink */ cc->c_increation = 0; return (-nlines); } av++; } if (data) { loud_error(0, "coll: incomplete"); collcommon_clearall(cc); /* LATER rethink */ cc->c_increation = 0; return (-nlines); } cc->c_increation = 0; return (nlines); } static int collcommon_frombinbuf(t_collcommon *cc, t_binbuf *bb) { return (collcommon_fromatoms(cc, binbuf_getnatom(bb), binbuf_getvec(bb))); } static void collcommon_doread(t_collcommon *cc, t_symbol *fn, t_canvas *cv) { t_binbuf *bb; char buf[MAXPDSTRING]; if (!fn && !(fn = cc->c_filename)) /* !fn: 'readagain' */ return; /* FIXME use open_via_path() */ if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg, 'readagain' */ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } if (!cc->c_refs) { /* loading during object creation -- avoid binbuf_read()'s complaints, LATER rethink */ FILE *fp; char fname[MAXPDSTRING]; sys_bashfilename(buf, fname); if (!(fp = fopen(fname, "r"))) { loud_warning(&coll_class, 0, "no coll file '%s'", fname); return; } fclose(fp); } bb = binbuf_new(); if (binbuf_read(bb, buf, "", 0)) loud_error(0, "coll: error reading text file '%s'", fn->s_name); else { int nlines = collcommon_frombinbuf(cc, bb); if (nlines > 0) { t_coll *x; /* LATER consider making this more robust */ for (x = cc->c_refs; x; x = x->x_next) outlet_bang(x->x_filebangout); cc->c_lastcanvas = cv; cc->c_filename = fn; post("coll: finished reading %d lines from text file '%s'", nlines, fn->s_name); } else if (nlines < 0) loud_error(0, "coll: error in line %d of text file '%s'", 1 - nlines, fn->s_name); else loud_error(0, "coll: error reading text file '%s'", fn->s_name); if (cc->c_refs) collcommon_modified(cc, 1); } binbuf_free(bb); } static void collcommon_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { collcommon_doread((t_collcommon *)z, fn, 0); } static void collcommon_tobinbuf(t_collcommon *cc, t_binbuf *bb) { t_collelem *ep; t_atom at[3]; for (ep = cc->c_first; ep; ep = ep->e_next) { t_atom *ap = at; int cnt = 1; if (ep->e_hasnumkey) { SETFLOAT(ap, ep->e_numkey); ap++; cnt++; } if (ep->e_symkey) { SETSYMBOL(ap, ep->e_symkey); ap++; cnt++; } SETCOMMA(ap); binbuf_add(bb, cnt, at); binbuf_add(bb, ep->e_size, ep->e_data); binbuf_addsemi(bb); } } static void collcommon_dowrite(t_collcommon *cc, t_symbol *fn, t_canvas *cv) { t_binbuf *bb; int ac; t_atom *av; char buf[MAXPDSTRING]; if (!fn && !(fn = cc->c_filename)) /* !fn: 'writeagain' */ return; if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'write' w/o arg, 'writeagain' */ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } bb = binbuf_new(); collcommon_tobinbuf(cc, bb); if (binbuf_write(bb, buf, "", 0)) loud_error(0, "coll: error writing text file '%s'", fn->s_name); else { cc->c_lastcanvas = cv; cc->c_filename = fn; } binbuf_free(bb); } static void collcommon_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { collcommon_dowrite((t_collcommon *)z, fn, 0); } static void coll_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) { t_coll *x = (t_coll *)z; t_collcommon *cc = x->x_common; if (cc->c_embedflag) { t_collelem *ep; t_atom at[6]; binbuf_addv(bb, "ssii;", bindsym, gensym("flags"), 1, 0); SETSYMBOL(at, bindsym); for (ep = cc->c_first; ep; ep = ep->e_next) { t_atom *ap = at + 1; int cnt; if (ep->e_hasnumkey && ep->e_symkey) { SETSYMBOL(ap, gensym("nstore")); ap++; SETSYMBOL(ap, ep->e_symkey); ap++; SETFLOAT(ap, ep->e_numkey); cnt = 4; } else if (ep->e_symkey) { SETSYMBOL(ap, gensym("store")); ap++; SETSYMBOL(ap, ep->e_symkey); cnt = 3; } else { SETFLOAT(ap, ep->e_numkey); cnt = 2; } binbuf_add(bb, cnt, at); binbuf_add(bb, ep->e_size, ep->e_data); binbuf_addsemi(bb); } } } static void collcommon_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) { int nlines = collcommon_fromatoms((t_collcommon *)z, ac, av); if (nlines < 0) loud_error(0, "coll: editing error in line %d", 1 - nlines); } static void collcommon_free(t_collcommon *cc) { t_collelem *ep1, *ep2 = cc->c_first; while (ep1 = ep2) { ep2 = ep1->e_next; collelem_free(ep1); } } static void *collcommon_new(void) { t_collcommon *cc = (t_collcommon *)pd_new(collcommon_class); cc->c_embedflag = 0; cc->c_first = cc->c_last = 0; cc->c_head = 0; cc->c_headstate = COLL_HEADRESET; return (cc); } static t_collcommon *coll_checkcommon(t_coll *x) { if (x->x_name && x->x_common != (t_collcommon *)pd_findbyclass(x->x_name, collcommon_class)) { loudbug_bug("coll_checkcommon"); return (0); } return (x->x_common); } static void coll_unbind(t_coll *x) { /* LATER consider calling coll_checkcommon(x) */ t_collcommon *cc = x->x_common; t_coll *prev, *next; if ((prev = cc->c_refs) == x) { if (!(cc->c_refs = x->x_next)) { hammerfile_free(cc->c_filehandle); collcommon_free(cc); if (x->x_name) pd_unbind(&cc->c_pd, x->x_name); pd_free(&cc->c_pd); } } else if (prev) { while (next = prev->x_next) { if (next == x) { prev->x_next = next->x_next; break; } prev = next; } } x->x_common = 0; x->x_name = 0; x->x_next = 0; } static void coll_bind(t_coll *x, t_symbol *name) { t_collcommon *cc = 0; if (name == &s_) name = 0; else if (name) cc = (t_collcommon *)pd_findbyclass(name, collcommon_class); if (!cc) { cc = (t_collcommon *)collcommon_new(); cc->c_refs = 0; cc->c_increation = 0; if (name) { pd_bind(&cc->c_pd, name); /* LATER rethink canvas unpredictability */ collcommon_doread(cc, name, x->x_canvas); } else { cc->c_filename = 0; cc->c_lastcanvas = 0; } cc->c_filehandle = hammerfile_new((t_pd *)cc, 0, collcommon_readhook, collcommon_writehook, collcommon_editorhook); } x->x_common = cc; x->x_name = name; x->x_next = cc->c_refs; cc->c_refs = x; } static int coll_rebind(t_coll *x, t_symbol *name) { t_collcommon *cc; if (name && name != &s_ && (cc = (t_collcommon *)pd_findbyclass(name, collcommon_class))) { coll_unbind(x); x->x_common = cc; x->x_name = name; x->x_next = cc->c_refs; cc->c_refs = x; return (1); } else return (0); } static void coll_dooutput(t_coll *x, int ac, t_atom *av) { if (ac > 1) { if (av->a_type == A_FLOAT) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else if (av->a_type == A_SYMBOL) outlet_anything(((t_object *)x)->ob_outlet, av->a_w.w_symbol, ac-1, av+1); } else if (ac) { if (av->a_type == A_FLOAT) outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); else if (av->a_type == A_SYMBOL) outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); } } static void coll_keyoutput(t_coll *x, t_collelem *ep) { t_collcommon *cc = x->x_common; if (!cc->c_entered++) cc->c_selfmodified = 0; cc->c_volatile = 0; if (ep->e_hasnumkey) outlet_float(x->x_keyout, ep->e_numkey); else if (ep->e_symkey) outlet_symbol(x->x_keyout, ep->e_symkey); else outlet_float(x->x_keyout, 0); if (cc->c_volatile) cc->c_selfmodified = 1; cc->c_entered--; } static t_collelem *coll_findkey(t_coll *x, t_atom *key, t_symbol *mess) { t_collcommon *cc = x->x_common; t_collelem *ep = 0; if (key->a_type == A_FLOAT) { int numkey; if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess)) ep = collcommon_numkey(cc, numkey); else mess = 0; } else if (key->a_type == A_SYMBOL) ep = collcommon_symkey(cc, key->a_w.w_symbol); else if (mess) { loud_messarg((t_pd *)x, mess); mess = 0; } if (!ep && mess) loud_error((t_pd *)x, "no such key"); return (ep); } static t_collelem *coll_tokey(t_coll *x, t_atom *key, int ac, t_atom *av, int replace, t_symbol *mess) { t_collcommon *cc = x->x_common; t_collelem *ep = 0; if (key->a_type == A_FLOAT) { int numkey; if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess)) ep = collcommon_tonumkey(cc, numkey, ac, av, replace); } else if (key->a_type == A_SYMBOL) ep = collcommon_tosymkey(cc, key->a_w.w_symbol, ac, av, replace); else if (mess) loud_messarg((t_pd *)x, mess); return (ep); } static t_collelem *coll_firsttyped(t_coll *x, int ndx, t_atomtype type) { t_collcommon *cc = x->x_common; t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) if (ep->e_size > ndx && ep->e_data[ndx].a_type == type) return (ep); return (0); } /* the methods */ static void coll_float(t_coll *x, t_float f) { t_collcommon *cc = x->x_common; t_collelem *ep; int numkey; if (loud_checkint((t_pd *)x, f, &numkey, &s_float) && (ep = collcommon_numkey(cc, numkey))) { coll_keyoutput(x, ep); if (!cc->c_selfmodified || (ep = collcommon_numkey(cc, numkey))) coll_dooutput(x, ep->e_size, ep->e_data); } } static void coll_symbol(t_coll *x, t_symbol *s) { t_collcommon *cc = x->x_common; t_collelem *ep; if (ep = collcommon_symkey(cc, s)) { coll_keyoutput(x, ep); if (!cc->c_selfmodified || (ep = collcommon_symkey(cc, s))) coll_dooutput(x, ep->e_size, ep->e_data); } } static void coll_list(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av->a_type == A_FLOAT) coll_tokey(x, av, ac-1, av+1, 1, &s_list); else loud_messarg((t_pd *)x, &s_list); } static void coll_anything(t_coll *x, t_symbol *s, int ac, t_atom *av) { coll_symbol(x, s); } static void coll_store(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2) coll_tokey(x, av, ac-1, av+1, 1, s); else loud_messarg((t_pd *)x, s); } static void coll_nstore(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 3) { t_collcommon *cc = x->x_common; t_collelem *ep; int numkey; if (av->a_type == A_FLOAT && av[1].a_type == A_SYMBOL) { if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s)) { if (ep = collcommon_symkey(cc, av[1].a_w.w_symbol)) collcommon_remove(cc, ep); ep = collcommon_tonumkey(cc, numkey, ac-2, av+2, 1); ep->e_symkey = av[1].a_w.w_symbol; } } else if (av->a_type == A_SYMBOL && av[1].a_type == A_FLOAT) { if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &numkey, s)) { if (ep = collcommon_numkey(cc, numkey)) collcommon_remove(cc, ep); ep = collcommon_tosymkey(cc, av->a_w.w_symbol, ac-2, av+2, 1); ep->e_hasnumkey = 1; ep->e_numkey = numkey; } } else loud_messarg((t_pd *)x, s); } else loud_messarg((t_pd *)x, s); } static void coll_insert(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av->a_type == A_FLOAT) coll_tokey(x, av, ac-1, av+1, 0, s); else loud_messarg((t_pd *)x, s); } static void coll_remove(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac) { t_collelem *ep; if (ep = coll_findkey(x, av, s)) collcommon_remove(x->x_common, ep); } else loud_messarg((t_pd *)x, s); } static void coll_delete(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac) { t_collelem *ep; if (ep = coll_findkey(x, av, s)) { if (av->a_type == A_FLOAT) { int numkey = ep->e_numkey; t_collelem *next; for (next = ep->e_next; next; next = next->e_next) if (next->e_hasnumkey && next->e_numkey > numkey) next->e_numkey--; } collcommon_remove(x->x_common, ep); } } else loud_messarg((t_pd *)x, s); } static void coll_assoc(t_coll *x, t_symbol *s, t_floatarg f) { int numkey; if (loud_checkint((t_pd *)x, f, &numkey, gensym("assoc"))) { t_collcommon *cc = x->x_common; t_collelem *ep1, *ep2; if ((ep1 = collcommon_numkey(cc, numkey)) && ep1->e_symkey != s) /* LATER rethink */ { if (ep2 = collcommon_symkey(cc, s)) collcommon_remove(cc, ep2); collcommon_changesymkey(cc, ep1, s); } } } static void coll_deassoc(t_coll *x, t_symbol *s, t_floatarg f) { int numkey; if (loud_checkint((t_pd *)x, f, &numkey, gensym("deassoc"))) { t_collcommon *cc = x->x_common; t_collelem *ep; if (ep = collcommon_numkey(cc, numkey)) collcommon_changesymkey(cc, ep, 0); } } static void coll_subsym(t_coll *x, t_symbol *s1, t_symbol *s2) { t_collelem *ep; if (s1 != s2 && (ep = collcommon_symkey(x->x_common, s2))) collcommon_changesymkey(x->x_common, ep, s1); } static void coll_renumber(t_coll *x, t_floatarg f) { int startkey; if (loud_checkint((t_pd *)x, f, &startkey, gensym("renumber"))) collcommon_renumber(x->x_common, startkey); } static void coll_merge(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2) { t_collcommon *cc = x->x_common; t_collelem *ep; if (av->a_type == A_FLOAT) { int numkey; if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s)) { if (ep = collcommon_numkey(cc, numkey)) collcommon_adddata(cc, ep, ac-1, av+1); else /* LATER consider defining collcommon_toclosest() */ collcommon_tonumkey(cc, numkey, ac-1, av+1, 1); } } else if (av->a_type == A_SYMBOL) { if (ep = collcommon_symkey(cc, av->a_w.w_symbol)) collcommon_adddata(cc, ep, ac-1, av+1); else { ep = collelem_new(ac-1, av+1, 0, av->a_w.w_symbol); collcommon_putafter(cc, ep, cc->c_last); } } else loud_messarg((t_pd *)x, s); } else loud_messarg((t_pd *)x, s); } static void coll_sub(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac) { t_collelem *ep; if (ep = coll_findkey(x, av, s)) { t_collcommon *cc = x->x_common; t_atom *key = av++; ac--; while (ac >= 2) { if (av->a_type == A_FLOAT) { int ndx; if (loud_checkint((t_pd *)x, av->a_w.w_float, &ndx, 0) && ndx >= 1 && ndx <= ep->e_size) ep->e_data[ndx-1] = av[1]; } ac -= 2; av += 2; } if (s == gensym("sub")) { coll_keyoutput(x, ep); if (!cc->c_selfmodified || (ep = coll_findkey(x, key, 0))) coll_dooutput(x, ep->e_size, ep->e_data); } } } else loud_messarg((t_pd *)x, s); } static void coll_sort(t_coll *x, t_floatarg f1, t_floatarg f2) { int dir, ndx; if (loud_checkint((t_pd *)x, f1, &dir, gensym("sort")) && loud_checkint((t_pd *)x, f2, &ndx, gensym("sort"))) collcommon_sort(x->x_common, (dir < 0 ? 0 : 1), (ndx < 0 ? -1 : (ndx ? ndx - 1 : 0))); } static void coll_clear(t_coll *x) { collcommon_clearall(x->x_common); } /* According to the refman, the data should be swapped, rather than the keys -- easy here, but apparently c74 people have chosen to avoid some effort needed in case of their implementation... */ static void coll_swap(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac == 2) { t_collelem *ep1, *ep2; if ((ep1 = coll_findkey(x, av, s)) && (ep2 = coll_findkey(x, av + 1, s))) collcommon_swapkeys(x->x_common, ep1, ep2); } else loud_messarg((t_pd *)x, s); } /* CHECKED traversal direction change is consistent with the general rule: 'next' always outputs e_next of a previous output, and 'prev' always outputs e_prev, whether preceded by 'prev', or by 'next'. This is currently implemented by pre-updating of the head (which is inhibited if there was no previous output, i.e. after 'goto', 'end', or collection initialization). CHECKME again. */ static void coll_next(t_coll *x) { t_collcommon *cc = x->x_common; if (cc->c_headstate != COLL_HEADRESET && cc->c_headstate != COLL_HEADDELETED) /* asymmetric, LATER rethink */ { if (cc->c_head) cc->c_head = cc->c_head->e_next; if (!cc->c_head && !(cc->c_head = cc->c_first)) /* CHECKED wrapping */ return; } else if (!cc->c_head && !(cc->c_head = cc->c_first)) return; cc->c_headstate = COLL_HEADNEXT; coll_keyoutput(x, cc->c_head); if (cc->c_head) coll_dooutput(x, cc->c_head->e_size, cc->c_head->e_data); else if (!cc->c_selfmodified) loudbug_bug("coll_next"); /* LATER rethink */ } static void coll_prev(t_coll *x) { t_collcommon *cc = x->x_common; if (cc->c_headstate != COLL_HEADRESET) { if (cc->c_head) cc->c_head = cc->c_head->e_prev; if (!cc->c_head && !(cc->c_head = cc->c_last)) /* CHECKED wrapping */ return; } else if (!cc->c_head && !(cc->c_head = cc->c_first)) return; cc->c_headstate = COLL_HEADPREV; coll_keyoutput(x, cc->c_head); if (cc->c_head) coll_dooutput(x, cc->c_head->e_size, cc->c_head->e_data); else if (!cc->c_selfmodified) loudbug_bug("coll_prev"); /* LATER rethink */ } static void coll_end(t_coll *x) { t_collcommon *cc = x->x_common; cc->c_head = cc->c_last; cc->c_headstate = COLL_HEADRESET; } static void coll_goto(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac) { t_collelem *ep = coll_findkey(x, av, s); if (ep) { t_collcommon *cc = x->x_common; cc->c_head = ep; cc->c_headstate = COLL_HEADRESET; } } else loud_messarg((t_pd *)x, s); } static void coll_nth(t_coll *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av[1].a_type == A_FLOAT) { int ndx; t_collelem *ep; if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &ndx, s) && (ep = coll_findkey(x, av, s)) && ep->e_size >= ndx) { t_atom *ap = ep->e_data + --ndx; if (ap->a_type == A_FLOAT) outlet_float(((t_object *)x)->ob_outlet, ap->a_w.w_float); else if (ap->a_type == A_SYMBOL) outlet_symbol(((t_object *)x)->ob_outlet, ap->a_w.w_symbol); } } else loud_messarg((t_pd *)x, s); } static void coll_length(t_coll *x) { t_collcommon *cc = x->x_common; t_collelem *ep = cc->c_first; int result = 0; while (ep) result++, ep = ep->e_next; outlet_float(((t_object *)x)->ob_outlet, result); } static void coll_min(t_coll *x, t_floatarg f) { int ndx; if (loud_checkint((t_pd *)x, f, &ndx, gensym("min"))) { t_collelem *found; if (ndx > 0) ndx--; /* LATER consider complaining: */ else if (ndx < 0) return; /* CHECKED silently rejected */ /* else CHECKED silently defaults to 1 */ if (found = coll_firsttyped(x, ndx, A_FLOAT)) { t_float result = found->e_data[ndx].a_w.w_float; t_collelem *ep; for (ep = found->e_next; ep; ep = ep->e_next) { if (ep->e_size > ndx && ep->e_data[ndx].a_type == A_FLOAT && ep->e_data[ndx].a_w.w_float < result) { found = ep; result = ep->e_data[ndx].a_w.w_float; } } coll_keyoutput(x, found); outlet_float(((t_object *)x)->ob_outlet, result); } } } static void coll_max(t_coll *x, t_floatarg f) { int ndx; if (loud_checkint((t_pd *)x, f, &ndx, gensym("max"))) { t_collelem *found; if (ndx > 0) ndx--; /* LATER consider complaining: */ else if (ndx < 0) return; /* CHECKED silently rejected */ /* else CHECKED silently defaults to 1 */ if (found = coll_firsttyped(x, ndx, A_FLOAT)) { t_float result = found->e_data[ndx].a_w.w_float; t_collelem *ep; for (ep = found->e_next; ep; ep = ep->e_next) { if (ep->e_size > ndx && ep->e_data[ndx].a_type == A_FLOAT && ep->e_data[ndx].a_w.w_float > result) { found = ep; result = ep->e_data[ndx].a_w.w_float; } } coll_keyoutput(x, found); outlet_float(((t_object *)x)->ob_outlet, result); } } } static void coll_refer(t_coll *x, t_symbol *s) { if (!coll_rebind(x, s)) { /* LATER consider complaining */ } } static void coll_flags(t_coll *x, t_float f1, t_float f2) { int i1; if (loud_checkint((t_pd *)x, f1, &i1, gensym("flags"))) { t_collcommon *cc = x->x_common; cc->c_embedflag = (i1 != 0); } } static void coll_read(t_coll *x, t_symbol *s) { t_collcommon *cc = x->x_common; if (s && s != &s_) collcommon_doread(cc, s, x->x_canvas); else hammerpanel_open(cc->c_filehandle, 0); } static void coll_write(t_coll *x, t_symbol *s) { t_collcommon *cc = x->x_common; if (s && s != &s_) collcommon_dowrite(cc, s, x->x_canvas); else hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKED no default name */ } static void coll_readagain(t_coll *x) { t_collcommon *cc = x->x_common; if (cc->c_filename) collcommon_doread(cc, 0, 0); else hammerpanel_open(cc->c_filehandle, 0); } static void coll_writeagain(t_coll *x) { t_collcommon *cc = x->x_common; if (cc->c_filename) collcommon_dowrite(cc, 0, 0); else hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKED no default name */ } static void coll_filetype(t_coll *x, t_symbol *s) { /* dummy */ } static void coll_dump(t_coll *x) { t_collcommon *cc = x->x_common; t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) { coll_keyoutput(x, ep); if (cc->c_selfmodified) break; coll_dooutput(x, ep->e_size, ep->e_data); /* FIXME dooutput() may invalidate ep as well as keyoutput()... */ } outlet_bang(x->x_dumpbangout); } static void coll_open(t_coll *x) { t_collcommon *cc = x->x_common; t_binbuf *bb = binbuf_new(); int i, natoms, newline; t_atom *ap; char buf[MAXPDSTRING]; hammereditor_open(cc->c_filehandle, (x->x_name ? x->x_name->s_name : "Untitled"), "coll"); collcommon_tobinbuf(cc, bb); natoms = binbuf_getnatom(bb); ap = binbuf_getvec(bb); newline = 1; while (natoms--) { char *ptr = buf; if (ap->a_type != A_SEMI && ap->a_type != A_COMMA && !newline) *ptr++ = ' '; atom_string(ap, ptr, MAXPDSTRING); if (ap->a_type == A_SEMI) { strcat(buf, "\n"); newline = 1; } else newline = 0; hammereditor_append(cc->c_filehandle, buf); ap++; } hammereditor_setdirty(cc->c_filehandle, 0); binbuf_free(bb); } /* CHECKED if there was any editing, both close window and 'wclose' ask and replace the contents. LATER debug. */ static void coll_wclose(t_coll *x) { hammereditor_close(x->x_common->c_filehandle, 1); } static void coll_click(t_coll *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { coll_open(x); } #ifdef COLL_DEBUG static void collelem_post(t_collelem *ep) { if (ep->e_hasnumkey && ep->e_symkey) loudbug_startpost("%d %s:", ep->e_numkey, ep->e_symkey->s_name); else if (ep->e_hasnumkey) loudbug_startpost("%d:", ep->e_numkey); else if (ep->e_symkey) loudbug_startpost("%s:", ep->e_symkey->s_name); else loudbug_bug("collcommon_post"); loudbug_postatom(ep->e_size, ep->e_data); loudbug_endpost(); } static void collcommon_post(t_collcommon *cc) { t_collelem *ep; for (ep = cc->c_first; ep; ep = ep->e_next) collelem_post(ep); } static void coll_debug(t_coll *x, t_floatarg f) { t_collcommon *cc = coll_checkcommon(x); if (cc) { t_coll *x1 = cc->c_refs; t_collelem *ep, *last; int i = 0; while (x1) i++, x1 = x1->x_next; loudbug_post("refcount %d", i); for (ep = cc->c_first, last = 0; ep; ep = ep->e_next) last = ep; if (last != cc->c_last) loudbug_bug("coll_debug: last element"); collcommon_post(cc); } } #endif static void coll_free(t_coll *x) { hammerfile_free(x->x_filehandle); coll_unbind(x); } static void *coll_new(t_symbol *s) { t_coll *x = (t_coll *)pd_new(coll_class); x->x_canvas = canvas_getcurrent(); outlet_new((t_object *)x, &s_); x->x_keyout = outlet_new((t_object *)x, &s_); x->x_filebangout = outlet_new((t_object *)x, &s_bang); x->x_dumpbangout = outlet_new((t_object *)x, &s_bang); x->x_filehandle = hammerfile_new((t_pd *)x, coll_embedhook, 0, 0, 0); coll_bind(x, s); return (x); } void coll_setup(void) { coll_class = class_new(gensym("coll"), (t_newmethod)coll_new, (t_method)coll_free, sizeof(t_coll), 0, A_DEFSYM, 0); class_addbang(coll_class, coll_next); class_addfloat(coll_class, coll_float); class_addsymbol(coll_class, coll_symbol); class_addlist(coll_class, coll_list); class_addanything(coll_class, coll_anything); class_addmethod(coll_class, (t_method)coll_store, gensym("store"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_nstore, gensym("nstore"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_insert, gensym("insert"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_remove, gensym("remove"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_delete, gensym("delete"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_assoc, gensym("assoc"), A_SYMBOL, A_FLOAT, 0); class_addmethod(coll_class, (t_method)coll_deassoc, gensym("deassoc"), A_SYMBOL, A_FLOAT, 0); class_addmethod(coll_class, (t_method)coll_subsym, gensym("subsym"), A_SYMBOL, A_SYMBOL, 0); class_addmethod(coll_class, (t_method)coll_renumber, gensym("renumber"), A_DEFFLOAT, 0); class_addmethod(coll_class, (t_method)coll_merge, gensym("merge"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_sub, gensym("sub"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_sub, gensym("nsub"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_clear, gensym("clear"), 0); class_addmethod(coll_class, (t_method)coll_sort, gensym("sort"), A_FLOAT, A_DEFFLOAT, 0); class_addmethod(coll_class, (t_method)coll_swap, gensym("swap"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_next, gensym("next"), 0); class_addmethod(coll_class, (t_method)coll_prev, gensym("prev"), 0); class_addmethod(coll_class, (t_method)coll_end, gensym("end"), 0); class_addmethod(coll_class, (t_method)coll_goto, gensym("goto"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_nth, gensym("nth"), A_GIMME, 0); class_addmethod(coll_class, (t_method)coll_length, gensym("length"), 0); class_addmethod(coll_class, (t_method)coll_min, gensym("min"), A_DEFFLOAT, 0); class_addmethod(coll_class, (t_method)coll_max, gensym("max"), A_DEFFLOAT, 0); class_addmethod(coll_class, (t_method)coll_refer, gensym("refer"), A_SYMBOL, 0); class_addmethod(coll_class, (t_method)coll_flags, gensym("flags"), A_FLOAT, A_FLOAT, 0); class_addmethod(coll_class, (t_method)coll_read, gensym("read"), A_DEFSYM, 0); class_addmethod(coll_class, (t_method)coll_write, gensym("write"), A_DEFSYM, 0); class_addmethod(coll_class, (t_method)coll_readagain, gensym("readagain"), 0); class_addmethod(coll_class, (t_method)coll_writeagain, gensym("writeagain"), 0); class_addmethod(coll_class, (t_method)coll_filetype, gensym("filetype"), A_SYMBOL, 0); class_addmethod(coll_class, (t_method)coll_dump, gensym("dump"), 0); class_addmethod(coll_class, (t_method)coll_open, gensym("open"), 0); class_addmethod(coll_class, (t_method)coll_wclose, gensym("wclose"), 0); class_addmethod(coll_class, (t_method)coll_click, gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); #ifdef COLL_DEBUG class_addmethod(coll_class, (t_method)coll_debug, gensym("debug"), A_DEFFLOAT, 0); #endif hammerfile_setup(coll_class, 1); collcommon_class = class_new(gensym("coll"), 0, 0, sizeof(t_collcommon), CLASS_PD, 0); /* this call is a nop (collcommon does not embed, and the hammerfile class itself has been already set up above), but it is better to have it around, just in case... */ hammerfile_setup(collcommon_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/offer.c0000644000076500007650000000465211466617445017120 0ustar hanshans/* Copyright (c) 2002-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #include "hammer/tree.h" /* As a class `derived' from the common hammertree code (also in funbuff), offer maintains the auxiliary list, the main purpose of which is faster traversal (not needed here). As a side-effect, there is a bonus of a small speedup of deletion, and a penalty of a small slowdown of insertion. */ typedef struct _offer { t_object x_ob; t_float x_value; int x_valueset; t_hammertree x_tree; } t_offer; static t_class *offer_class; static void offer_float(t_offer *x, t_float f) { int ndx; if (loud_checkint((t_pd *)x, f, &ndx, &s_float)) /* CHECKED */ { t_hammernode *np; if (x->x_valueset) { hammertree_insertfloat(&x->x_tree, ndx, x->x_value, 1); x->x_valueset = 0; } else if (np = hammertree_search(&x->x_tree, ndx)) { outlet_float(((t_object *)x)->ob_outlet, HAMMERNODE_GETFLOAT(np)); hammertree_delete(&x->x_tree, np); } } } static void offer_ft1(t_offer *x, t_floatarg f) { /* this is incompatible -- CHECKED float is silently truncated */ x->x_value = f; x->x_valueset = 1; } static void offer_clear(t_offer *x) { hammertree_clear(&x->x_tree, 0); /* CHECKED valueset is not cleared */ } #ifdef HAMMERTREE_DEBUG static void offer_debug(t_offer *x, t_floatarg f) { hammertree_debug(&x->x_tree, (int)f, 0); } #endif static void offer_free(t_offer *x) { hammertree_clear(&x->x_tree, 0); } static void *offer_new(void) { t_offer *x = (t_offer *)pd_new(offer_class); x->x_valueset = 0; hammertree_inittyped(&x->x_tree, HAMMERTYPE_FLOAT, 0); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_float); return (x); } void offer_setup(void) { offer_class = class_new(gensym("offer"), (t_newmethod)offer_new, (t_method)offer_free, sizeof(t_offer), 0, 0); class_addfloat(offer_class, offer_float); class_addmethod(offer_class, (t_method)offer_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(offer_class, (t_method)offer_clear, gensym("clear"), 0); #ifdef HAMMERTREE_DEBUG class_addmethod(offer_class, (t_method)offer_debug, gensym("debug"), A_DEFFLOAT, 0); #endif } cyclone-0.1-alpha55/cyclone/hammer/TogEdge.c0000644000076500007650000000256611466617445017337 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" typedef struct _TogEdge { t_object x_ob; int x_wason; t_outlet *x_out1; } t_TogEdge; static t_class *TogEdge_class; static void TogEdge_bang(t_TogEdge *x) { if (x->x_wason) { x->x_wason = 0; outlet_bang(x->x_out1); } else { x->x_wason = 1; outlet_bang(((t_object *)x)->ob_outlet); } } static void TogEdge_float(t_TogEdge *x, t_float f) { int i; if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */ { if (x->x_wason) { if (!i) { x->x_wason = 0; outlet_bang(x->x_out1); } } else { if (i) { x->x_wason = 1; outlet_bang(((t_object *)x)->ob_outlet); } } } } static void *TogEdge_new(void) { t_TogEdge *x = (t_TogEdge *)pd_new(TogEdge_class); x->x_wason = 0; /* CHECKED */ outlet_new((t_object *)x, &s_bang); x->x_out1 = outlet_new((t_object *)x, &s_bang); return (x); } void TogEdge_setup(void) { TogEdge_class = class_new(gensym("TogEdge"), (t_newmethod)TogEdge_new, 0, sizeof(t_TogEdge), 0, 0); class_addbang(TogEdge_class, TogEdge_bang); class_addfloat(TogEdge_class, TogEdge_float); } cyclone-0.1-alpha55/cyclone/hammer/xnoteout.c0000644000076500007650000000344611466617445017704 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _xnoteout { t_object x_ob; t_float x_channel; t_float x_flag; t_float x_velocity; int x_pitch; } t_xnoteout; static t_class *xnoteout_class; static void xnoteout_dooutput(t_xnoteout *x) { int status = ((int)x->x_flag ? 0x90 : 0x80); /* CHECKME */ int channel = (int)x->x_channel; /* CHECKME */ int pitch = x->x_pitch; int velocity = (int)x->x_velocity & 0x7F; /* CHECKME */ if (pitch >= 0 && /* CHECKME */ pitch <= 127 && /* CHECKME */ channel > 0) /* CHECKME */ { outlet_float(((t_object *)x)->ob_outlet, status + ((channel-1) & 0x0F)); outlet_float(((t_object *)x)->ob_outlet, pitch); outlet_float(((t_object *)x)->ob_outlet, velocity); } } static void xnoteout_float(t_xnoteout *x, t_float f) { x->x_pitch = (int)f; /* CHECKME */ xnoteout_dooutput(x); } static void *xnoteout_new(t_floatarg f) { t_xnoteout *x = (t_xnoteout *)pd_new(xnoteout_class); floatinlet_new((t_object *)x, &x->x_velocity); floatinlet_new((t_object *)x, &x->x_flag); floatinlet_new((t_object *)x, &x->x_channel); outlet_new((t_object *)x, &s_float); x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */ x->x_flag = 0; /* CHECKME */ x->x_velocity = 0; /* CHECKME */ x->x_pitch = -1; /* CHECKME */ return (x); } void xnoteout_setup(void) { xnoteout_class = class_new(gensym("xnoteout"), (t_newmethod)xnoteout_new, 0, sizeof(t_xnoteout), 0, A_DEFFLOAT, 0); class_addbang(xnoteout_class, xnoteout_dooutput); class_addfloat(xnoteout_class, xnoteout_float); } cyclone-0.1-alpha55/cyclone/hammer/sinh.c0000644000076500007650000000212411466617445016750 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define sinhf sinh #endif typedef struct _sinh { t_object x_ob; float x_value; } t_sinh; static t_class *sinh_class; static void sinh_bang(t_sinh *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_value); } static void sinh_float(t_sinh *x, t_float f) { /* CHECKME large values */ outlet_float(((t_object *)x)->ob_outlet, x->x_value = sinhf(f)); } static void *sinh_new(t_floatarg f) { t_sinh *x = (t_sinh *)pd_new(sinh_class); /* CHECKME large values */ x->x_value = sinhf(f); outlet_new((t_object *)x, &s_float); return (x); } void sinh_setup(void) { sinh_class = class_new(gensym("sinh"), (t_newmethod)sinh_new, 0, sizeof(t_sinh), 0, A_DEFFLOAT, 0); class_addbang(sinh_class, sinh_bang); class_addfloat(sinh_class, sinh_float); } cyclone-0.1-alpha55/cyclone/hammer/Bucket.c0000644000076500007650000000701011466617445017223 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is a modified version of Joseph A. Sarlo's code. The most important changes are listed in "pd-lib-notes.txt" file. */ #include "m_pd.h" typedef struct _Bucket { t_object x_ob; int x_numbucks; t_float *x_bucks; /* CHECKED: no limit */ t_outlet **x_outs; short int x_frozen; /* 0 for thawed, 1 for frozen */ short int x_dir; /* 0 for L2R, 1 for R2L */ } t_Bucket; static t_class *Bucket_class; static void Bucket_bang(t_Bucket *x) { int i = x->x_numbucks; /* CHECKED: outlets output in right-to-left order */ while (i--) outlet_float(x->x_outs[i], x->x_bucks[i]); } static void Bucket_float(t_Bucket *x, t_float val) { int i; if (!x->x_frozen) Bucket_bang(x); if (!x->x_dir) { for (i = x->x_numbucks - 1; i > 0; i--) x->x_bucks[i] = x->x_bucks[i - 1]; x->x_bucks[0] = val; } else { for (i = 0; i < x->x_numbucks - 1; i++) x->x_bucks[i] = x->x_bucks[i + 1]; x->x_bucks[x->x_numbucks - 1] = val; } } static void Bucket_freeze(t_Bucket *x) { x->x_frozen = 1; } static void Bucket_thaw(t_Bucket *x) { x->x_frozen = 0; } static void Bucket_roll(t_Bucket *x) { if (x->x_dir) Bucket_float(x, x->x_bucks[0]); else Bucket_float(x, x->x_bucks[x->x_numbucks - 1]); } static void Bucket_rtol(t_Bucket *x) { x->x_dir = 1; } static void Bucket_ltor(t_Bucket *x) { x->x_dir = 0; } static void Bucket_set(t_Bucket *x, t_floatarg f) { int i = x->x_numbucks; while (i--) x->x_bucks[i] = f; if (!x->x_frozen) /* CHECKED */ Bucket_bang(x); } static void Bucket_free(t_Bucket *x) { if (x->x_bucks) freebytes(x->x_bucks, x->x_numbucks * sizeof(*x->x_bucks)); if (x->x_outs) freebytes(x->x_outs, x->x_numbucks * sizeof(*x->x_outs)); } static void *Bucket_new(t_floatarg val) { t_Bucket *x; int i, nbucks = (int)val; t_float *bucks; t_outlet **outs; if (nbucks < 1) nbucks = 1; if (!(bucks = (t_float *)getbytes(nbucks * sizeof(*bucks)))) return (0); if (!(outs = (t_outlet **)getbytes(nbucks * sizeof(*outs)))) { freebytes(bucks, nbucks * sizeof(*bucks)); return (0); } x = (t_Bucket *)pd_new(Bucket_class); x->x_numbucks = nbucks; x->x_bucks = bucks; x->x_outs = outs; x->x_frozen = 0; x->x_dir = 0; while (nbucks--) *outs++ = outlet_new((t_object *)x, &s_float); return (x); } void Bucket_setup(void) { Bucket_class = class_new(gensym("Bucket"), (t_newmethod)Bucket_new, (t_method)Bucket_free, sizeof(t_Bucket), 0, A_DEFFLOAT, 0); class_addbang(Bucket_class, Bucket_bang); class_addfloat(Bucket_class, Bucket_float); class_addmethod(Bucket_class, (t_method)Bucket_freeze, gensym("freeze"), 0); class_addmethod(Bucket_class, (t_method)Bucket_thaw, gensym("thaw"), 0); class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("L2R"), 0); class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("R2L"), 0); /* CHECKED (refman error) roll has no argument */ class_addmethod(Bucket_class, (t_method)Bucket_roll, gensym("roll"), 0); /* 3.5 additions */ class_addmethod(Bucket_class, (t_method)Bucket_set, gensym("set"), A_FLOAT, 0); class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("l2r"), 0); class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("r2l"), 0); } cyclone-0.1-alpha55/cyclone/hammer/xbendin.c0000644000076500007650000000410511466617445017437 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _xbendin { t_object x_ob; int x_omni; unsigned char x_ready; unsigned char x_status; unsigned char x_channel; unsigned char x_lsb; t_outlet *x_chanout; } t_xbendin; static t_class *xbendin_class; static void xbendin_clear(t_xbendin *x) { x->x_status = 0; x->x_ready = 0; } static void xbendin_float(t_xbendin *x, t_float f) { int ival = (int)f; /* CHECKME */ if (ival < 0) { /* CHECKME */ return; } if (ival < 256) /* CHECKME */ { unsigned char bval = ival; if (bval & 0x80) { unsigned char status = bval & 0xF0; if (status == 0xF0) { /* CHECKME */ if (bval < 0xF8) xbendin_clear(x); } else if (status == 0xE0) { unsigned char channel = bval & 0x0F; if (x->x_omni) x->x_channel = channel; x->x_status = (x->x_channel == channel); x->x_ready = 0; } else xbendin_clear(x); } else if (x->x_ready) { if (x->x_omni) outlet_float(x->x_chanout, x->x_channel + 1); outlet_float(((t_object *)x)->ob_outlet, (bval << 7) + x->x_lsb); x->x_ready = 0; } else if (x->x_status) { x->x_lsb = bval; x->x_ready = 1; } } else xbendin_clear(x); } static void *xbendin_new(t_floatarg f) { int channel = (int)f; /* CHECKME */ t_xbendin *x = (t_xbendin *)pd_new(xbendin_class); outlet_new((t_object *)x, &s_float); if (x->x_omni = (channel == 0)) /* CHECKME */ x->x_chanout = outlet_new((t_object *)x, &s_float); else x->x_channel = (unsigned char)--channel; /* CHECKME */ xbendin_clear(x); return (x); } void xbendin_setup(void) { xbendin_class = class_new(gensym("xbendin"), (t_newmethod)xbendin_new, 0, sizeof(t_xbendin), 0, A_DEFFLOAT, 0); class_addfloat(xbendin_class, xbendin_float); /* CHECKME autocasting lists to floats */ } cyclone-0.1-alpha55/cyclone/hammer/Makefile.objects0000644000076500007650000000043611466617445020737 0ustar hanshansSHARED_OBJECTS = \ unstable/forky.o \ unstable/fragile.o \ unstable/fringe.o \ common/loud.o \ common/grow.o \ common/os.o \ common/fitter.o \ common/rand.o \ common/vefl.o \ common/mifi.o \ common/lex.o \ common/binport.o \ common/port.o \ hammer/file.o \ hammer/gui.o \ hammer/tree.o cyclone-0.1-alpha55/cyclone/hammer/Table.c0000644000076500007650000006325111466617445017046 0ustar hanshans/* Copyright (c) 2004-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* Write access is totally encapsulated in tablecommon calls, in order to simplify proper handling of the distribution cache. Direct read access from table calls is allowed (for speed). */ #include #include #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" #include "common/grow.h" #include "common/rand.h" #include "hammer/file.h" #ifdef KRZYSZCZ #define TABLE_DEBUG #endif #define TABLE_INISIZE 256 /* LATER rethink */ #define TABLE_DEFLENGTH 128 /* CHECKED */ #define TABLE_MINLENGTH 2 /* CHECKED */ #define TABLE_MAXLENGTH 16383 /* CHECKED, LATER rethink */ #define TABLE_MINRANGE 2 /* CHECKED */ #define TABLE_MAXQ 32768 /* CHECKME */ typedef struct _tablecommon { t_pd c_pd; struct _table *c_refs; int c_increation; int c_volatile; int c_selfmodified; int c_entered; /* a counter, LATER rethink */ /* CHECKED flags, etc. are common fields */ int c_visflag; int c_embedflag; int c_dontsaveflag; int c_notenamesflag; int c_signedflag; int c_range; int c_left; int c_top; int c_right; int c_bottom; int c_size; /* as allocated */ int c_length; /* as used */ int *c_table; int c_tableini[TABLE_INISIZE]; int c_cacheisfresh; int c_cachesum; int c_cachemin; int c_cachemax; int *c_cache; int c_cacheini[TABLE_INISIZE]; t_symbol *c_filename; t_canvas *c_lastcanvas; t_hammerfile *c_filehandle; } t_tablecommon; typedef struct _table { t_object x_ob; t_canvas *x_glist; t_symbol *x_name; t_tablecommon *x_common; t_float x_value; int x_valueset; int x_head; int x_intraversal; /* ``set-with-next/prev'' flag */ int x_loadflag; int x_loadndx; unsigned int x_seed; t_hammerfile *x_filehandle; t_outlet *x_bangout; struct _table *x_next; } t_table; static t_class *table_class; static t_class *tablecommon_class; static void tablecommon_modified(t_tablecommon *cc, int relocated) { cc->c_cacheisfresh = 0; if (cc->c_increation) return; if (relocated) { cc->c_volatile = 1; } if (cc->c_embedflag) { t_table *x; for (x = cc->c_refs; x; x = x->x_next) if (x->x_glist && glist_isvisible(x->x_glist)) canvas_dirty(x->x_glist, 1); } } static int tablecommon_getindex(t_tablecommon *cc, int ndx) { int nmx = cc->c_length - 1; /* CHECKED ndx silently clipped */ return (ndx < 0 ? 0 : (ndx > nmx ? nmx : ndx)); } static int tablecommon_getvalue(t_tablecommon *cc, int ndx) { int nmx = cc->c_length - 1; /* CHECKED ndx silently clipped */ return (cc->c_table[ndx < 0 ? 0 : (ndx > nmx ? nmx : ndx)]); } static void tablecommon_setvalue(t_tablecommon *cc, int ndx, int v) { int nmx = cc->c_length - 1; /* CHECKED ndx silently clipped, value not clipped */ cc->c_table[ndx < 0 ? 0 : (ndx > nmx ? nmx : ndx)] = v; tablecommon_modified(cc, 0); } static int tablecommon_loadvalue(t_tablecommon *cc, int ndx, int v) { /* CHECKME */ if (ndx < cc->c_length) { cc->c_table[ndx] = v; tablecommon_modified(cc, 0); return (1); } else return (0); } static void tablecommon_setall(t_tablecommon *cc, int v) { int ndx = cc->c_length; int *ptr = cc->c_table; while (ndx--) *ptr++ = v; tablecommon_modified(cc, 0); } static void tablecommon_setatoms(t_tablecommon *cc, int ndx, int ac, t_atom *av) { if (ac > 1 && av->a_type == A_FLOAT) { /* CHECKED no resizing */ int last = tablecommon_getindex(cc, ndx + ac - 1); int *ptr = cc->c_table + ndx; for (; ndx <= last; ndx++, av++) *ptr++ = (av->a_type == A_FLOAT ? (int)av->a_w.w_float : 0); tablecommon_modified(cc, 0); } } static void tablecommon_setlength(t_tablecommon *cc, int length) { int relocate; if (length < TABLE_MINLENGTH) length = TABLE_MINLENGTH; else if (length > TABLE_MAXLENGTH) length = TABLE_MAXLENGTH; if (relocate = (length > cc->c_size)) { int l = length; /* CHECKED existing values are preserved */ cc->c_table = grow_withdata(&length, &cc->c_length, &cc->c_size, cc->c_table, TABLE_INISIZE, cc->c_tableini, sizeof(*cc->c_table)); if (length == l) cc->c_table = grow_nodata(&length, &cc->c_size, cc->c_cache, TABLE_INISIZE, cc->c_cacheini, sizeof(*cc->c_cache)); if (length != l) { if (cc->c_table != cc->c_tableini) freebytes(cc->c_table, cc->c_size * sizeof(*cc->c_table)); if (cc->c_cache != cc->c_cacheini) freebytes(cc->c_cache, cc->c_size * sizeof(*cc->c_cache)); cc->c_size = length = TABLE_INISIZE; cc->c_table = cc->c_tableini; cc->c_cache = cc->c_cacheini; } } cc->c_length = length; /* CHECKED values at common indices are preserved */ /* CHECKED rewinding neither head, nor loadndx -- both are preserved, although there is a bug in handling of 'prev' after the head overflows due to shrinking. */ tablecommon_modified(cc, relocate); } static void tablecommon_cacheupdate(t_tablecommon *cc) { int ndx = cc->c_length, sum = 0, mn, mx; int *tptr = cc->c_table, *cptr = cc->c_cache; mn = mx = *tptr; while (ndx--) { int v = *tptr++; *cptr++ = (sum += v); if (mn > v) mn = v; else if (mx < v) mx = v; } cc->c_cachesum = sum; cc->c_cachemin = mn; cc->c_cachemax = mx; cc->c_cacheisfresh = 1; } static int tablecommon_quantile(t_tablecommon *cc, float f) { /* CHECKME */ float fv; int ndx, *ptr, nmx = cc->c_length - 1; if (!cc->c_cacheisfresh) tablecommon_cacheupdate(cc); fv = f * cc->c_cachesum; for (ndx = 0, ptr = cc->c_cache; ndx < nmx; ndx++, ptr++) if (*ptr >= fv) break; return (ndx); } static void tablecommon_fromatoms(t_tablecommon *cc, int ac, t_atom *av) { int i, size = 0, nsyms = 0; t_atom *ap; int *ptr; cc->c_increation = 1; for (i = 0, ap = av; i < ac; i++, ap++) { if (ap->a_type == A_FLOAT) size++; else if (ap->a_type == A_SYMBOL) nsyms++, size++; } if (size < ac) loud_warning(0, "Table", "%d invalid atom%s ignored", ac - size, (ac - size > 1 ? "s" : "")); if (nsyms) loud_warning(0, "Table", "%d symbol%s bashed to zero", nsyms, (nsyms > 1 ? "s" : "")); tablecommon_setlength(cc, size); size = cc->c_length; ptr = cc->c_table; for (i = 0; i < ac; i++, av++) { if (av->a_type == A_FLOAT) *ptr++ = (int)av->a_w.w_float; else if (av->a_type == A_SYMBOL) *ptr++ = 0; else continue; if (size-- == 1) break; } while (size--) *ptr++ = 0; cc->c_increation = 0; } /* FIXME keep int precision: save/load directly, not through a bb */ /* LATER binary files */ static void tablecommon_doread(t_tablecommon *cc, t_symbol *fn, t_canvas *cv) { t_binbuf *bb = binbuf_new(); int ac; t_atom *av; char buf[MAXPDSTRING]; if (!fn) return; /* CHECKME complaint */ /* FIXME use open_via_path() */ if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg */ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } binbuf_read(bb, buf, "", 0); if ((ac = binbuf_getnatom(bb)) && (av = binbuf_getvec(bb)) && av->a_type == A_SYMBOL && av->a_w.w_symbol == gensym("table")) { tablecommon_fromatoms(cc, ac - 1, av + 1); post("Table: %s read successful", fn->s_name); /* CHECKME */ } #if 0 /* FIXME */ else /* CHECKME complaint */ loud_error((t_pd *)cc, "invalid file %s", fn->s_name); #endif binbuf_free(bb); } static void tablecommon_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { tablecommon_doread((t_tablecommon *)z, fn, 0); } static void tablecommon_dowrite(t_tablecommon *cc, t_symbol *fn, t_canvas *cv) { t_binbuf *bb = binbuf_new(); char buf[MAXPDSTRING]; int ndx, *ptr; if (!fn) return; /* CHECKME complaint */ if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'write' w/o arg */ canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } binbuf_addv(bb, "s", atom_getsymbol(binbuf_getvec(cc->c_refs->x_ob.te_binbuf))); for (ndx = 0, ptr = cc->c_table; ndx < cc->c_length; ndx++, ptr++) binbuf_addv(bb, "i", *ptr); binbuf_write(bb, buf, "", 0); binbuf_free(bb); } static void tablecommon_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { tablecommon_dowrite((t_tablecommon *)z, fn, 0); } static void table_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) { t_table *x = (t_table *)z; t_tablecommon *cc = x->x_common; if (cc->c_embedflag) { int ndx = 0, left = cc->c_length; int *ptr = cc->c_table; binbuf_addv(bb, "ssi;", bindsym, gensym("size"), cc->c_length); binbuf_addv(bb, "ssiiii;", bindsym, gensym("flags"), 1, cc->c_dontsaveflag, cc->c_notenamesflag, cc->c_signedflag); binbuf_addv(bb, "ssi;", bindsym, gensym("tabrange"), cc->c_range); binbuf_addv(bb, "ssiiiii;", bindsym, gensym("_coords"), cc->c_left, cc->c_top, cc->c_right, cc->c_bottom, cc->c_visflag); while (left > 0) { int cnt = (left > 128 ? 128 : left); left -= cnt; ndx += cnt; binbuf_addv(bb, "ssi", bindsym, gensym("set"), ndx); while (cnt--) { t_atom at; SETFLOAT(&at, (float)*ptr); binbuf_add(bb, 1, &at); ptr++; } binbuf_addsemi(bb); } } } static void tablecommon_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) { tablecommon_fromatoms((t_tablecommon *)z, ac, av); } static void tablecommon_free(t_tablecommon *cc) { if (cc->c_table != cc->c_tableini) freebytes(cc->c_table, cc->c_size * sizeof(*cc->c_table)); if (cc->c_cache != cc->c_cacheini) freebytes(cc->c_cache, cc->c_size * sizeof(*cc->c_cache)); } static void *tablecommon_new(void) { t_tablecommon *cc = (t_tablecommon *)pd_new(tablecommon_class); cc->c_visflag = 0; cc->c_embedflag = 0; cc->c_dontsaveflag = 0; cc->c_notenamesflag = 0; cc->c_signedflag = 0; cc->c_size = TABLE_INISIZE; cc->c_length = TABLE_DEFLENGTH; cc->c_table = cc->c_tableini; cc->c_cache = cc->c_cacheini; cc->c_cacheisfresh = 0; return (cc); } static t_tablecommon *table_checkcommon(t_table *x) { if (x->x_name && x->x_common != (t_tablecommon *)pd_findbyclass(x->x_name, tablecommon_class)) { loudbug_bug("table_checkcommon"); return (0); } return (x->x_common); } static void table_unbind(t_table *x) { /* LATER consider calling table_checkcommon(x) */ t_tablecommon *cc = x->x_common; t_table *prev, *next; if ((prev = cc->c_refs) == x) { if (!(cc->c_refs = x->x_next)) { hammerfile_free(cc->c_filehandle); tablecommon_free(cc); if (x->x_name) pd_unbind(&cc->c_pd, x->x_name); pd_free(&cc->c_pd); } } else if (prev) { while (next = prev->x_next) { if (next == x) { prev->x_next = next->x_next; break; } prev = next; } } x->x_common = 0; x->x_name = 0; x->x_next = 0; } static void table_bind(t_table *x, t_symbol *name) { t_tablecommon *cc = 0; if (name == &s_) name = 0; else if (name) cc = (t_tablecommon *)pd_findbyclass(name, tablecommon_class); if (!cc) { cc = (t_tablecommon *)tablecommon_new(); cc->c_refs = 0; cc->c_increation = 0; if (name) { pd_bind(&cc->c_pd, name); /* LATER rethink canvas unpredictability */ tablecommon_doread(cc, name, x->x_glist); } else { cc->c_filename = 0; cc->c_lastcanvas = 0; } cc->c_filehandle = hammerfile_new((t_pd *)cc, 0, tablecommon_readhook, tablecommon_writehook, tablecommon_editorhook); } x->x_common = cc; x->x_name = name; x->x_next = cc->c_refs; cc->c_refs = x; } static int table_rebind(t_table *x, t_symbol *name) { t_tablecommon *cc; if (name && name != &s_ && (cc = (t_tablecommon *)pd_findbyclass(name, tablecommon_class))) { table_unbind(x); x->x_common = cc; x->x_name = name; x->x_next = cc->c_refs; cc->c_refs = x; return (1); } else return (0); } static void table_dooutput(t_table *x, int ndx) { outlet_float(((t_object *)x)->ob_outlet, (t_float)tablecommon_getvalue(x->x_common, ndx)); } static void table_bang(t_table *x) { /* CHECKME */ outlet_float(((t_object *)x)->ob_outlet, (t_float)tablecommon_quantile(x->x_common, rand_unipolar(&x->x_seed))); } static void table_float(t_table *x, t_float f) { if (x->x_loadflag) { /* CHECKME */ if (tablecommon_loadvalue(x->x_common, x->x_loadndx, (int)f)) x->x_loadndx++; } else { int ndx = (int)f; /* CHECKED floats are truncated */ if (x->x_valueset) { tablecommon_setvalue(x->x_common, ndx, x->x_value); x->x_valueset = 0; } else table_dooutput(x, ndx); /* CHECKED head is not updated */ } } static void table_ft1(t_table *x, t_floatarg f) { x->x_value = (int)f; /* CHECKED floats are truncated */ x->x_valueset = 1; } static void table_size(t_table *x, t_floatarg f) { tablecommon_setlength(x->x_common, (int)f); } static void table_set(t_table *x, t_symbol *s, int ac, t_atom *av) { if (ac > 1 && av->a_type == A_FLOAT) { int ndx = tablecommon_getindex(x->x_common, (int)av->a_w.w_float); tablecommon_setatoms(x->x_common, ndx, ac - 1, av + 1); } } static void table_flags(t_table *x, t_symbol *s, int ac, t_atom *av) { t_tablecommon *cc = x->x_common; int i = 0, v; while (ac && av->a_type == A_FLOAT && loud_checkint((t_pd *)x, av->a_w.w_float, &v, gensym("flags"))) { /* CHECKED order, modifying only explicitly specified flags */ if (i == 0) cc->c_embedflag = (v != 0); else if (i == 1) cc->c_dontsaveflag = (v != 0); else if (i == 2) cc->c_notenamesflag = (v != 0); else if (i == 3) cc->c_signedflag = (v != 0); else break; i++; ac--; av++; } } static void table_tabrange(t_table *x, t_floatarg f) { int i = (int)f; x->x_common->c_range = (i > TABLE_MINRANGE ? i : TABLE_MINRANGE); } static void table__coords(t_table *x, t_floatarg fl, t_floatarg ft, t_floatarg fr, t_floatarg fb, t_floatarg fv) { t_tablecommon *cc = x->x_common; /* FIXME constraints */ cc->c_left = (int)fl; cc->c_top = (int)ft; cc->c_right = (int)fr; cc->c_bottom = (int)fb; cc->c_visflag = ((int)fv != 0); } static void table_cancel(t_table *x) { x->x_valueset = 0; } static void table_clear(t_table *x) { tablecommon_setall(x->x_common, 0); /* CHECKED head preserved */ } static void table_const(t_table *x, t_floatarg f) { tablecommon_setall(x->x_common, (int)f); /* CHECKED head preserved */ } static void table_load(t_table *x) { x->x_loadflag = 1; x->x_loadndx = 0; /* CHECKED rewind, head not affected */ } static void table_normal(t_table *x) { x->x_loadflag = 0; } static void table_next(t_table *x) { if (!x->x_intraversal) x->x_intraversal = 1; else if (++x->x_head >= x->x_common->c_length) x->x_head = 0; table_dooutput(x, x->x_head); } static void table_prev(t_table *x) { if (!x->x_intraversal) x->x_intraversal = 1; else if (--x->x_head < 0) x->x_head = x->x_common->c_length - 1; table_dooutput(x, x->x_head); } static void table_goto(t_table *x, t_floatarg f) { /* CHECKED floats are truncated */ x->x_head = tablecommon_getindex(x->x_common, (int)f); /* CHECKED the head should be pre-updated during traversal, in order to maintain the logical way of direction change. Therefore, we need the flag below, which locks head in place that has just been set by goto. The flag is then set by next or prev. */ x->x_intraversal = 0; } static void table_send(t_table *x, t_symbol *s, int ac, t_atom *av) { if (ac > 1 && av->a_type == A_SYMBOL) { t_symbol *target = av->a_w.w_symbol; if (!target->s_thing) return; /* CHECKED no complaint */ ac--; av++; if (av->a_type == A_FLOAT) { if (ac == 1) { int ndx = (int)av->a_w.w_float; pd_float(target->s_thing, (t_float)tablecommon_getvalue(x->x_common, ndx)); } /* CHECKED incompatible: 'send ' stores at (a bug?) */ } else if (av->a_type == A_SYMBOL) { /* CHECKED 'send length' works, but not max, min, sum... */ if (av->a_w.w_symbol == gensym("length")) pd_float(target->s_thing, (t_float)x->x_common->c_length); } } } static void table_length(t_table *x) { outlet_float(((t_object *)x)->ob_outlet, (t_float)x->x_common->c_length); } static void table_sum(t_table *x) { t_tablecommon *cc = x->x_common; if (!cc->c_cacheisfresh) tablecommon_cacheupdate(cc); outlet_float(((t_object *)x)->ob_outlet, (t_float)cc->c_cachesum); } static void table_min(t_table *x) { t_tablecommon *cc = x->x_common; if (!cc->c_cacheisfresh) tablecommon_cacheupdate(cc); outlet_float(((t_object *)x)->ob_outlet, (t_float)cc->c_cachemin); } static void table_max(t_table *x) { t_tablecommon *cc = x->x_common; if (!cc->c_cacheisfresh) tablecommon_cacheupdate(cc); outlet_float(((t_object *)x)->ob_outlet, (t_float)cc->c_cachemax); } static void table_getbits(t_table *x, t_floatarg f1, t_floatarg f2, t_floatarg f3) { /* FIXME */ } static void table_setbits(t_table *x, t_floatarg f1, t_floatarg f2, t_floatarg f3, t_floatarg f4) { /* FIXME */ } static void table_inv(t_table *x, t_floatarg f) { /* CHECKME none found, float */ int v = (int)f, ndx, *ptr, nmx = x->x_common->c_length - 1; for (ndx = 0, ptr = x->x_common->c_table; ndx < nmx; ndx++, ptr++) if (*ptr >= v) break; outlet_float(((t_object *)x)->ob_outlet, (t_float)ndx); } static void table_quantile(t_table *x, t_floatarg f) { /* CHECKME */ outlet_float(((t_object *)x)->ob_outlet, (t_float)tablecommon_quantile(x->x_common, f / ((float)TABLE_MAXQ))); } static void table_fquantile(t_table *x, t_floatarg f) { /* CHECKME constraints */ outlet_float(((t_object *)x)->ob_outlet, (t_float)tablecommon_quantile(x->x_common, f)); } static void table_dump(t_table *x, t_symbol *s, int ac, t_atom *av) { t_tablecommon *cc = x->x_common; int thelength = cc->c_length; int *thetable = cc->c_table; t_outlet *out = ((t_object *)x)->ob_outlet; int ndx, nmx, *ptr; /* CHECKED optional arguments: from, to, Negative 'from' causes invalid output, symbols are bashed to zero for both arguments, inconsistent warnings, etc. -- no strict emulation attempted below. */ if (ac && av->a_type == A_FLOAT) ndx = tablecommon_getindex(cc, (int)av->a_w.w_float); else ndx = 0; if (ac > 1 && av[1].a_type == A_FLOAT) nmx = tablecommon_getindex(cc, (int)av[1].a_w.w_float); else nmx = thelength - 1; for (ptr = thetable + ndx; ndx <= nmx; ndx++, ptr++) { /* Plain traversing by incrementing a pointer is not robust, because calling outlet_float() may invalidate the pointer. Continous storage does not require generic selfmod detection (ala coll), so we can get away with the simpler test below. */ if (cc->c_length != thelength || cc->c_table != thetable) break; /* CHECKED no remote dumping */ outlet_float(out, (t_float)*ptr); } } static void table_refer(t_table *x, t_symbol *s) { if (!table_rebind(x, s)) { /* LATER consider complaining */ } } static void table_read(t_table *x, t_symbol *s) { t_tablecommon *cc = x->x_common; if (s && s != &s_) tablecommon_doread(cc, s, x->x_glist); else hammerpanel_open(cc->c_filehandle, 0); } static void table_write(t_table *x, t_symbol *s) { t_tablecommon *cc = x->x_common; if (s && s != &s_) tablecommon_dowrite(cc, s, x->x_glist); else hammerpanel_save(cc->c_filehandle, 0, 0); } static int tablecommon_editorappend(t_tablecommon *cc, int v, char *buf, int col) { char *bp = buf; int cnt = 0; if (col > 0) *bp++ = ' ', cnt++; cnt += sprintf(bp, "%d", v); if (col + cnt > 80) buf[0] = '\n', col = cnt - 1; /* assuming col > 0 */ else col += cnt; hammereditor_append(cc->c_filehandle, buf); return (col); } static void table_open(t_table *x) { t_tablecommon *cc = x->x_common; char buf[MAXPDSTRING]; int *bp = cc->c_table; int count = cc->c_length, col = 0; hammereditor_open(cc->c_filehandle, (x->x_name ? x->x_name->s_name : 0), 0); while (count--) col = tablecommon_editorappend(cc, *bp++, buf, col); hammereditor_setdirty(cc->c_filehandle, 0); } static void table_wclose(t_table *x) { hammereditor_close(x->x_common->c_filehandle, 1); } static void table_click(t_table *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { table_open(x); } #ifdef TABLE_DEBUG static void table_debug(t_table *x, t_floatarg f) { t_tablecommon *cc = table_checkcommon(x); if (cc) { t_table *x1 = cc->c_refs; int i = 0; while (x1) i++, x1 = x1->x_next; loudbug_post("refcount %d", i); } } #endif static void table_free(t_table *x) { hammerfile_free(x->x_filehandle); table_unbind(x); } static void *table_new(t_symbol *s) { t_table *x = (t_table *)pd_new(table_class); static int warned = 0; if (!warned) { loud_warning((t_pd *)x, 0, "Table is not ready yet"); warned = 1; } x->x_glist = canvas_getcurrent(); x->x_valueset = 0; x->x_head = 0; x->x_intraversal = 0; /* CHECKED */ x->x_loadflag = 0; rand_seed(&x->x_seed, 0); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_float); x->x_bangout = outlet_new((t_object *)x, &s_bang); x->x_filehandle = hammerfile_new((t_pd *)x, table_embedhook, 0, 0, 0); table_bind(x, s); return (x); } void Table_setup(void) { table_class = class_new(gensym("Table"), (t_newmethod)table_new, (t_method)table_free, sizeof(t_table), 0, A_DEFSYM, 0); class_addbang(table_class, table_bang); class_addfloat(table_class, table_float); class_addmethod(table_class, (t_method)table_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_size, gensym("size"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_set, gensym("set"), A_GIMME, 0); class_addmethod(table_class, (t_method)table_flags, gensym("flags"), A_GIMME, 0); class_addmethod(table_class, (t_method)table_tabrange, gensym("tabrange"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table__coords, gensym("_coords"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); class_addmethod(table_class, (t_method)table_cancel, gensym("cancel"), 0); class_addmethod(table_class, (t_method)table_clear, gensym("clear"), 0); class_addmethod(table_class, (t_method)table_const, gensym("const"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_load, gensym("load"), 0); class_addmethod(table_class, (t_method)table_normal, gensym("normal"), 0); class_addmethod(table_class, (t_method)table_next, gensym("next"), 0); class_addmethod(table_class, (t_method)table_prev, gensym("prev"), 0); class_addmethod(table_class, (t_method)table_goto, gensym("goto"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_send, gensym("send"), A_GIMME, 0); class_addmethod(table_class, (t_method)table_length, gensym("length"), 0); class_addmethod(table_class, (t_method)table_sum, gensym("sum"), 0); class_addmethod(table_class, (t_method)table_min, gensym("min"), 0); class_addmethod(table_class, (t_method)table_max, gensym("max"), 0); class_addmethod(table_class, (t_method)table_getbits, gensym("getbits"), A_FLOAT, A_FLOAT, A_FLOAT, 0); class_addmethod(table_class, (t_method)table_setbits, gensym("setbits"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); class_addmethod(table_class, (t_method)table_inv, gensym("inv"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_quantile, gensym("quantile"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_fquantile, gensym("fquantile"), A_FLOAT, 0); class_addmethod(table_class, (t_method)table_dump, gensym("dump"), A_GIMME, 0); class_addmethod(table_class, (t_method)table_refer, gensym("refer"), A_SYMBOL, 0); class_addmethod(table_class, (t_method)table_read, gensym("read"), A_DEFSYM, 0); class_addmethod(table_class, (t_method)table_write, gensym("write"), A_DEFSYM, 0); class_addmethod(table_class, (t_method)table_open, gensym("open"), 0); class_addmethod(table_class, (t_method)table_wclose, gensym("wclose"), 0); class_addmethod(table_class, (t_method)table_click, gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); #ifdef TABLE_DEBUG class_addmethod(table_class, (t_method)table_debug, gensym("debug"), A_DEFFLOAT, 0); #endif hammerfile_setup(table_class, 1); tablecommon_class = class_new(gensym("Table"), 0, 0, sizeof(t_tablecommon), CLASS_PD, 0); /* this call is a nop (tablecommon does not embed, and the hammerfile class itself has been already set up above), but it is better to have it around, just in case... */ hammerfile_setup(tablecommon_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/prob.c0000644000076500007650000002107111466617445016753 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #include "common/rand.h" #include "hammer/file.h" /* CHECKED: no preallocation. It looks like if new state-entries were added to the list's head, and new transition-entries were added to the sublist's head. No sorting of any kind. */ #ifdef KRZYSZCZ //#define PROB_DEBUG #endif typedef struct _probtrans { int tr_value; /* state (if a header trans), or suffix value (otherwise) */ int tr_count; /* (a total in case of a header trans) */ struct _probtrans *tr_suffix; /* header trans of a suffix state */ struct _probtrans *tr_nexttrans; /* next trans of this state */ struct _probtrans *tr_nextstate; /* header trans of a next state */ } t_probtrans; typedef struct _prob { t_object x_ob; t_probtrans *x_translist; t_probtrans *x_state; t_probtrans *x_default; int x_embedmode; int x_silent; unsigned int x_seed; t_outlet *x_bangout; t_hammerfile *x_filehandle; } t_prob; static t_class *prob_class; static t_probtrans *prob_findstate(t_prob *x, int value, int complain) { t_probtrans *state; for (state = x->x_translist; state; state = state->tr_nextstate) if (state->tr_value == value) break; if (!state && complain && !x->x_silent) loud_error((t_pd *)x, "no state %d", value); /* CHECKED */ return (state); } static void prob_reset(t_prob *x, t_floatarg f) { int value = (int)f; /* CHECKED: float converted to int */ t_probtrans *state = prob_findstate(x, value, 1); if (state) /* CHECKED */ { x->x_default = state; /* CHECKED (sort of): */ if (!x->x_state->tr_nexttrans) x->x_state = state; } } static void prob_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) { t_prob *x = (t_prob *)z; if (x->x_embedmode) { t_probtrans *pfx, *sfx; for (pfx = x->x_translist; pfx; pfx = pfx->tr_nextstate) for (sfx = pfx->tr_nexttrans; sfx; sfx = sfx->tr_nexttrans) binbuf_addv(bb, "siii;", bindsym, pfx->tr_value, sfx->tr_value, sfx->tr_count); binbuf_addv(bb, "ssi;", bindsym, gensym("embed"), 1); if (x->x_default) binbuf_addv(bb, "ssi;", bindsym, gensym("reset"), x->x_default->tr_value); } } static void prob_embed(t_prob *x, t_floatarg f) { x->x_embedmode = ((int)f != 0); } static void prob_clear(t_prob *x) { t_probtrans *state, *nextstate; for (state = x->x_translist; state; state = nextstate) { t_probtrans *trans, *nexttrans; for (trans = state->tr_nexttrans; trans; trans = nexttrans) { nexttrans = trans->tr_nexttrans; freebytes(trans, sizeof(*trans)); } nextstate = state->tr_nextstate; freebytes(state, sizeof(*state)); } x->x_translist = 0; x->x_state = 0; x->x_default = 0; /* CHECKED: default number is not kept */ /* CHECKED embedmode is kept */ } /* CHECKED */ static void prob_dump(t_prob *x) { t_probtrans *state; post("transition probabilities:"); for (state = x->x_translist; state; state = state->tr_nextstate) { t_probtrans *trans; for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans) post(" from %3d to %3d: %d", state->tr_value, trans->tr_value, trans->tr_count); /* CHECKED: dead-ends are reported */ post("total weights for state %d: %d", state->tr_value, state->tr_count); } } static void prob_bang(t_prob *x) { if (x->x_state) /* CHECKED: no output after clear */ { int rnd = rand_int(&x->x_seed, x->x_state->tr_count); t_probtrans *trans = x->x_state->tr_nexttrans; if (trans) { for (trans = x->x_state->tr_nexttrans; trans; trans = trans->tr_nexttrans) if ((rnd -= trans->tr_count) < 0) break; if (trans) { t_probtrans *nextstate = trans->tr_suffix; if (nextstate) { outlet_float(((t_object *)x)->ob_outlet, nextstate->tr_value); x->x_state = nextstate; } else loudbug_bug("prob_bang: void suffix"); } else loudbug_bug("prob_bang: search overflow"); } else { outlet_bang(x->x_bangout); if (x->x_default) /* CHECKED: stays at dead-end if no default */ x->x_state = x->x_default; } } } static void prob_float(t_prob *x, t_float f) { int value; if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */ { t_probtrans *state = prob_findstate(x, value, 1); if (state) /* CHECKED */ x->x_state = state; } } static void prob_list(t_prob *x, t_symbol *s, int ac, t_atom *av) { int prefval, suffval, count; if (ac == 3 && av->a_type == A_FLOAT && av[1].a_type == A_FLOAT && av[2].a_type == A_FLOAT && (prefval = (int)av->a_w.w_float) == av->a_w.w_float && (suffval = (int)av[1].a_w.w_float) == av[1].a_w.w_float && (count = (int)av[2].a_w.w_float) == av[2].a_w.w_float) { t_probtrans *prefix = prob_findstate(x, prefval, 0); t_probtrans *suffix = prob_findstate(x, suffval, 0); t_probtrans *trans; if (prefix && suffix) { for (trans = prefix->tr_nexttrans; trans; trans = trans->tr_nexttrans) if (trans->tr_suffix == suffix) break; if (trans) { /* the transition already exists... */ prefix->tr_count += (count - trans->tr_count); trans->tr_count = count; return; } } if (!prefix) { if (!(prefix = getbytes(sizeof(*prefix)))) return; prefix->tr_value = prefval; prefix->tr_count = 0; prefix->tr_suffix = 0; prefix->tr_nexttrans = 0; prefix->tr_nextstate = x->x_translist; x->x_translist = prefix; if (suffval == prefval) suffix = prefix; } if (!suffix) { if (!(suffix = getbytes(sizeof(*suffix)))) return; suffix->tr_value = suffval; suffix->tr_count = 0; suffix->tr_suffix = 0; suffix->tr_nexttrans = 0; suffix->tr_nextstate = x->x_translist; x->x_translist = suffix; } if (trans = getbytes(sizeof(*trans))) { trans->tr_value = suffval; trans->tr_count = count; trans->tr_suffix = suffix; trans->tr_nexttrans = prefix->tr_nexttrans; trans->tr_nextstate = prefix->tr_nextstate; prefix->tr_count += count; prefix->tr_nexttrans = trans; } if (!x->x_state) /* CHECKED */ x->x_state = prefix; /* CHECKED */ } else loud_error((t_pd *)x, "bad list message format"); /* CHECKED */ } static void prob__silent(t_prob *x) { if (!x->x_silent) { fittermax_warning(prob_class, "no '_silent' message in max"); x->x_silent = 1; } } /* CHECKED not available, LATER full editing */ static void prob_click(t_prob *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { t_probtrans *state; char buf[64]; hammereditor_open(x->x_filehandle, 0, 0); for (state = x->x_translist; state; state = state->tr_nextstate) { t_probtrans *trans; for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans) { sprintf(buf, "%d %d %d\n", state->tr_value, trans->tr_value, trans->tr_count); hammereditor_append(x->x_filehandle, buf); } } } static void prob_free(t_prob *x) { prob_clear(x); hammerfile_free(x->x_filehandle); } static void *prob_new(void) { t_prob *x = (t_prob *)pd_new(prob_class); x->x_translist = 0; x->x_state = 0; x->x_default = 0; x->x_embedmode = 0; /* CHECKED */ x->x_silent = 0; rand_seed(&x->x_seed, 0); outlet_new((t_object *)x, &s_float); x->x_bangout = outlet_new((t_object *)x, &s_bang); x->x_filehandle = hammerfile_new((t_pd *)x, prob_embedhook, 0, 0, 0); return (x); } void prob_setup(void) { prob_class = class_new(gensym("prob"), (t_newmethod)prob_new, (t_method)prob_free, sizeof(t_prob), 0, 0); class_addbang(prob_class, prob_bang); class_addfloat(prob_class, prob_float); class_addlist(prob_class, prob_list); class_addmethod(prob_class, (t_method)prob_embed, gensym("embed"), A_FLOAT, 0); class_addmethod(prob_class, (t_method)prob_reset, gensym("reset"), A_FLOAT, 0); class_addmethod(prob_class, (t_method)prob_clear, gensym("clear"), 0); class_addmethod(prob_class, (t_method)prob_dump, gensym("dump"), 0); /* CHECKED: doesn't understand "seed" */ class_addmethod(prob_class, (t_method)prob__silent, gensym("_silent"), 0); class_addmethod(prob_class, (t_method)prob_click, gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); hammerfile_setup(prob_class, 1); fitter_setup(prob_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/prepend.c0000644000076500007650000002233311466617445017450 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" #include "common/fitter.h" #define PREPEND_INISIZE 32 /* LATER rethink */ #define PREPEND_MAXSIZE 256 typedef struct _prepend { t_object x_ob; t_symbol *x_selector; int x_size; /* as allocated */ int x_natoms; /* as used */ t_atom *x_message; t_atom x_messini[PREPEND_INISIZE]; int x_entered; int x_auxsize; t_atom *x_auxbuf; t_pd *x_proxy; } t_prepend; typedef struct _prependxy { t_pd xy_pd; t_prepend *xy_owner; } t_prependxy; static t_class *prepend_class; static t_class *prependxy_class; static int prepend_iscompatible = 0; /* FIXME per-object */ /* Usually a preallocation method is used, except in special cases of: 1) reentrant output request, or 2) an output request which would cause resizing to more than MAXSIZE (no such limit for a 'set' message). In both special cases, a temporary output buffer is allocated. A separately preallocated output buffer is not used, thus avoiding memcpying of the stored message (a small performance gain when the preallocation method is chosen). Instead, self-invoked 'set' messages are postponed, using an auxiliary buffer. */ /* called only from prepend_doanything() */ static void prepend_dooutput(t_prepend *x, int ac, t_atom *av) { if (x->x_selector == &s_float) { if (ac > 1) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); } else if (x->x_selector == &s_list) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else /* x->x_selector guaranteed non-empty */ /* CHECKED: 'bang' is prepended -- we cannot do so... ('symbol' cannot be compatible too) */ outlet_anything(((t_object *)x)->ob_outlet, x->x_selector, ac, av); } static void prepend_doanything(t_prepend *x, t_symbol *s, int ac, t_atom *av) { int reentered = x->x_entered; x->x_entered = 1; if (s == &s_) s = 0; if (s || x->x_natoms) { int prealloc = !reentered; int ntotal = x->x_natoms + ac; t_atom *buf; if (s) ntotal++; if (prealloc && ntotal > x->x_size) { if (ntotal > PREPEND_MAXSIZE) prealloc = 0; else { int nrequested = ntotal; x->x_message = grow_withdata(&nrequested, &x->x_natoms, &x->x_size, x->x_message, PREPEND_INISIZE, x->x_messini, sizeof(*x->x_message)); prealloc = (nrequested == ntotal); } } if (prealloc) { buf = x->x_message + x->x_natoms; if (s) { SETSYMBOL(buf, s); buf++; } if (ac) memcpy(buf, av, ac * sizeof(*buf)); prepend_dooutput(x, ntotal, x->x_message); } else { /* LATER consider using the stack if ntotal <= MAXSTACK */ if (buf = getbytes(ntotal * sizeof(*buf))) { t_atom *bp = buf + x->x_natoms; if (x->x_natoms) memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf)); if (s) { SETSYMBOL(bp, s); bp++; } if (ac) memcpy(bp, av, ac * sizeof(*bp)); prepend_dooutput(x, ntotal, buf); freebytes(buf, ntotal * sizeof(*buf)); } } } else prepend_dooutput(x, ac, av); if (!reentered) { x->x_entered = 0; if (x->x_auxbuf) { if (x->x_auxsize <= x->x_size) { x->x_natoms = x->x_auxsize / 2; memcpy(x->x_message, x->x_auxbuf, x->x_natoms * sizeof(*x->x_message)); freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); } else { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); x->x_size = x->x_auxsize; x->x_message = x->x_auxbuf; x->x_natoms = x->x_auxsize / 2; } x->x_auxbuf = 0; } } } static void prepend_bang(t_prepend *x) { if (x->x_selector) { if (prepend_iscompatible) { t_atom at; SETSYMBOL(&at, &s_bang); /* CHECKED */ prepend_doanything(x, 0, 1, &at); } else prepend_doanything(x, 0, 0, 0); } else outlet_bang(((t_object *)x)->ob_outlet); } static void prepend_float(t_prepend *x, t_float f) { if (x->x_selector) { t_atom at; SETFLOAT(&at, f); prepend_doanything(x, 0, 1, &at); } else outlet_float(((t_object *)x)->ob_outlet, f); } static void prepend_symbol(t_prepend *x, t_symbol *s) { if (x->x_selector) { t_atom at; SETSYMBOL(&at, s); prepend_doanything(x, 0, 1, &at); } else outlet_symbol(((t_object *)x)->ob_outlet, s); } /* LATER gpointer */ static void prepend_list(t_prepend *x, t_symbol *s, int ac, t_atom *av) { if (x->x_selector) prepend_doanything(x, 0, ac, av); else outlet_list(((t_object *)x)->ob_outlet, s, ac, av); } static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av) { if (x->x_selector) prepend_doanything(x, s, ac, av); else outlet_anything(((t_object *)x)->ob_outlet, s, ac, av); } static void prepend_doset(t_prepend *x, t_symbol *s, int ac, t_atom *av) { if (s) x->x_selector = s; else if (ac) { if (av->a_type == A_SYMBOL) { x->x_selector = av->a_w.w_symbol; ac--; av++; } else if (av->a_type == A_FLOAT) x->x_selector = (ac > 1 ? &s_list : &s_float); else return; /* LATER rethink */ } else x->x_selector = 0; if (ac) { int newsize = ac * 2; if (x->x_entered) { if (x->x_auxbuf) { loud_warning((t_pd *)x, 0, "'set' message overridden"); freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); x->x_auxsize = 0; } if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf))) { memcpy(x->x_auxbuf, av, ac * sizeof(*x->x_auxbuf)); x->x_auxsize = newsize; } } else { t_atom *ap; if (newsize > x->x_size) { int sz = newsize; x->x_message = grow_nodata(&sz, &x->x_size, x->x_message, PREPEND_INISIZE, x->x_messini, sizeof(*x->x_message)); if (sz != newsize) ac = sz / 2; /* LATER rethink */ } x->x_natoms = ac; ap = x->x_message; while (ac--) *ap++ = *av++; } } else x->x_natoms = 0; } static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av) { if (x->x_proxy) prepend_anything(x, s, ac, av); else /* LATER (when?) controlled by maxmode */ prepend_doset(x, 0, ac, av); } static void prependxy_bang(t_prependxy *xy) { prepend_doset(xy->xy_owner, 0, 0, 0); /* LATER rethink */ } static void prependxy_float(t_prependxy *xy, t_float f) { t_atom at; SETFLOAT(&at, f); prepend_doset(xy->xy_owner, &s_float, 1, &at); } static void prependxy_symbol(t_prependxy *xy, t_symbol *s) { prepend_doset(xy->xy_owner, (s && s != &s_ ? s : &s_symbol), 0, 0); /* LATER rethink */ } static void prependxy_list(t_prependxy *xy, t_symbol *s, int ac, t_atom *av) { prepend_doset(xy->xy_owner, &s_list, ac, av); /* LATER rethink */ } static void prependxy_anything(t_prependxy *xy, t_symbol *s, int ac, t_atom *av) { prepend_doset(xy->xy_owner, s, ac, av); } static void prepend_free(t_prepend *x) { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); if (x->x_auxbuf) { loudbug_bug("prepend_free"); /* LATER rethink */ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); } if (x->x_proxy) pd_free(x->x_proxy); } static void *prepend_new(t_symbol *s, int ac, t_atom *av) { t_prepend *x = (t_prepend *)pd_new(prepend_class); x->x_selector = 0; x->x_size = PREPEND_INISIZE; x->x_natoms = 0; x->x_message = x->x_messini; x->x_auxbuf = 0; x->x_entered = 0; if (ac) { x->x_proxy = 0; prepend_doset(x, 0, ac, av); } else { if (prepend_iscompatible) /* CHECKED in max an object without an outlet is created, and there is no warning when loading from a file. */ fittermax_warning(prepend_class, "creating an object without an argument"); x->x_proxy = pd_new(prependxy_class); ((t_prependxy *)x->x_proxy)->xy_owner = x; inlet_new((t_object *)x, x->x_proxy, 0, 0); } outlet_new((t_object *)x, &s_anything); return (x); } static void prepend_fitter(void) { prepend_iscompatible = fittermax_get(); } void prepend_setup(void) { prepend_class = class_new(gensym("prepend"), (t_newmethod)prepend_new, (t_method)prepend_free, sizeof(t_prepend), 0, A_GIMME, 0); class_addbang(prepend_class, prepend_bang); class_addfloat(prepend_class, prepend_float); class_addsymbol(prepend_class, prepend_symbol); class_addlist(prepend_class, prepend_list); class_addanything(prepend_class, prepend_anything); class_addmethod(prepend_class, (t_method)prepend_set, gensym("set"), A_GIMME, 0); prependxy_class = class_new(gensym("prepend"), 0, 0, sizeof(t_prependxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(prependxy_class, prependxy_bang); class_addfloat(prependxy_class, prependxy_float); class_addsymbol(prependxy_class, prependxy_symbol); class_addlist(prependxy_class, prependxy_list); class_addanything(prependxy_class, prependxy_anything); fitter_setup(prepend_class, prepend_fitter); } cyclone-0.1-alpha55/cyclone/hammer/hammer.c0000644000076500007650000000655611466617445017275 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "unstable/fragile.h" #include "common/loud.h" #include "common/port.h" #include "hammer/file.h" #include "../build_counter" void allhammers_setup(void); typedef struct _hammer { t_object x_ob; t_hammerfile *x_filehandle; } t_hammer; static t_class *hammer_class; static int hammer_firstndx; static int hammer_lastndx; static void hammer_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { int result = import_max(fn->s_name, ""); outlet_float(((t_object *)z)->ob_outlet, (t_float)result); } static void hammer_doimport(t_hammer *x, t_symbol *fn) { if (fn && fn != &s_) { t_symbol *dir = hammerpanel_getopendir(x->x_filehandle); int result = import_max(fn->s_name, (dir && dir != &s_ ? dir->s_name : "")); outlet_float(((t_object *)x)->ob_outlet, (t_float)result); } else hammerpanel_open(x->x_filehandle, 0); } static void hammer_click(t_hammer *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { hammer_doimport(x, 0); } static void hammer_import(t_hammer *x, t_symbol *fn) { hammer_doimport(x, fn); } static void hammer_cd(t_hammer *x, t_symbol *dir) { hammerpanel_setopendir(x->x_filehandle, dir); } static void hammer_pwd(t_hammer *x, t_symbol *s) { t_symbol *dir; if (s && s->s_thing && (dir = hammerpanel_getopendir(x->x_filehandle))) pd_symbol(s->s_thing, dir); } static void hammer_bang(t_hammer *x) { fragile_class_printnames("hammer classes are: ", hammer_firstndx, hammer_lastndx); } static void hammer_free(t_hammer *x) { hammerfile_free(x->x_filehandle); } static void *hammer_new(void) { t_hammer *x = (t_hammer *)pd_new(hammer_class); x->x_filehandle = hammerfile_new((t_pd *)x, 0, hammer_readhook, 0, 0); outlet_new((t_object *)x, &s_float); return (x); } void hammer_setup(void) { if (canvas_getcurrent()) { /* Loading the library by object creation is banned, because of a danger of having some of the classes already loaded. LATER rethink. */ loud_error(0, "apparently an attempt to create a 'hammer' object"); loud_errand(0, "without having hammer library preloaded"); return; } if (zgetfn(&pd_objectmaker, gensym("hammer"))) { loud_error(0, "hammer is already loaded"); return; } if (!zgetfn(&pd_objectmaker, gensym("cyclone"))) post("this is hammer %s, %s %s build", CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); hammer_class = class_new(gensym("hammer"), (t_newmethod)hammer_new, (t_method)hammer_free, sizeof(t_hammer), 0, 0); class_addbang(hammer_class, hammer_bang); class_addmethod(hammer_class, (t_method)hammer_cd, gensym("cd"), A_DEFSYM, 0); class_addmethod(hammer_class, (t_method)hammer_pwd, gensym("pwd"), A_SYMBOL, 0); class_addmethod(hammer_class, (t_method)hammer_import, gensym("import"), A_DEFSYM, 0); class_addmethod(hammer_class, (t_method)hammer_click, gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); hammerfile_setup(hammer_class, 0); hammer_firstndx = fragile_class_count(); allhammers_setup(); hammer_lastndx = fragile_class_count() - 1; } cyclone-0.1-alpha55/cyclone/hammer/mousefilter.c0000644000076500007650000000336211466617445020352 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "hammer/gui.h" typedef struct _mousefilter { t_object x_ob; int x_isup; int x_ispending; t_float x_value; } t_mousefilter; static t_class *mousefilter_class; static void mousefilter_float(t_mousefilter *x, t_float f) { if (x->x_isup) outlet_float(((t_object *)x)->ob_outlet, f); else { x->x_ispending = 1; x->x_value = f; } } static void mousefilter_anything(t_mousefilter *x, t_symbol *s, int ac, t_atom *av) { /* dummy method, filtering out those messages from gui, which are not handled explicitly */ } static void mousefilter_doup(t_mousefilter *x, t_floatarg f) { if ((x->x_isup = (int)f) && x->x_ispending) { x->x_ispending = 0; outlet_float(((t_object *)x)->ob_outlet, x->x_value); } } static void mousefilter_free(t_mousefilter *x) { hammergui_unbindmouse((t_pd *)x); } static void *mousefilter_new(void) { t_mousefilter *x = (t_mousefilter *)pd_new(mousefilter_class); x->x_isup = 0; /* LATER rethink */ x->x_ispending = 0; outlet_new((t_object *)x, &s_float); hammergui_bindmouse((t_pd *)x); return (x); } void mousefilter_setup(void) { mousefilter_class = class_new(gensym("mousefilter"), (t_newmethod)mousefilter_new, (t_method)mousefilter_free, sizeof(t_mousefilter), 0, 0); class_addfloat(mousefilter_class, mousefilter_float); class_addanything(mousefilter_class, mousefilter_anything); class_addmethod(mousefilter_class, (t_method)mousefilter_doup, gensym("_up"), A_FLOAT, 0); } cyclone-0.1-alpha55/cyclone/hammer/midiparse.c0000644000076500007650000000633311466617445017772 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _midiparse { t_object x_ob; unsigned char x_ready; unsigned char x_status; unsigned char x_channel; unsigned char x_data1; t_outlet *x_polyout; t_outlet *x_ctlout; t_outlet *x_pgmout; t_outlet *x_touchout; t_outlet *x_bendout; t_outlet *x_chanout; } t_midiparse; static t_class *midiparse_class; static void midiparse_clear(t_midiparse *x) { x->x_status = 0; x->x_ready = 0; } static void midiparse_float(t_midiparse *x, t_float f) { int ival = (int)f; /* CHECKED */ if (ival < 0) { /* CHECKME */ return; } if (ival < 256) /* CHECKED clear if input over 255 */ { unsigned char bval = ival; if (bval & 0x80) { unsigned char status = bval & 0xF0; if (status == 0xF0) { /* CHECKED no such test in max -- this is incompatible, but real-time messages are out-of-band, and they should be ignored here. LATER rethink the 0xFE case. */ if (bval < 0xF8) midiparse_clear(x); } else { x->x_status = status; x->x_channel = bval & 0x0F; x->x_ready = (status == 0xC0 || status == 0xD0); } } else if (x->x_ready) { t_atom at[2]; x->x_ready = 0; outlet_float(x->x_chanout, x->x_channel + 1); switch (x->x_status) { case 0x80: SETFLOAT(&at[0], x->x_data1); SETFLOAT(&at[1], 0); outlet_list(((t_object *)x)->ob_outlet, 0, 2, at); break; case 0x90: SETFLOAT(&at[0], x->x_data1); SETFLOAT(&at[1], bval); outlet_list(((t_object *)x)->ob_outlet, 0, 2, at); break; case 0xA0: SETFLOAT(&at[0], bval); SETFLOAT(&at[1], x->x_data1); outlet_list(x->x_polyout, 0, 2, at); break; case 0xB0: SETFLOAT(&at[0], bval); SETFLOAT(&at[1], x->x_data1); outlet_list(x->x_ctlout, 0, 2, at); break; case 0xC0: outlet_float(x->x_pgmout, bval); x->x_ready = 1; break; case 0xD0: outlet_float(x->x_touchout, bval); x->x_ready = 1; break; case 0xE0: /* CHECKED: ignores data1 */ outlet_float(x->x_bendout, bval); break; default:; } } else if (x->x_status) { x->x_data1 = bval; /* CHECKED key #0 accepted */ x->x_ready = 1; } } else midiparse_clear(x); } static void *midiparse_new(void) { t_midiparse *x = (t_midiparse *)pd_new(midiparse_class); outlet_new((t_object *)x, &s_list); x->x_polyout = outlet_new((t_object *)x, &s_list); x->x_ctlout = outlet_new((t_object *)x, &s_list); x->x_pgmout = outlet_new((t_object *)x, &s_float); x->x_touchout = outlet_new((t_object *)x, &s_float); x->x_bendout = outlet_new((t_object *)x, &s_float); x->x_chanout = outlet_new((t_object *)x, &s_float); midiparse_clear(x); return (x); } void midiparse_setup(void) { midiparse_class = class_new(gensym("midiparse"), (t_newmethod)midiparse_new, 0, sizeof(t_midiparse), 0, 0); class_addbang(midiparse_class, midiparse_clear); class_addfloat(midiparse_class, midiparse_float); /* CHECKED autocasting lists to floats */ } cyclone-0.1-alpha55/cyclone/hammer/counter.c0000644000076500007650000002565411466617445017503 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is an entirely rewritten version of Joseph A. Sarlo's code. The most important changes are listed in "pd-lib-notes.txt" file. */ /* Beware -- the max reference manual page for the counter object reflects mostly opcode max features. Apparently counter works differently in cycling max (e.g. inlets 3 and 4). But I am sick of checking -- I will not bother, until there is some feedback. */ #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #define COUNTER_UP 0 #define COUNTER_DOWN 1 #define COUNTER_UPDOWN 2 #define COUNTER_DEFMAX 0x7fffffff /* CHECKED (man says otherwise) */ typedef struct _counter { t_object x_ob; int x_count; int x_maxcount; int x_dir; int x_inc; int x_min; int x_max; int x_carrybang; int x_minhitflag; int x_maxhitflag; t_pd *x_proxies[4]; t_outlet *x_out2; t_outlet *x_out3; t_outlet *x_out4; } t_counter; typedef struct _counter_proxy { t_object p_ob; t_counter *p_master; void (*p_bangmethod)(t_counter *x); void (*p_floatmethod)(t_counter *x, t_float f); } t_counter_proxy; static t_class *counter_class; static t_class *counter_proxy_class; static void counter_up(t_counter *x) { x->x_dir = COUNTER_UP; x->x_inc = 1; } static void counter_down(t_counter *x) { /* CHECKED: no explicit minimum needed */ x->x_dir = COUNTER_DOWN; x->x_inc = -1; } static void counter_updown(t_counter *x) { /* CHECKED: neither explicit maximum, nor minimum needed */ x->x_dir = COUNTER_UPDOWN; /* CHECKED: x->x_inc unchanged (continuation) */ } static void counter_dir(t_counter *x, t_floatarg f) { switch ((int)f) { case COUNTER_UP: counter_up(x); break; case COUNTER_DOWN: counter_down(x); break; case COUNTER_UPDOWN: counter_updown(x); break; default: counter_up(x); /* CHECKED: invalid == default */ /* CHECKED: no warning */ } } static void counter_dobang(t_counter *x, int notjam) { int offmin = 0, offmax = 0, onmin = 0, onmax = 0; /* CHECKED: carry-off is not sent if min >= max */ /* LATER rethink (this is a hack) */ if (x->x_min < x->x_max) offmin = x->x_minhitflag, offmax = x->x_maxhitflag; x->x_minhitflag = x->x_maxhitflag = 0; if (x->x_count < x->x_min) { if (x->x_inc == 1) { /* min has changed, which should imply x->x_count == x->x_min */ loudbug_bug("counter_dobang (count < min)"); } else if (x->x_dir == COUNTER_UPDOWN) { x->x_inc = 1; if ((x->x_count = x->x_min + 1) > x->x_max) x->x_count = x->x_min; } else if ((x->x_count = x->x_max) < x->x_min) x->x_count = x->x_min; } else if (x->x_count > x->x_max) { if (x->x_inc == -1) { /* CHECKED: ignored */ } else if (x->x_dir == COUNTER_UPDOWN) { x->x_inc = -1; if ((x->x_count = x->x_max - 1) < x->x_min) x->x_count = x->x_min; } else x->x_count = x->x_min; } if (x->x_count == x->x_min && x->x_inc == -1) { /* CHECKED: 'jam' inhibits middle outlets (unless carry-off) carry-on is never sent if max < min, but sent if max == min */ if (notjam && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */ onmin = 1; } else if (x->x_count == x->x_max && x->x_inc == 1) { /* CHECKED: this counter is never reset (and goes up to INT_MAX) -- neither after dir change, nor after max change */ x->x_maxcount++; /* CHECKED: 'jam' does the increment */ outlet_float(x->x_out4, x->x_maxcount); /* CHECKED: 'jam' inhibits middle outlets (unless carry-off) carry-on is never sent if max < min, but sent if max == min */ if (notjam && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */ onmax = 1; } /* CHECKED: outlets deliver in right-to-left order */ if (onmax) { if (x->x_carrybang) outlet_bang(x->x_out3); else { outlet_float(x->x_out3, 1); x->x_maxhitflag = 1; } } else if (offmax) outlet_float(x->x_out3, 0); else if (onmin) { if (x->x_carrybang) outlet_bang(x->x_out2); else { outlet_float(x->x_out2, 1); x->x_minhitflag = 1; } } else if (offmin) outlet_float(x->x_out2, 0); outlet_float(((t_object *)x)->ob_outlet, x->x_count); } static void counter_bang(t_counter *x) { x->x_count += x->x_inc; counter_dobang(x, 1); } static void counter_float(t_counter *x, t_float dummy) { counter_bang(x); } /* CHECKED: out-of-range values are ignored */ /* CHECKED: 'down, set 3, up, bang' gives 5 */ static void counter_set(t_counter *x, t_floatarg f) { int i = (int)f; if (i >= x->x_min && i <= x->x_max) x->x_count = i - x->x_inc; } /* CHECKED: out-of-range values are ignored */ static void counter_jam(t_counter *x, t_floatarg f) { int i = (int)f; if (i >= x->x_min && i <= x->x_max) { x->x_count = i; counter_dobang(x, 0); } } /* CHECKED: sends max carry on/off in any mode */ static void counter_inc(t_counter *x) { int tempdir = x->x_dir; int tempinc = x->x_inc; counter_up(x); counter_bang(x); x->x_dir = tempdir; x->x_inc = tempinc; } /* CHECKED: sends min carry on/off in any mode */ static void counter_dec(t_counter *x) { int tempdir = x->x_dir; int tempinc = x->x_inc; counter_down(x); counter_bang(x); x->x_dir = tempdir; x->x_inc = tempinc; } /* CHECKED: min can be set over max */ static void counter_min(t_counter *x, t_floatarg f) { /* CHECKED: min change always sets count to min and bangs */ /* do not use counter_jam() here -- avoid range checking */ x->x_count = x->x_min = (int)f; counter_dobang(x, 0); } /* CHECKED: max can be set below min */ static void counter_max(t_counter *x, t_floatarg f) { x->x_max = (int)f; } static void counter_carrybang(t_counter *x) { x->x_carrybang = 1; } static void counter_carryint(t_counter *x) { x->x_carrybang = 0; } /* CHECKED: up/down switch */ static void counter_bang1(t_counter *x) { if (x->x_dir == COUNTER_UP) counter_down(x); else if (x->x_dir == COUNTER_DOWN) counter_up(x); else x->x_inc = -x->x_inc; /* CHECKED */ } /* CHECKED */ static void counter_bang2(t_counter *x) { counter_set(x, x->x_min); } /* CHECKED: out-of-range values are accepted (LATER rethink) */ /* CHECKED: no resetting of min, nor of max (contrary to the man) */ /* CHECKED: 'down, float2 3, up, bang' gives 3 (LATER rethink) */ static void counter_float2(t_counter *x, t_floatarg f) { counter_set(x, f); /* FIXME */ } /* CHECKED */ static void counter_bang3(t_counter *x) { counter_jam(x, x->x_min); } /* CHECKED: out-of-range values are accepted (LATER rethink) */ /* CHECKED: no resetting of min, nor of max (contrary to the man) */ static void counter_float3(t_counter *x, t_floatarg f) { counter_jam(x, f); /* FIXME */ } /* CHECKED */ static void counter_bang4(t_counter *x) { counter_set(x, x->x_max); } static void counter_proxy_bang(t_counter_proxy *x) { x->p_bangmethod(x->p_master); } static void counter_proxy_float(t_counter_proxy *x, t_float f) { x->p_floatmethod(x->p_master, f); } static void counter_free(t_counter *x) { int i; for (i = 0; i < 4; i++) if (x->x_proxies[i]) pd_free(x->x_proxies[i]); } static void *counter_new(t_floatarg f1, t_floatarg f2, t_floatarg f3) { t_counter *x = (t_counter *)pd_new(counter_class); t_counter_proxy **pp = (t_counter_proxy **)x->x_proxies; int i1 = (int)f1; int i2 = (int)f2; int i3 = (int)f3; int i; static int warned = 0; if (fittermax_get() && !warned) { post("warning: counter is not fully compatible,\ please report differences"); warned = 1; } x->x_dir = COUNTER_UP; x->x_inc = 1; /* previous value required by counter_dir() */ x->x_min = 0; x->x_max = COUNTER_DEFMAX; if (i3) x->x_dir = i1, x->x_min = i2, x->x_max = i3; else if (i2) x->x_min = i1, x->x_max = i2; else if (i1) x->x_max = i1; x->x_carrybang = 0; /* CHECKED */ x->x_minhitflag = x->x_maxhitflag = 0; x->x_maxcount = 0; counter_dir(x, x->x_dir); /* CHECKED: [counter 1 ] starts from */ x->x_count = (x->x_dir == COUNTER_DOWN ? x->x_max : x->x_min); for (i = 0; i < 4; i++) { x->x_proxies[i] = pd_new(counter_proxy_class); ((t_counter_proxy *)x->x_proxies[i])->p_master = x; inlet_new((t_object *)x, x->x_proxies[i], 0, 0); } (*pp)->p_bangmethod = counter_bang1; (*pp++)->p_floatmethod = counter_dir; /* CHECKED: same as dir */ (*pp)->p_bangmethod = counter_bang2; (*pp++)->p_floatmethod = counter_float2; (*pp)->p_bangmethod = counter_bang3; (*pp++)->p_floatmethod = counter_float3; (*pp)->p_bangmethod = counter_bang4; (*pp++)->p_floatmethod = counter_max; /* CHECKED: same as max */ outlet_new((t_object *)x, &s_float); x->x_out2 = outlet_new((t_object *)x, &s_anything); /* float/bang */ x->x_out3 = outlet_new((t_object *)x, &s_anything); /* float/bang */ x->x_out4 = outlet_new((t_object *)x, &s_float); return (x); } void counter_setup(void) { counter_class = class_new(gensym("counter"), (t_newmethod)counter_new, (t_method)counter_free, sizeof(t_counter), 0, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(counter_class, counter_bang); class_addfloat(counter_class, counter_float); class_addmethod(counter_class, (t_method)counter_bang, gensym("next"), 0); class_addmethod(counter_class, (t_method)counter_set, gensym("set"), A_FLOAT, 0); class_addmethod(counter_class, (t_method)counter_set, gensym("goto"), A_FLOAT, 0); class_addmethod(counter_class, (t_method)counter_jam, gensym("jam"), A_FLOAT, 0); class_addmethod(counter_class, (t_method)counter_up, gensym("up"), 0); class_addmethod(counter_class, (t_method)counter_down, gensym("down"), 0); class_addmethod(counter_class, (t_method)counter_updown, gensym("updown"), 0); class_addmethod(counter_class, (t_method)counter_inc, gensym("inc"), 0); class_addmethod(counter_class, (t_method)counter_dec, gensym("dec"), 0); class_addmethod(counter_class, (t_method)counter_min, gensym("min"), A_FLOAT, 0); class_addmethod(counter_class, (t_method)counter_max, gensym("max"), A_FLOAT, 0); class_addmethod(counter_class, (t_method)counter_carrybang, gensym("carrybang"), 0); class_addmethod(counter_class, (t_method)counter_carryint, gensym("carryint"), 0); counter_proxy_class = class_new(gensym("_counter_proxy"), 0, 0, sizeof(t_counter_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(counter_proxy_class, counter_proxy_bang); class_addfloat(counter_proxy_class, counter_proxy_float); fitter_setup(counter_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/cartopol.c0000644000076500007650000000215311466617445017634 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define atan2f atan2 #define hypotf hypot #endif typedef struct _cartopol { t_object x_ob; t_float x_imag; t_outlet *x_out2; } t_cartopol; static t_class *cartopol_class; static void cartopol_float(t_cartopol *x, t_float f) { outlet_float(x->x_out2, atan2f(x->x_imag, f)); outlet_float(((t_object *)x)->ob_outlet, hypotf(f, x->x_imag)); } static void *cartopol_new(void) { t_cartopol *x = (t_cartopol *)pd_new(cartopol_class); floatinlet_new((t_object *)x, &x->x_imag); outlet_new((t_object *)x, &s_float); x->x_out2 = outlet_new((t_object *)x, &s_float); return (x); } void cartopol_setup(void) { cartopol_class = class_new(gensym("cartopol"), (t_newmethod)cartopol_new, 0, sizeof(t_cartopol), 0, 0); class_addfloat(cartopol_class, cartopol_float); } cyclone-0.1-alpha55/cyclone/hammer/next.c0000644000076500007650000000247011466617445016771 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" //#define NEXT_USEEVENTNO typedef struct _next { t_object x_ob; #ifdef NEXT_USEEVENTNO int x_lastevent; #else double x_lastevent; #endif t_outlet *x_out2; } t_next; static t_class *next_class; /* CHECKME first call, CHECKME if the outlets are not swapped */ static void next_anything(t_next *x, t_symbol *s, int ac, t_atom *av) { #ifdef NEXT_USEEVENTNO int nextevent = sys_geteventno(); #else double nextevent = clock_getlogicaltime(); #endif if (x->x_lastevent == nextevent) outlet_bang(x->x_out2); else { x->x_lastevent = nextevent; outlet_bang(((t_object *)x)->ob_outlet); } } static void *next_new(void) { t_next *x = (t_next *)pd_new(next_class); outlet_new((t_object *)x, &s_bang); x->x_out2 = outlet_new((t_object *)x, &s_bang); #ifdef NEXT_USEEVENTNO x->x_lastevent = sys_geteventno(); #else x->x_lastevent = clock_getlogicaltime(); #endif return (x); } void next_setup(void) { next_class = class_new(gensym("next"), (t_newmethod)next_new, 0, sizeof(t_next), 0, 0); class_addanything(next_class, next_anything); } cyclone-0.1-alpha55/cyclone/hammer/sprintf.c0000644000076500007650000004001711466617445017477 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include "m_pd.h" #include "common/loud.h" #ifdef KRZYSZCZ //#define SPRINTF_DEBUG #endif /* Pattern types. These are the parsing routine's return values. If returned value is >= SPRINTF_MINSLOTTYPE, then another slot is created (i.e. an inlet, and a proxy handling it). */ #define SPRINTF_UNSUPPORTED 0 #define SPRINTF_LITERAL 1 #define SPRINTF_MINSLOTTYPE 2 #define SPRINTF_INT 2 #define SPRINTF_FLOAT 3 #define SPRINTF_CHAR 4 #define SPRINTF_STRING 5 /* Numbers: assuming max 62 digits preceding a decimal point in any fixed-point representation of a t_float (39 in my system) -- need to be sure, that using max precision would never produce a representation longer than max width. If this is so, then no number representation would exceed max width (presumably...). Strings: for the time being, any string longer than max width would be truncated (somehow compatible with Str256, but LATER warn-and-allow). */ /* LATER rethink it all */ #define SPRINTF_MAXPRECISION 192 #define SPRINTF_MAXWIDTH 256 typedef struct _sprintf { t_object x_ob; int x_nslots; int x_nproxies; /* as requested (and allocated) */ t_pd **x_proxies; int x_fsize; /* as allocated (i.e. including a terminating 0) */ char *x_fstring; } t_sprintf; typedef struct _sprintf_proxy { t_object p_ob; t_sprintf *p_master; int p_id; int p_type; /* a value #defined above */ char *p_pattern; char *p_pattend; t_atom p_atom; /* current input */ int p_size; int p_valid; } t_sprintf_proxy; static t_class *sprintf_class; static t_class *sprintf_proxy_class; /* CHECKED: 'symout' argument has no special meaning in max4.07, LATER investigate */ /* LATER use snprintf, if it is available on other systems (should be...) */ static void sprintf_proxy_checkit(t_sprintf_proxy *x, char *buf, int checkin) { int result = 0, valid = 0; char *pattend = x->p_pattend; if (pattend) { char tmp = *pattend; *pattend = 0; if (x->p_atom.a_type == A_FLOAT) { t_float f = x->p_atom.a_w.w_float; if (x->p_type == SPRINTF_INT) /* CHECKME large/negative values */ result = sprintf(buf, x->p_pattern, (int)f); else if (x->p_type == SPRINTF_FLOAT) result = sprintf(buf, x->p_pattern, f); else if (x->p_type == SPRINTF_CHAR) /* CHECKED: if 0 is input into a %c-slot, the whole output string is null-terminated */ /* CHECKED: float into a %c-slot is truncated, but CHECKME large/negative values */ result = sprintf(buf, x->p_pattern, (unsigned char)f); else if (x->p_type == SPRINTF_STRING) { /* CHECKED: any number input into a %s-slot is ok */ char tmp[64]; /* LATER rethink */ sprintf(tmp, "%g", f); result = sprintf(buf, x->p_pattern, tmp); } else /* LATER consider calling it a bug(), rather than error? */ loud_error((t_pd *)x->p_master, "can't convert float to type of argument %d", x->p_id + 1); if (result > 0) valid = 1; } else if (x->p_atom.a_type == A_SYMBOL) { t_symbol *s = x->p_atom.a_w.w_symbol; if (x->p_type == SPRINTF_STRING) { if (strlen(s->s_name) > SPRINTF_MAXWIDTH) { strncpy(buf, s->s_name, SPRINTF_MAXWIDTH); buf[SPRINTF_MAXWIDTH] = 0; result = SPRINTF_MAXWIDTH; } else result = sprintf(buf, x->p_pattern, s->s_name); if (result >= 0) valid = 1; } else /* CHECKED */ loud_error((t_pd *)x->p_master, "can't convert symbol to type of argument %d", x->p_id + 1); } *pattend = tmp; } else loudbug_bug("sprintf_proxy_checkit"); if (x->p_valid = valid) { #ifdef SPRINTF_DEBUG if (checkin) loudbug_post("[%d in \"%s\"]", result, buf); #endif x->p_size = result; } else { #ifdef SPRINTF_DEBUG if (checkin) loudbug_post("checkit failed"); #endif x->p_size = 0; } } static void sprintf_dooutput(t_sprintf *x) { int i, outsize; char *outstring; outsize = x->x_fsize; /* this is strlen() + 1 */ /* LATER consider subtracting format pattern sizes */ for (i = 0; i < x->x_nslots; i++) { t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; if (y->p_valid) outsize += y->p_size; else { /* slot i has received an invalid input -- CHECKME if this condition blocks all subsequent output requests? */ return; } } if (outsize > 0 && (outstring = getbytes(outsize))) { char *inp = x->x_fstring; char *outp = outstring; for (i = 0; i < x->x_nslots; i++) { t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; int len = y->p_pattern - inp; if (len > 0) { strncpy(outp, inp, len); outp += len; } sprintf_proxy_checkit(y, outp, 0); outp += y->p_size; /* p_size is never negative */ inp = y->p_pattend; } strcpy(outp, inp); outp = outstring; while (*outp == ' ' || *outp == '\t' || *outp == '\n' || *outp == '\r') outp++; if (*outp) { t_binbuf *bb = binbuf_new(); int ac; t_atom *av; binbuf_text(bb, outp, strlen(outp)); ac = binbuf_getnatom(bb); av = binbuf_getvec(bb); if (ac) { if (av->a_type == A_SYMBOL) outlet_anything(((t_object *)x)->ob_outlet, av->a_w.w_symbol, ac - 1, av + 1); else if (av->a_type == A_FLOAT) { if (ac > 1) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); } } binbuf_free(bb); } freebytes(outstring, outsize); } } static void sprintf_proxy_bang(t_sprintf_proxy *x) { sprintf_dooutput(x->p_master); /* CHECKED (in any inlet) */ } static void sprintf_proxy_float(t_sprintf_proxy *x, t_float f) { char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ SETFLOAT(&x->p_atom, f); sprintf_proxy_checkit(x, buf, 1); if (x->p_id == 0 && x->p_valid) sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */ } static void sprintf_proxy_symbol(t_sprintf_proxy *x, t_symbol *s) { char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ if (s && *s->s_name) SETSYMBOL(&x->p_atom, s); else SETFLOAT(&x->p_atom, 0); sprintf_proxy_checkit(x, buf, 1); if (x->p_id == 0 && x->p_valid) sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */ } static void sprintf_dolist(t_sprintf *x, t_symbol *s, int ac, t_atom *av, int startid) { int cnt = x->x_nslots - startid; if (ac > cnt) ac = cnt; if (ac-- > 0) { int id; for (id = startid + ac, av += ac; id >= startid; id--, av--) { if (av->a_type == A_FLOAT) sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[id], av->a_w.w_float); else if (av->a_type == A_SYMBOL) sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[id], av->a_w.w_symbol); } } } static void sprintf_doanything(t_sprintf *x, t_symbol *s, int ac, t_atom *av, int startid) { if (s && s != &s_) { sprintf_dolist(x, 0, ac, av, startid + 1); sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[startid], s); } else sprintf_dolist(x, 0, ac, av, startid); } static void sprintf_proxy_list(t_sprintf_proxy *x, t_symbol *s, int ac, t_atom *av) { sprintf_dolist(x->p_master, s, ac, av, x->p_id); } static void sprintf_proxy_anything(t_sprintf_proxy *x, t_symbol *s, int ac, t_atom *av) { sprintf_doanything(x->p_master, s, ac, av, x->p_id); } static void sprintf_bang(t_sprintf *x) { if (x->x_nslots) sprintf_proxy_bang((t_sprintf_proxy *)x->x_proxies[0]); } static void sprintf_float(t_sprintf *x, t_float f) { if (x->x_nslots) sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[0], f); } static void sprintf_symbol(t_sprintf *x, t_symbol *s) { if (x->x_nslots) sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[0], s); } static void sprintf_list(t_sprintf *x, t_symbol *s, int ac, t_atom *av) { if (x->x_nslots) sprintf_dolist(x, s, ac, av, 0); } static void sprintf_anything(t_sprintf *x, t_symbol *s, int ac, t_atom *av) { if (x->x_nslots) sprintf_doanything(x, s, ac, av, 0); } /* adjusted binbuf_gettext(), LATER do it right */ static char *hammer_gettext(int ac, t_atom *av, int *sizep) { char *buf = getbytes(1); int size = 1; char atomtext[MAXPDSTRING]; while (ac--) { char *newbuf; int newsize; if (buf[size-1] == 0 || av->a_type == A_SEMI || av->a_type == A_COMMA) size--; atom_string(av, atomtext, MAXPDSTRING); newsize = size + strlen(atomtext) + 1; if (!(newbuf = resizebytes(buf, size, newsize))) { *sizep = 1; return (getbytes(1)); } buf = newbuf; strcpy(buf + size, atomtext); size = newsize; buf[size-1] = ' '; av++; } buf[size-1] = 0; *sizep = size; return (buf); } /* Called twice: 1st pass (with x == 0) is used for counting valid patterns; 2nd pass (after object allocation) -- for initializing the proxies. If there is a "%%" pattern, then the buffer is shrinked in the second pass (LATER rethink). */ static int sprintf_parsepattern(t_sprintf *x, char **patternp) { int type = SPRINTF_UNSUPPORTED; char errstring[MAXPDSTRING]; char *ptr; char modifier = 0; int width = 0; int precision = 0; int *numfield = &width; int dotseen = 0; *errstring = 0; for (ptr = *patternp; *ptr; ptr++) { if (*ptr >= '0' && *ptr <= '9') { if (!numfield) { if (x) sprintf(errstring, "extra number field"); break; } *numfield = 10 * *numfield + *ptr - '0'; if (dotseen) { if (precision > SPRINTF_MAXPRECISION) { if (x) sprintf(errstring, "precision field too large"); break; } } else { if (width > SPRINTF_MAXWIDTH) { if (x) sprintf(errstring, "width field too large"); break; } } continue; } if (*numfield) numfield = 0; if (strchr("diouxX", *ptr)) { type = SPRINTF_INT; break; } else if (strchr("aAeEfgG", *ptr)) { if (modifier) { if (x) sprintf(errstring, "\'%c\' modifier not supported", modifier); break; } type = SPRINTF_FLOAT; break; } else if (strchr("c", *ptr)) { if (modifier) { if (x) sprintf(errstring, "\'%c\' modifier not supported", modifier); break; } type = SPRINTF_CHAR; break; } else if (strchr("s", *ptr)) { if (modifier) { if (x) sprintf(errstring, "\'%c\' modifier not supported", modifier); break; } type = SPRINTF_STRING; break; } else if (*ptr == '%') { type = SPRINTF_LITERAL; if (x) { /* buffer-shrinking hack, LATER rethink */ char *p1 = ptr, *p2 = ptr + 1; do *p1++ = *p2; while (*p2++); ptr--; } break; } else if (strchr("CSnm", *ptr)) { if (x) sprintf(errstring, "\'%c\' type not supported", *ptr); break; } else if (strchr("l", *ptr)) { if (modifier) { if (x) sprintf(errstring, "only single modifier is supported"); break; } modifier = *ptr; } else if (strchr("hjLqtzZ", *ptr)) { if (x) sprintf(errstring, "\'%c\' modifier not supported", *ptr); break; } else if (*ptr == '.') { if (dotseen) { if (x) sprintf(errstring, "multiple dots"); break; } numfield = &precision; dotseen = 1; } else if (*ptr == '$') { if (x) sprintf(errstring, "parameter number field not supported"); break; } else if (*ptr == '*') { if (x) sprintf(errstring, "%s parameter not supported", (dotseen ? "precision" : "width")); break; } else if (!strchr("-+ #\'", *ptr)) { if (x) sprintf(errstring, "\'%c\' format character not supported", *ptr); break; } } if (*ptr) ptr++; /* LATER rethink */ else if (x) sprintf(errstring, "type not specified"); if (x && type == SPRINTF_UNSUPPORTED) { if (*errstring) loud_error((t_pd *)x, "slot skipped (%s %s)", errstring, "in a format pattern"); else loud_error((t_pd *)x, "slot skipped"); } *patternp = ptr; return (type); } static void sprintf_free(t_sprintf *x) { if (x->x_proxies) { int i = x->x_nslots; while (i--) { t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; pd_free((t_pd *)y); } freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); } if (x->x_fstring) freebytes(x->x_fstring, x->x_fsize); } static void *sprintf_new(t_symbol *s, int ac, t_atom *av) { t_sprintf *x; int fsize; char *fstring; char *p1, *p2; int i, nslots, nproxies = 0; t_pd **proxies; fstring = hammer_gettext(ac, av, &fsize); p1 = fstring; while (p2 = strchr(p1, '%')) { int type; p1 = p2 + 1; type = sprintf_parsepattern(0, &p1); if (type >= SPRINTF_MINSLOTTYPE) nproxies++; } if (!nproxies) { /* CHECKED: an object without arguments, if created in the editor, has no inlets/outlets, but it would have one inlet (no outlets) upon loading. Error message is printed in either case. */ x = (t_sprintf *)pd_new(sprintf_class); x->x_nslots = 0; x->x_nproxies = 0; x->x_proxies = 0; x->x_fsize = fsize; x->x_fstring = fstring; p1 = fstring; while (p2 = strchr(p1, '%')) { p1 = p2 + 1; sprintf_parsepattern(x, &p1); } loud_error((t_pd *)x, "an object created without valid format patterns..."); return (x); } #ifdef SPRINTF_DEBUG loudbug_post("%d slots:", nproxies); #endif /* CHECKED: max creates as many inlets, as there are %-signs, no matter if they are valid, or not -- if not, it prints ``can't convert'' errors for any input... */ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) { freebytes(fstring, fsize); return (0); } for (nslots = 0; nslots < nproxies; nslots++) if (!(proxies[nslots] = pd_new(sprintf_proxy_class))) break; if (!nslots) { freebytes(fstring, fsize); freebytes(proxies, nproxies * sizeof(*proxies)); return (0); } x = (t_sprintf *)pd_new(sprintf_class); x->x_nslots = nslots; x->x_nproxies = nproxies; x->x_proxies = proxies; x->x_fsize = fsize; x->x_fstring = fstring; p1 = fstring; i = 0; while (p2 = strchr(p1, '%')) { int type; p1 = p2 + 1; type = sprintf_parsepattern(x, &p1); if (type >= SPRINTF_MINSLOTTYPE) { #ifdef SPRINTF_DEBUG char tmp = *p1; *p1 = 0; loudbug_poststring(p2); loudbug_endpost(); *p1 = tmp; #endif if (i < nslots) { char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ t_sprintf_proxy *y = (t_sprintf_proxy *)proxies[i]; y->p_master = x; y->p_id = i; y->p_type = type; y->p_pattern = p2; y->p_pattend = p1; if (type == SPRINTF_STRING) SETSYMBOL(&y->p_atom, &s_); else SETFLOAT(&y->p_atom, 0); y->p_size = 0; y->p_valid = 0; if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); sprintf_proxy_checkit(y, buf, 1); i++; } } } #ifdef SPRINTF_DEBUG loudbug_post("printf(\"%s\", ...)", fstring); #endif outlet_new((t_object *)x, &s_anything); return (x); } void sprintf_setup(void) { sprintf_class = class_new(gensym("sprintf"), (t_newmethod)sprintf_new, (t_method)sprintf_free, sizeof(t_sprintf), 0, A_GIMME, 0); class_addbang(sprintf_class, sprintf_bang); class_addfloat(sprintf_class, sprintf_float); class_addsymbol(sprintf_class, sprintf_symbol); class_addlist(sprintf_class, sprintf_list); class_addanything(sprintf_class, sprintf_anything); sprintf_proxy_class = class_new(gensym("_sprintf_proxy"), 0, 0, sizeof(t_sprintf_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(sprintf_proxy_class, sprintf_proxy_bang); class_addfloat(sprintf_proxy_class, sprintf_proxy_float); class_addsymbol(sprintf_proxy_class, sprintf_proxy_symbol); class_addlist(sprintf_proxy_class, sprintf_proxy_list); class_addanything(sprintf_proxy_class, sprintf_proxy_anything); } cyclone-0.1-alpha55/cyclone/hammer/decide.c0000644000076500007650000000361311466617445017230 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" typedef struct _decide { t_object x_ob; unsigned int x_seed; } t_decide; static t_class *decide_class; /* the random bit algo is taken from NR (method II in 7.4) -- CHECKED */ #define RBIT1 1 #define RBIT2 2 #define RBIT5 16 #define RBIT18 131072 #define RBIT_MASK (RBIT1 + RBIT2 + RBIT5) static void decide_bang(t_decide *x) { if (x->x_seed & RBIT18) { x->x_seed = ((x->x_seed ^ RBIT_MASK) << 1) | RBIT1; outlet_float(((t_object *)x)->ob_outlet, 1); } else { x->x_seed <<= 1; outlet_float(((t_object *)x)->ob_outlet, 0); } } static void decide_float(t_decide *x, t_float f) { /* CHECKED: float loudly rejected, int (any value) same as bang */ int i; if (loud_checkint((t_pd *)x, f, &i, &s_float)) decide_bang(x); } static void decide_ft1(t_decide *x, t_floatarg f) { int i = (int)f; /* CHECKED */ if (i) /* CHECKED: negative numbers are accepted */ x->x_seed = i; else x->x_seed = 123456789; /* FIXME */ } static void *decide_new(t_floatarg f) { t_decide *x = (t_decide *)pd_new(decide_class); x->x_seed = 123456789; /* FIXME */ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_float); return (x); } void decide_setup(void) { decide_class = class_new(gensym("decide"), (t_newmethod)decide_new, 0, sizeof(t_decide), 0, A_DEFFLOAT, 0); class_addbang(decide_class, decide_bang); class_addfloat(decide_class, decide_float); class_addmethod(decide_class, (t_method)decide_ft1, gensym("ft1"), A_FLOAT, 0); /* CHECKED list is auto-unfolded */ /* CHECKED doesn't understand "seed" */ } cyclone-0.1-alpha55/cyclone/hammer/switch.c0000644000076500007650000001047611466617445017321 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #define SWITCH_MININLETS 2 /* LATER consider using 1 (with a warning) */ #define SWITCH_C74MAXINLETS 100 #define SWITCH_DEFINLETS 2 typedef struct _switch { t_object x_ob; int x_open; int x_ninlets; /* not counting left one */ int x_nproxies; /* as requested (and allocated) */ t_pd **x_proxies; } t_switch; typedef struct _switch_proxy { t_object p_ob; t_switch *p_master; int p_id; } t_switch_proxy; static t_class *switch_class; static t_class *switch_proxy_class; static void switch_proxy_bang(t_switch_proxy *x) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_bang(((t_object *)master)->ob_outlet); } static void switch_proxy_float(t_switch_proxy *x, t_float f) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_float(((t_object *)master)->ob_outlet, f); } static void switch_proxy_symbol(t_switch_proxy *x, t_symbol *s) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_symbol(((t_object *)master)->ob_outlet, s); } static void switch_proxy_pointer(t_switch_proxy *x, t_gpointer *gp) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_pointer(((t_object *)master)->ob_outlet, gp); } static void switch_proxy_list(t_switch_proxy *x, t_symbol *s, int ac, t_atom *av) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_list(((t_object *)master)->ob_outlet, s, ac, av); } static void switch_proxy_anything(t_switch_proxy *x, t_symbol *s, int ac, t_atom *av) { t_switch *master = x->p_master; if (master->x_open == x->p_id) outlet_anything(((t_object *)master)->ob_outlet, s, ac, av); } static void switch_float(t_switch *x, t_float f) { int i = (int)f; if (i < 0) i = -i; if (i > x->x_ninlets) i = x->x_ninlets; x->x_open = i; } static void switch_bang(t_switch *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_open); } static void switch_free(t_switch *x) { if (x->x_proxies) { int i = x->x_ninlets; while (i--) pd_free(x->x_proxies[i]); freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); } } static void *switch_new(t_floatarg f1, t_floatarg f2) { t_switch *x; int i, ninlets, nproxies = (int)f1; t_pd **proxies; if (nproxies < SWITCH_MININLETS) nproxies = SWITCH_DEFINLETS; if (nproxies > SWITCH_C74MAXINLETS) fittermax_rangewarning(switch_class, SWITCH_C74MAXINLETS, "inlets"); if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) return (0); for (ninlets = 0; ninlets < nproxies; ninlets++) if (!(proxies[ninlets] = pd_new(switch_proxy_class))) break; if (ninlets < SWITCH_MININLETS) { int i = ninlets; while (i--) pd_free(proxies[i]); freebytes(proxies, nproxies * sizeof(*proxies)); return (0); } x = (t_switch *)pd_new(switch_class); x->x_ninlets = ninlets; x->x_nproxies = nproxies; x->x_proxies = proxies; for (i = 0; i < ninlets; i++) { t_switch_proxy *y = (t_switch_proxy *)proxies[i]; y->p_master = x; y->p_id = i + 1; inlet_new((t_object *)x, (t_pd *)y, 0, 0); } outlet_new((t_object *)x, &s_anything); switch_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */ return (x); } void switch_setup(void) { switch_class = class_new(gensym("switch"), (t_newmethod)switch_new, (t_method)switch_free, sizeof(t_switch), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addfloat(switch_class, switch_float); class_addbang(switch_class, switch_bang); switch_proxy_class = class_new(gensym("_switch_proxy"), 0, 0, sizeof(t_switch_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addfloat(switch_proxy_class, switch_proxy_float); class_addbang(switch_proxy_class, switch_proxy_bang); class_addsymbol(switch_proxy_class, switch_proxy_symbol); class_addpointer(switch_proxy_class, switch_proxy_pointer); class_addlist(switch_proxy_class, switch_proxy_list); class_addanything(switch_proxy_class, switch_proxy_anything); fitter_setup(switch_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/minimum.c0000644000076500007650000000426511466617445017472 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #define MINIMUM_C74MAXITEMS 256 typedef struct _minimum { t_object x_ob; t_float x_last; t_float x_test; } t_minimum; static t_class *minimum_class; static void minimum_bang(t_minimum *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_last); } static void minimum_float(t_minimum *x, t_float f) { outlet_float(((t_object *)x)->ob_outlet, x->x_last = (f < x->x_test ? f : x->x_test)); } static void minimum_list(t_minimum *x, t_symbol *s, int ac, t_atom *av) { if (ac > MINIMUM_C74MAXITEMS) fittermax_rangewarning(*(t_pd *)x, MINIMUM_C74MAXITEMS, "items"); while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME (a warning?) */ if (ac) { t_float fpick = av->a_w.w_float; ac--; av++; while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME */ if (ac) { t_float fnext, f = av->a_w.w_float; if (f < fpick) { fnext = fpick; fpick = f; } else fnext = f; ac--; av++; while (ac--) { if (av->a_type == A_FLOAT) { f = av->a_w.w_float; if (f < fpick) { fnext = fpick; fpick = f; } else if (f < fnext) fnext = f; } /* CHECKME else */ av++; } x->x_test = fnext; outlet_float(((t_object *)x)->ob_outlet, x->x_last = fpick); } else minimum_float(x, fpick); /* CHECKME */ } /* CHECKME else */ } static void *minimum_new(t_floatarg f) { t_minimum *x = (t_minimum *)pd_new(minimum_class); x->x_last = 0; /* CHECKME */ x->x_test = f; floatinlet_new((t_object *)x, &x->x_test); outlet_new((t_object *)x, &s_float); return (x); } void minimum_setup(void) { minimum_class = class_new(gensym("minimum"), (t_newmethod)minimum_new, 0, sizeof(t_minimum), 0, A_DEFFLOAT, 0); class_addbang(minimum_class, minimum_bang); class_addfloat(minimum_class, minimum_float); class_addlist(minimum_class, minimum_list); fitter_setup(minimum_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/MouseState.c0000644000076500007650000000773511466617445020115 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "hammer/gui.h" typedef struct _MouseState { t_object x_ob; int x_ispolling; int x_wasbanged; int x_waszeroed; int x_hlast; int x_vlast; int x_hzero; int x_vzero; t_outlet *x_hposout; t_outlet *x_vposout; t_outlet *x_hdiffout; t_outlet *x_vdiffout; } t_MouseState; static t_class *MouseState_class; static void MouseState_anything(t_MouseState *x, t_symbol *s, int ac, t_atom *av) { /* dummy method, filtering out those messages from gui, which are not handled explicitly */ } static void MouseState_doup(t_MouseState *x, t_floatarg f) { outlet_float(((t_object *)x)->ob_outlet, ((int)f ? 0 : 1)); } static void MouseState_dobang(t_MouseState *x, t_floatarg f1, t_floatarg f2) { if (x->x_wasbanged) { int h = (int)f1, v = (int)f2; outlet_float(x->x_vdiffout, v - x->x_vlast); outlet_float(x->x_hdiffout, h - x->x_hlast); outlet_float(x->x_vposout, v - x->x_vzero); outlet_float(x->x_hposout, h - x->x_hzero); x->x_hlast = h; x->x_vlast = v; x->x_wasbanged = 0; } } static void MouseState_dozero(t_MouseState *x, t_floatarg f1, t_floatarg f2) { if (x->x_waszeroed) { int h = (int)f1, v = (int)f2; x->x_hzero = h; x->x_vzero = v; x->x_waszeroed = 0; } } static void MouseState_dopoll(t_MouseState *x, t_floatarg f1, t_floatarg f2) { if (x->x_ispolling) { x->x_wasbanged = 1; MouseState_dobang(x, f1, f2); } } static void MouseState_bang(t_MouseState *x) { hammergui_mousexy(gensym("_bang")); x->x_wasbanged = 1; } static void MouseState_poll(t_MouseState *x) { if (!x->x_ispolling) { x->x_ispolling = 1; hammergui_startpolling((t_pd *)x); } } static void MouseState_nopoll(t_MouseState *x) { if (x->x_ispolling) { x->x_ispolling = 0; hammergui_stoppolling((t_pd *)x); } } static void MouseState_zero(t_MouseState *x) { hammergui_mousexy(gensym("_zero")); x->x_waszeroed = 1; } static void MouseState_reset(t_MouseState *x) { x->x_hzero = x->x_vzero = 0; } static void MouseState_free(t_MouseState *x) { MouseState_nopoll(x); hammergui_unbindmouse((t_pd *)x); } static void *MouseState_new(void) { t_MouseState *x = (t_MouseState *)pd_new(MouseState_class); x->x_ispolling = x->x_wasbanged = x->x_waszeroed = 0; outlet_new((t_object *)x, &s_float); x->x_hposout = outlet_new((t_object *)x, &s_float); x->x_vposout = outlet_new((t_object *)x, &s_float); x->x_hdiffout = outlet_new((t_object *)x, &s_float); x->x_vdiffout = outlet_new((t_object *)x, &s_float); hammergui_bindmouse((t_pd *)x); hammergui_willpoll(); MouseState_reset(x); return (x); } void MouseState_setup(void) { MouseState_class = class_new(gensym("MouseState"), (t_newmethod)MouseState_new, (t_method)MouseState_free, sizeof(t_MouseState), 0, 0); class_addanything(MouseState_class, MouseState_anything); class_addmethod(MouseState_class, (t_method)MouseState_doup, gensym("_up"), A_FLOAT, 0); class_addmethod(MouseState_class, (t_method)MouseState_dobang, gensym("_bang"), A_FLOAT, A_FLOAT, 0); class_addmethod(MouseState_class, (t_method)MouseState_dozero, gensym("_zero"), A_FLOAT, A_FLOAT, 0); class_addmethod(MouseState_class, (t_method)MouseState_dopoll, gensym("_poll"), A_FLOAT, A_FLOAT, 0); class_addbang(MouseState_class, MouseState_bang); class_addmethod(MouseState_class, (t_method)MouseState_poll, gensym("poll"), 0); class_addmethod(MouseState_class, (t_method)MouseState_nopoll, gensym("nopoll"), 0); class_addmethod(MouseState_class, (t_method)MouseState_zero, gensym("zero"), 0); class_addmethod(MouseState_class, (t_method)MouseState_reset, gensym("reset"), 0); } cyclone-0.1-alpha55/cyclone/hammer/bangbang.c0000644000076500007650000000403411466617445017550 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is a modified version of Joseph A. Sarlo's code. The most important changes are listed in "pd-lib-notes.txt" file. */ #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #define BANGBANG_MINOUTS 1 #define BANGBANG_C74MAXOUTS 40 /* CHECKED (just clipped without warning) */ #define BANGBANG_DEFOUTS 2 typedef struct _bangbang { t_object x_ob; int x_nouts; t_outlet **x_outs; t_outlet *x_outbuf[BANGBANG_DEFOUTS]; } t_bangbang; static t_class *bangbang_class; static void bangbang_bang(t_bangbang *x) { int i = x->x_nouts; while (i--) outlet_bang(x->x_outs[i]); } static void bangbang_anything(t_bangbang *x, t_symbol *s, int ac, t_atom *av) { bangbang_bang(x); } static void bangbang_free(t_bangbang *x) { if (x->x_outs != x->x_outbuf) freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); } static void *bangbang_new(t_floatarg val) { t_bangbang *x; int i, nouts = (int)val; t_outlet **outs; if (nouts < BANGBANG_MINOUTS) nouts = BANGBANG_DEFOUTS; if (nouts > BANGBANG_C74MAXOUTS) fittermax_rangewarning(bangbang_class, BANGBANG_C74MAXOUTS, "outlets"); if (nouts > BANGBANG_DEFOUTS) { if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) return (0); } else outs = 0; x = (t_bangbang *)pd_new(bangbang_class); x->x_nouts = nouts; x->x_outs = (outs ? outs : x->x_outbuf); for (i = 0; i < nouts; i++) x->x_outs[i] = outlet_new((t_object *)x, &s_bang); return (x); } void bangbang_setup(void) { bangbang_class = class_new(gensym("bangbang"), (t_newmethod)bangbang_new, (t_method)bangbang_free, sizeof(t_bangbang), 0, A_DEFFLOAT, 0); class_addbang(bangbang_class, bangbang_bang); class_addanything(bangbang_class, bangbang_anything); fitter_setup(bangbang_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/funbuff.c0000644000076500007650000003551411466617445017453 0ustar hanshans/* Copyright (c) 2002-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #include "common/vefl.h" #include "hammer/tree.h" #include "hammer/file.h" typedef struct _funbuff { t_object x_ob; t_canvas *x_canvas; t_symbol *x_defname; t_float x_value; int x_valueset; /* CHECKED filling with a large set, then sending 'goto', 'read', 'next'... outputs the previous, replaced contents (same with deletion) -- apparently a node pointer is stored, corrupt in these cases */ t_hammernode *x_pointer; int x_pointerset; /* set-with-goto flag */ int x_lastdelta; int x_embedflag; t_hammerfile *x_filehandle; t_hammertree x_tree; t_outlet *x_deltaout; t_outlet *x_bangout; } t_funbuff; static t_class *funbuff_class; static void funbuff_dooutput(t_funbuff *x, float value, float delta) { /* CHECKED lastdelta sent for 'next', 'float', 'min', 'max', 'interp', 'find' */ outlet_float(x->x_deltaout, delta); outlet_float(((t_object *)x)->ob_outlet, value); } static void funbuff_bang(t_funbuff *x) { t_hammernode *np; int count = 0; int xmin = 0, xmax = 0; t_float ymin = 0, ymax = 0; if (np = x->x_tree.t_first) { /* LATER consider using extra fields, updated on the fly */ count = 1; xmin = np->n_key; xmax = x->x_tree.t_last->n_key; ymin = ymax = HAMMERNODE_GETFLOAT(np); while (np = np->n_next) { t_float f = HAMMERNODE_GETFLOAT(np); if (f < ymin) ymin = f; else if (f > ymax) ymax = f; count++; } } /* format CHECKED */ post("funbuff info: %d elements long", count); /* CHECKED 0 and 1 */ if (count) { post(" -> minX= %d maxX= %d", xmin, xmax); post(" -> minY= %g maxY= %g", ymin, ymax); post(" -> domain= %d range= %g", xmax - xmin, ymax - ymin); } } static void funbuff_float(t_funbuff *x, t_float f) { int ndx = (int)f; /* CHECKED float is silently truncated */ t_hammernode *np; if (x->x_valueset) { np = hammertree_insertfloat(&x->x_tree, ndx, x->x_value, 1); x->x_valueset = 0; } else if (np = hammertree_closest(&x->x_tree, ndx, 0)) funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np), x->x_lastdelta); /* CHECKED pointer is updated -- 'next' outputs np also in a !valueset case (it is sent twice) */ x->x_pointer = np; /* FIXME */ x->x_pointerset = 0; } static void funbuff_ft1(t_funbuff *x, t_floatarg f) { /* this is incompatible -- CHECKED float is silently truncated */ x->x_value = f; x->x_valueset = 1; } static void funbuff_clear(t_funbuff *x) { hammertree_clear(&x->x_tree, 0); /* CHECKED valueset is not cleared */ x->x_pointer = 0; } /* LATER dirty flag handling */ static void funbuff_embed(t_funbuff *x, t_floatarg f) { x->x_embedflag = (f != 0); } static void funbuff_goto(t_funbuff *x, t_floatarg f) { /* CHECKED truncation */ x->x_pointer = hammertree_closest(&x->x_tree, (int)f, 1); x->x_pointerset = 1; /* CHECKED delta output by 'next' will be zero */ } /* LATER consider using an extra field, updated on the fly */ static void funbuff_min(t_funbuff *x) { t_hammernode *np; if (np = x->x_tree.t_first) /* CHECKED nop if empty */ { t_float result = HAMMERNODE_GETFLOAT(np); while (np = np->n_next) if (HAMMERNODE_GETFLOAT(np) < result) result = HAMMERNODE_GETFLOAT(np); funbuff_dooutput(x, result, x->x_lastdelta); /* CHECKED pointer not updated */ } } /* LATER consider using an extra field, updated on the fly */ static void funbuff_max(t_funbuff *x) { t_hammernode *np; if (np = x->x_tree.t_first) /* CHECKED nop if empty */ { t_float result = HAMMERNODE_GETFLOAT(np); while (np = np->n_next) if (HAMMERNODE_GETFLOAT(np) > result) result = HAMMERNODE_GETFLOAT(np); funbuff_dooutput(x, result, x->x_lastdelta); /* CHECKED pointer not updated */ } } static void funbuff_next(t_funbuff *x) { t_hammernode *np; if (!x->x_tree.t_root) return; if (!(np = x->x_pointer)) { outlet_bang(x->x_bangout); /* CHECKED banging until reset */ return; } if (x->x_pointerset) x->x_lastdelta = 0; else if (np->n_prev) x->x_lastdelta = np->n_key - np->n_prev->n_key; else x->x_lastdelta = 0; /* CHECKED corrupt delta sent here... */ funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np), x->x_lastdelta); x->x_pointer = np->n_next; x->x_pointerset = 0; } static void funbuff_set(t_funbuff *x, t_symbol *s, int ac, t_atom *av) { /* CHECKED symbols somehow bashed to zeros, decreasing x coords corrupt the funbuff -- not emulated here... */ int i = ac; t_atom *ap = av; while (i--) if (ap++->a_type != A_FLOAT) { loud_error((t_pd *)x, "bad input (not a number) -- no data to set"); return; } if (!ac || (ac % 2)) { /* CHECKED odd/null ac loudly rejected, current contents preserved */ loud_error((t_pd *)x, "bad input (%s) -- no data to set", (ac ? "odd arg count" : "no input")); return; } funbuff_clear(x); /* CHECKED the contents is replaced */ while (ac--) { int ndx = (int)av++->a_w.w_float; if (!hammertree_insertfloat(&x->x_tree, ndx, av++->a_w.w_float, 1)) return; ac--; } } static void funbuff_doread(t_funbuff *x, t_symbol *fn) { t_binbuf *bb = binbuf_new(); int ac; t_atom *av; char buf[MAXPDSTRING]; /* FIXME use open_via_path() */ canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); binbuf_read(bb, buf, "", 0); if ((ac = binbuf_getnatom(bb)) && (av = binbuf_getvec(bb)) && av->a_type == A_SYMBOL && av->a_w.w_symbol == gensym("funbuff")) { post("funbuff_read: %s read successful", fn->s_name); /* CHECKED */ funbuff_set(x, 0, ac-1, av+1); } else /* CHECKED no complaints... */ loud_error((t_pd *)x, "invalid file %s", fn->s_name); binbuf_free(bb); } static void funbuff_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { funbuff_doread((t_funbuff *)z, fn); } static void funbuff_dowrite(t_funbuff *x, t_symbol *fn) { t_binbuf *bb = binbuf_new(); char buf[MAXPDSTRING]; t_hammernode *np; binbuf_addv(bb, "s", atom_getsymbol(binbuf_getvec(x->x_ob.te_binbuf))); for (np = x->x_tree.t_first; np; np = np->n_next) binbuf_addv(bb, "if", np->n_key, HAMMERNODE_GETFLOAT(np)); canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); binbuf_write(bb, buf, "", 0); binbuf_free(bb); } static void funbuff_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { funbuff_dowrite((t_funbuff *)z, fn); } static void funbuff_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) { t_funbuff *x = (t_funbuff *)z; if (x->x_embedflag) { t_hammernode *np; binbuf_addv(bb, "ssi;", bindsym, gensym("embed"), 1); if (np = x->x_tree.t_first) { binbuf_addv(bb, "ss", bindsym, gensym("set")); for (; np; np = np->n_next) binbuf_addv(bb, "if", np->n_key, HAMMERNODE_GETFLOAT(np)); binbuf_addsemi(bb); } } } /* CHECKED symbol arg ok */ static void funbuff_read(t_funbuff *x, t_symbol *s) { if (s && s != &s_) funbuff_doread(x, s); else hammerpanel_open(x->x_filehandle, 0); } /* CHECKED symbol arg not allowed -- a bug? but CHECKME other classes (cf seq's filetype dilemma) */ static void funbuff_write(t_funbuff *x, t_symbol *s) { if (s && s != &s_) funbuff_dowrite(x, s); else /* CHECKME default name */ hammerpanel_save(x->x_filehandle, canvas_getdir(x->x_canvas), x->x_defname); } static void funbuff_delete(t_funbuff *x, t_symbol *s, int ac, t_atom *av) { if (ac && av->a_type == A_FLOAT && (ac == 1 || (ac == 2 && av[1].a_type == A_FLOAT))) { /* CHECKED float is silently truncated */ int ndx = (int)av->a_w.w_float; t_hammernode *np; if ((np = hammertree_search(&x->x_tree, ndx)) && (ac == 1 || HAMMERNODE_GETFLOAT(np) == av[1].a_w.w_float)) { if (np == x->x_pointer) x->x_pointer = 0; /* CHECKED corrupt pointer left here... */ hammertree_delete(&x->x_tree, np); /* FIXME */ } /* CHECKED mismatch silently ignored */ } else loud_messarg((t_pd *)x, s); /* CHECKED */ } static void funbuff_find(t_funbuff *x, t_floatarg f) { t_hammernode *np; if (np = x->x_tree.t_first) { do { /* CHECKED lastdelta preserved */ if (HAMMERNODE_GETFLOAT(np) == f) funbuff_dooutput(x, np->n_key, x->x_lastdelta); } while (np = np->n_next); /* CHECKED no bangout, no complaint if nothing found */ } else loud_error((t_pd *)x, "nothing to find"); /* CHECKED */ } static void funbuff_dump(t_funbuff *x) { t_hammernode *np; if (np = x->x_tree.t_first) { do { x->x_lastdelta = HAMMERNODE_GETFLOAT(np); /* CHECKED */ /* float value preserved (this is incompatible) */ funbuff_dooutput(x, np->n_key, x->x_lastdelta); } while (np = np->n_next); /* CHECKED no bangout */ } else loud_error((t_pd *)x, "nothing to dump"); /* CHECKED */ } /* CHECKME if pointer is updated */ static void funbuff_dointerp(t_funbuff *x, t_floatarg f, int vsz, t_float *vec) { t_hammernode *np1; int trunc = (int)f; if (trunc > f) trunc--; /* CHECKME negative floats */ if (np1 = hammertree_closest(&x->x_tree, trunc, 0)) { float value = HAMMERNODE_GETFLOAT(np1); t_hammernode *np2 = np1->n_next; if (np2) { float delta = (float)(np2->n_key - np1->n_key); /* this is incompatible -- CHECKED float argument is silently truncated (which does not make much sense here), CHECKME again */ float frac = f - np1->n_key; if (frac < 0 || frac >= delta) { loudbug_bug("funbuff_dointerp"); return; } frac /= delta; if (vec) { /* CHECKME */ float vpos = (vsz - 1) * frac; int vndx = (int)vpos; float vfrac = vpos - vndx; if (vndx < 0 || vndx >= vsz - 1) { loudbug_bug("funbuff_dointerp redundant test..."); return; } vec += vndx; frac = *vec + (vec[1] - *vec) * vfrac; } value += (HAMMERNODE_GETFLOAT(np2) - HAMMERNODE_GETFLOAT(np1)) * frac; } funbuff_dooutput(x, value, x->x_lastdelta); /* CHECKME !np2 */ } else if (np1 = hammertree_closest(&x->x_tree, trunc, 1)) /* CHECKME */ funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np1), x->x_lastdelta); } static void funbuff_interp(t_funbuff *x, t_floatarg f) { funbuff_dointerp(x, f, 0, 0); } static void funbuff_interptab(t_funbuff *x, t_symbol *s, t_floatarg f) { int vsz; t_float *vec; if (vec = vefl_get(s, &vsz, 0, (t_pd *)x)) { if (vsz > 2) funbuff_dointerp(x, f, vsz, vec); else funbuff_dointerp(x, f, 0, 0); } } static void funbuff_reduce(t_funbuff *x, t_floatarg f) { loud_notimplemented((t_pd *)x, "reduce"); } static void funbuff_select(t_funbuff *x, t_floatarg f1, t_floatarg f2) { loud_notimplemented((t_pd *)x, "select"); } /* CHECKED (sub)buffer's copy is stored, as expected -- 'delete' does not modify the clipboard */ /* CHECKED cut entire contents if no selection */ static void funbuff_cut(t_funbuff *x) { loud_notimplemented((t_pd *)x, "cut"); } /* CHECKED copy entire contents if no selection */ static void funbuff_copy(t_funbuff *x) { loud_notimplemented((t_pd *)x, "copy"); } static void funbuff_paste(t_funbuff *x) { loud_notimplemented((t_pd *)x, "paste"); } static void funbuff_undo(t_funbuff *x) { /* CHECKED apparently not working in 4.07 */ loud_notimplemented((t_pd *)x, "undo"); } #ifdef HAMMERTREE_DEBUG static void funbuff_debug(t_funbuff *x, t_floatarg f) { hammertree_debug(&x->x_tree, (int)f, 0); } #endif static void funbuff_free(t_funbuff *x) { hammerfile_free(x->x_filehandle); hammertree_clear(&x->x_tree, 0); } static void *funbuff_new(t_symbol *s) { t_funbuff *x = (t_funbuff *)pd_new(funbuff_class); x->x_canvas = canvas_getcurrent(); x->x_valueset = 0; x->x_pointer = 0; x->x_pointerset = 0; /* CHECKME, rename to intraversal? */ x->x_lastdelta = 0; x->x_embedflag = 0; hammertree_inittyped(&x->x_tree, HAMMERTYPE_FLOAT, 0); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_float); x->x_deltaout = outlet_new((t_object *)x, &s_float); x->x_bangout = outlet_new((t_object *)x, &s_bang); if (s && s != &s_) { x->x_defname = s; /* CHECKME if 'read' changes this */ funbuff_doread(x, s); } else x->x_defname = &s_; x->x_filehandle = hammerfile_new((t_pd *)x, funbuff_embedhook, funbuff_readhook, funbuff_writehook, 0); return (x); } void funbuff_setup(void) { funbuff_class = class_new(gensym("funbuff"), (t_newmethod)funbuff_new, (t_method)funbuff_free, sizeof(t_funbuff), 0, A_DEFSYM, 0); class_addbang(funbuff_class, funbuff_bang); class_addfloat(funbuff_class, funbuff_float); class_addmethod(funbuff_class, (t_method)funbuff_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_clear, gensym("clear"), 0); class_addmethod(funbuff_class, (t_method)funbuff_goto, gensym("goto"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_min, gensym("min"), 0); class_addmethod(funbuff_class, (t_method)funbuff_max, gensym("max"), 0); class_addmethod(funbuff_class, (t_method)funbuff_next, gensym("next"), 0); class_addmethod(funbuff_class, (t_method)funbuff_embed, gensym("embed"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_read, gensym("read"), A_DEFSYM, 0); class_addmethod(funbuff_class, (t_method)funbuff_write, gensym("write"), A_DEFSYM, 0); class_addmethod(funbuff_class, (t_method)funbuff_set, gensym("set"), A_GIMME, 0); class_addmethod(funbuff_class, (t_method)funbuff_delete, gensym("delete"), A_GIMME, 0); class_addmethod(funbuff_class, (t_method)funbuff_find, gensym("find"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_dump, gensym("dump"), 0); class_addmethod(funbuff_class, (t_method)funbuff_interp, gensym("interp"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_interptab, gensym("interptab"), A_FLOAT, A_SYMBOL, 0); class_addmethod(funbuff_class, (t_method)funbuff_reduce, gensym("reduce"), A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_select, gensym("select"), A_FLOAT, A_FLOAT, 0); class_addmethod(funbuff_class, (t_method)funbuff_cut, gensym("cut"), 0); class_addmethod(funbuff_class, (t_method)funbuff_copy, gensym("copy"), 0); class_addmethod(funbuff_class, (t_method)funbuff_paste, gensym("paste"), 0); class_addmethod(funbuff_class, (t_method)funbuff_undo, gensym("undo"), 0); #ifdef HAMMERTREE_DEBUG class_addmethod(funbuff_class, (t_method)funbuff_debug, gensym("debug"), A_DEFFLOAT, 0); #endif hammerfile_setup(funbuff_class, 1); } cyclone-0.1-alpha55/cyclone/hammer/bondo.c0000644000076500007650000002550011466617445017113 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER revisit buffer handling (maxsize, reentrancy) */ /* LATER rethink handling of symbols */ /* CHECKED: if 'n' argument is given, then store whole messages, instead of distributing atoms across successive slots. This is a new, buddy-like behaviour. */ /* CHECKED: without 'n' argument, 'symbol test' is parsed as two symbol atoms, but 'float 1' (or 'list 1') as a single float. */ #include #include "m_pd.h" #include "common/grow.h" #define BONDO_MINSLOTS 2 #define BONDO_INISIZE 4 /* LATER rethink (useful only in multiatom mode) */ typedef struct _bondo { t_object x_ob; t_float x_delay; int x_multiatom; int x_nslots; int x_nproxies; /* as requested (and allocated) */ t_pd **x_proxies; t_outlet **x_outs; t_clock *x_clock; } t_bondo; typedef struct _bondo_proxy { t_object p_ob; t_bondo *p_master; int p_id; t_symbol *p_selector; t_float p_float; t_symbol *p_symbol; t_gpointer *p_pointer; int p_size; /* as allocated */ int p_natoms; /* as used */ t_atom *p_message; t_atom p_messini[BONDO_INISIZE]; } t_bondo_proxy; static t_class *bondo_class; static t_class *bondo_proxy_class; static void bondo_doit(t_bondo *x) { t_bondo_proxy **p = (t_bondo_proxy **)x->x_proxies; int i = x->x_nslots; p = (t_bondo_proxy **)x->x_proxies; i = x->x_nslots; while (i--) { t_symbol *s = p[i]->p_selector; /* LATER consider complaining about extra arguments (CHECKED) */ if (s == &s_bang) outlet_bang(x->x_outs[i]); else if (s == &s_float) outlet_float(x->x_outs[i], p[i]->p_float); else if (s == &s_symbol && p[i]->p_symbol) { /* LATER rethink */ if (x->x_multiatom) outlet_symbol(x->x_outs[i], p[i]->p_symbol); else outlet_anything(x->x_outs[i], p[i]->p_symbol, 0, 0); } else if (s == &s_pointer) { /* LATER */ } else if (s == &s_list) outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); else if (s) /* CHECKED: a slot may be inactive (in multiatom mode) */ outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); } } static void bondo_arm(t_bondo *x) { if (x->x_delay <= 0) bondo_doit(x); else clock_delay(x->x_clock, x->x_delay); } static void bondo_proxy_bang(t_bondo_proxy *x) { bondo_arm(x->p_master); /* CHECKED: bang in any inlet works in this way */ } static void bondo_proxy_dofloat(t_bondo_proxy *x, t_float f, int doit) { x->p_selector = &s_float; x->p_float = f; x->p_natoms = 0; /* defensive */ if (doit) bondo_arm(x->p_master); } static void bondo_proxy_float(t_bondo_proxy *x, t_float f) { bondo_proxy_dofloat(x, f, 1); } static void bondo_proxy_dosymbol(t_bondo_proxy *x, t_symbol *s, int doit) { x->p_selector = &s_symbol; x->p_symbol = s; x->p_natoms = 0; /* defensive */ if (doit) bondo_arm(x->p_master); } static void bondo_proxy_symbol(t_bondo_proxy *x, t_symbol *s) { bondo_proxy_dosymbol(x, s, 1); } static void bondo_proxy_dopointer(t_bondo_proxy *x, t_gpointer *gp, int doit) { x->p_selector = &s_pointer; x->p_pointer = gp; x->p_natoms = 0; /* defensive */ if (doit) bondo_arm(x->p_master); } static void bondo_proxy_pointer(t_bondo_proxy *x, t_gpointer *gp) { bondo_proxy_dopointer(x, gp, 1); } /* CHECKED: the slots fire in right-to-left order, but they trigger only once (refman error) */ static void bondo_distribute(t_bondo *x, int startid, t_symbol *s, int ac, t_atom *av, int doit) { t_atom *ap = av; t_bondo_proxy **pp; int id = startid + ac; if (s) id++; if (id > x->x_nslots) id = x->x_nslots; ap += id - startid; pp = (t_bondo_proxy **)(x->x_proxies + id); if (s) ap--; while (ap-- > av) { pp--; if (ap->a_type == A_FLOAT) bondo_proxy_dofloat(*pp, ap->a_w.w_float, 0); else if (ap->a_type == A_SYMBOL) bondo_proxy_dosymbol(*pp, ap->a_w.w_symbol, 0); else if (ap->a_type == A_POINTER) bondo_proxy_dopointer(*pp, ap->a_w.w_gpointer, 0); } if (s) bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[startid], s, 0); if (doit) bondo_arm(x); } static void bondo_proxy_domultiatom(t_bondo_proxy *x, int ac, t_atom *av, int doit) { if (ac > x->p_size) { /* LATER consider using BONDO_MAXSIZE (and warning if exceeded) */ x->p_message = grow_nodata(&ac, &x->p_size, x->p_message, BONDO_INISIZE, x->p_messini, sizeof(*x->p_message)); } x->p_natoms = ac; memcpy(x->p_message, av, ac * sizeof(*x->p_message)); if (doit) bondo_arm(x->p_master); } static void bondo_proxy_dolist(t_bondo_proxy *x, int ac, t_atom *av, int doit) { if (x->p_master->x_multiatom) { x->p_selector = &s_list; bondo_proxy_domultiatom(x, ac, av, doit); } else bondo_distribute(x->p_master, x->p_id, 0, ac, av, doit); } static void bondo_proxy_list(t_bondo_proxy *x, t_symbol *s, int ac, t_atom *av) { bondo_proxy_dolist(x, ac, av, 1); } static void bondo_proxy_doanything(t_bondo_proxy *x, t_symbol *s, int ac, t_atom *av, int doit) { if (x->p_master->x_multiatom) { /* LATER rethink and CHECKME */ if (s == &s_symbol) { if (ac && av->a_type == A_SYMBOL) bondo_proxy_dosymbol(x, av->a_w.w_symbol, doit); else bondo_proxy_dosymbol(x, &s_symbol, doit); } else { x->p_selector = s; bondo_proxy_domultiatom(x, ac, av, doit); } } else bondo_distribute(x->p_master, x->p_id, s, ac, av, doit); } static void bondo_proxy_anything(t_bondo_proxy *x, t_symbol *s, int ac, t_atom *av) { bondo_proxy_doanything(x, s, ac, av, 1); } static void bondo_proxy_set(t_bondo_proxy *x, t_symbol *s, int ac, t_atom *av) { if (ac) { if (av->a_type == A_FLOAT) { if (ac > 1) bondo_proxy_dolist(x, ac, av, 0); else bondo_proxy_dofloat(x, av->a_w.w_float, 0); } else if (av->a_type == A_SYMBOL) /* CHECKED: no tests for 'set float ...' and 'set list...' -- the parsing is made in an output routine */ bondo_proxy_doanything(x, av->a_w.w_symbol, ac-1, av+1, 0); else if (av->a_type == A_POINTER) bondo_proxy_dopointer(x, av->a_w.w_gpointer, 0); } /* CHECKED: 'set' without arguments makes a slot inactive, if multiatom, but is ignored, if !multiatom */ else if (x->p_master->x_multiatom) x->p_selector = 0; } static void bondo_bang(t_bondo *x) { bondo_proxy_bang((t_bondo_proxy *)x->x_proxies[0]); } static void bondo_float(t_bondo *x, t_float f) { bondo_proxy_dofloat((t_bondo_proxy *)x->x_proxies[0], f, 1); } static void bondo_symbol(t_bondo *x, t_symbol *s) { bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[0], s, 1); } static void bondo_pointer(t_bondo *x, t_gpointer *gp) { bondo_proxy_dopointer((t_bondo_proxy *)x->x_proxies[0], gp, 1); } static void bondo_list(t_bondo *x, t_symbol *s, int ac, t_atom *av) { bondo_proxy_dolist((t_bondo_proxy *)x->x_proxies[0], ac, av, 1); } static void bondo_anything(t_bondo *x, t_symbol *s, int ac, t_atom *av) { bondo_proxy_doanything((t_bondo_proxy *)x->x_proxies[0], s, ac, av, 1); } static void bondo_set(t_bondo *x, t_symbol *s, int ac, t_atom *av) { bondo_proxy_set((t_bondo_proxy *)x->x_proxies[0], s, ac, av); } static void bondo_free(t_bondo *x) { if (x->x_clock) clock_free(x->x_clock); if (x->x_proxies) { int i = x->x_nslots; while (i--) { t_bondo_proxy *y = (t_bondo_proxy *)x->x_proxies[i]; if (y->p_message != y->p_messini) freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); pd_free((t_pd *)y); } freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); } if (x->x_outs) freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs)); } static void *bondo_new(t_symbol *s, int ac, t_atom *av) { t_bondo *x; int i, nslots, nproxies = BONDO_MINSLOTS; int multiatom = 0; t_float delay = 0; t_pd **proxies; t_outlet **outs; i = 0; while (ac--) { /* CHECKED: no warnings */ if (av->a_type == A_FLOAT) { if (i == 0) nproxies = (int)av->a_w.w_float; else if (i == 1) delay = av->a_w.w_float; i++; } else if (av->a_type == A_SYMBOL) { if (av->a_w.w_symbol == gensym("n")) multiatom = 1; /* CHECKED: 'n' has to be the last argument given; the arguments after any symbol are silently ignored -- LATER decide if we should comply and break here */ } av++; } if (nproxies < BONDO_MINSLOTS) nproxies = BONDO_MINSLOTS; if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) return (0); for (nslots = 0; nslots < nproxies; nslots++) if (!(proxies[nslots] = pd_new(bondo_proxy_class))) break; if (nslots < BONDO_MINSLOTS || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs)))) { i = nslots; while (i--) pd_free(proxies[i]); freebytes(proxies, nproxies * sizeof(*proxies)); return (0); } x = (t_bondo *)pd_new(bondo_class); x->x_delay = delay; x->x_multiatom = multiatom; x->x_nslots = nslots; x->x_nproxies = nproxies; x->x_proxies = proxies; x->x_outs = outs; for (i = 0; i < nslots; i++) { t_bondo_proxy *y = (t_bondo_proxy *)proxies[i]; y->p_master = x; y->p_id = i; y->p_selector = &s_float; /* CHECKED: it is so in multiatom mode too */ y->p_float = 0; y->p_symbol = 0; y->p_pointer = 0; y->p_size = BONDO_INISIZE; y->p_natoms = 0; y->p_message = y->p_messini; if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); x->x_outs[i] = outlet_new((t_object *)x, &s_anything); } x->x_clock = clock_new(x, (t_method)bondo_doit); return (x); } void bondo_setup(void) { bondo_class = class_new(gensym("bondo"), (t_newmethod)bondo_new, (t_method)bondo_free, sizeof(t_bondo), 0, A_GIMME, 0); class_addbang(bondo_class, bondo_bang); class_addfloat(bondo_class, bondo_float); class_addsymbol(bondo_class, bondo_symbol); class_addpointer(bondo_class, bondo_pointer); class_addlist(bondo_class, bondo_list); class_addanything(bondo_class, bondo_anything); class_addmethod(bondo_class, (t_method)bondo_set, gensym("set"), A_GIMME, 0); bondo_proxy_class = class_new(gensym("_bondo_proxy"), 0, 0, sizeof(t_bondo_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(bondo_proxy_class, bondo_proxy_bang); class_addfloat(bondo_proxy_class, bondo_proxy_float); class_addsymbol(bondo_proxy_class, bondo_proxy_symbol); class_addpointer(bondo_proxy_class, bondo_proxy_pointer); class_addlist(bondo_proxy_class, bondo_proxy_list); class_addanything(bondo_proxy_class, bondo_proxy_anything); class_addmethod(bondo_proxy_class, (t_method)bondo_proxy_set, gensym("set"), A_GIMME, 0); } cyclone-0.1-alpha55/cyclone/hammer/split.c0000644000076500007650000000333111466617445017143 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" /* CHECKED: 'list ' silently ignored (LATER remove a warning) ' ' as '' (LATER remove a warning) LATER more compatibility checks are needed... LATER sort out float/int dilemmas */ typedef struct _split { t_object x_ob; int x_floatmode; t_float x_min; t_float x_max; t_outlet *x_out2; } t_split; static t_class *split_class; static void split_float(t_split *x, t_float f) { if (x->x_floatmode) { if (f >= x->x_min && f <= x->x_max) outlet_float(((t_object *)x)->ob_outlet, f); else outlet_float(x->x_out2, f); } else { /* CHECKED: no pre-truncation */ if (f >= x->x_min && f <= x->x_max) outlet_float(((t_object *)x)->ob_outlet, (int)f); else outlet_float(x->x_out2, (int)f); } } static void *split_new(t_floatarg f1, t_floatarg f2) { t_split *x = (t_split *)pd_new(split_class); x->x_floatmode = (f1 != (int)f1); /* CHECKED: defaults are [0..0] and [0..f1] (for positive f1) or [f1..0] */ if (f1 < f2) /* CHECKED */ x->x_min = f1, x->x_max = f2; else x->x_min = f2, x->x_max = f1; floatinlet_new((t_object *)x, &x->x_min); floatinlet_new((t_object *)x, &x->x_max); outlet_new((t_object *)x, &s_float); x->x_out2 = outlet_new((t_object *)x, &s_float); return (x); } void split_setup(void) { split_class = class_new(gensym("split"), (t_newmethod)split_new, 0, sizeof(t_split), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addfloat(split_class, split_float); } cyclone-0.1-alpha55/cyclone/hammer/xbendout.c0000644000076500007650000000274311466617445017646 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _xbendout { t_object x_ob; t_float x_channel; int x_value; } t_xbendout; static t_class *xbendout_class; static void xbendout_dooutput(t_xbendout *x) { int value = x->x_value; int channel = (int)x->x_channel; /* CHECKME */ if (value >= 0 && /* CHECKME */ value <= 16383 && /* CHECKME */ channel > 0) /* CHECKME */ { outlet_float(((t_object *)x)->ob_outlet, 224 + ((channel-1) & 0x0F)); outlet_float(((t_object *)x)->ob_outlet, value & 0x7F); outlet_float(((t_object *)x)->ob_outlet, value >> 7); } } static void xbendout_float(t_xbendout *x, t_float f) { x->x_value = (int)f; /* CHECKME */ xbendout_dooutput(x); } static void *xbendout_new(t_floatarg f) { t_xbendout *x = (t_xbendout *)pd_new(xbendout_class); floatinlet_new((t_object *)x, &x->x_channel); outlet_new((t_object *)x, &s_float); x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */ x->x_value = 8192; /* CHECKME if not -1 */ return (x); } void xbendout_setup(void) { xbendout_class = class_new(gensym("xbendout"), (t_newmethod)xbendout_new, 0, sizeof(t_xbendout), 0, A_DEFFLOAT, 0); class_addbang(xbendout_class, xbendout_dooutput); class_addfloat(xbendout_class, xbendout_float); } cyclone-0.1-alpha55/cyclone/hammer/buddy.c0000644000076500007650000001532611466617445017126 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER compare with buddy.c from max sdk */ /* LATER revisit buffer handling (maxsize, reentrancy) */ #include #include "m_pd.h" #include "common/grow.h" #define BUDDY_MINSLOTS 2 #define BUDDY_INISIZE 4 /* LATER rethink */ typedef struct _buddy { t_object x_ob; int x_nslots; int x_nproxies; /* as requested (and allocated) */ t_pd **x_proxies; t_outlet **x_outs; } t_buddy; typedef struct _buddy_proxy { t_object p_ob; t_buddy *p_master; t_symbol *p_selector; t_float p_float; t_symbol *p_symbol; t_gpointer *p_pointer; int p_size; /* as allocated */ int p_natoms; /* as used */ t_atom *p_message; t_atom p_messini[BUDDY_INISIZE]; } t_buddy_proxy; static t_class *buddy_class; static t_class *buddy_proxy_class; static void buddy_clear(t_buddy *x) { t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies; int i = x->x_nslots; while (i--) { (*p)->p_selector = 0; (*p++)->p_natoms = 0; /* defensive */ } } static void buddy_check(t_buddy *x) { t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies; int i = x->x_nslots; while (i--) if (!(*p++)->p_selector) return; p = (t_buddy_proxy **)x->x_proxies; i = x->x_nslots; while (i--) { t_symbol *s = p[i]->p_selector; if (s == &s_bang) outlet_bang(x->x_outs[i]); else if (s == &s_float) outlet_float(x->x_outs[i], p[i]->p_float); else if (s == &s_symbol && p[i]->p_symbol) outlet_symbol(x->x_outs[i], p[i]->p_symbol); else if (s == &s_pointer) { /* LATER */ } else if (s == &s_list) outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); else if (s) outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); } buddy_clear(x); } static void buddy_proxy_bang(t_buddy_proxy *x) { x->p_selector = &s_bang; x->p_natoms = 0; /* defensive */ buddy_check(x->p_master); } static void buddy_proxy_float(t_buddy_proxy *x, t_float f) { x->p_selector = &s_float; x->p_float = f; x->p_natoms = 0; /* defensive */ buddy_check(x->p_master); } static void buddy_proxy_symbol(t_buddy_proxy *x, t_symbol *s) { x->p_selector = &s_symbol; x->p_symbol = s; x->p_natoms = 0; /* defensive */ buddy_check(x->p_master); } static void buddy_proxy_pointer(t_buddy_proxy *x, t_gpointer *gp) { x->p_selector = &s_pointer; x->p_pointer = gp; x->p_natoms = 0; /* defensive */ buddy_check(x->p_master); } static void buddy_proxy_domessage(t_buddy_proxy *x, int ac, t_atom *av) { if (ac > x->p_size) { /* LATER consider using BUDDY_MAXSIZE (and warning if exceeded) */ x->p_message = grow_nodata(&ac, &x->p_size, x->p_message, BUDDY_INISIZE, x->p_messini, sizeof(*x->p_message)); } x->p_natoms = ac; memcpy(x->p_message, av, ac * sizeof(*x->p_message)); buddy_check(x->p_master); } static void buddy_proxy_list(t_buddy_proxy *x, t_symbol *s, int ac, t_atom *av) { x->p_selector = &s_list; /* LATER rethink */ buddy_proxy_domessage(x, ac, av); } static void buddy_proxy_anything(t_buddy_proxy *x, t_symbol *s, int ac, t_atom *av) { x->p_selector = s; /* LATER rethink */ buddy_proxy_domessage(x, ac, av); } static void buddy_bang(t_buddy *x) { buddy_proxy_bang((t_buddy_proxy *)x->x_proxies[0]); } static void buddy_float(t_buddy *x, t_float f) { buddy_proxy_float((t_buddy_proxy *)x->x_proxies[0], f); } static void buddy_symbol(t_buddy *x, t_symbol *s) { buddy_proxy_symbol((t_buddy_proxy *)x->x_proxies[0], s); } static void buddy_pointer(t_buddy *x, t_gpointer *gp) { buddy_proxy_pointer((t_buddy_proxy *)x->x_proxies[0], gp); } static void buddy_list(t_buddy *x, t_symbol *s, int ac, t_atom *av) { buddy_proxy_list((t_buddy_proxy *)x->x_proxies[0], s, ac, av); } static void buddy_anything(t_buddy *x, t_symbol *s, int ac, t_atom *av) { buddy_proxy_anything((t_buddy_proxy *)x->x_proxies[0], s, ac, av); } static void buddy_free(t_buddy *x) { if (x->x_proxies) { int i = x->x_nslots; while (i--) { t_buddy_proxy *y = (t_buddy_proxy *)x->x_proxies[i]; if (y->p_message != y->p_messini) freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); pd_free((t_pd *)y); } freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); } if (x->x_outs) freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs)); } static void *buddy_new(t_floatarg f) { t_buddy *x; int i, nslots, nproxies = (int)f; t_pd **proxies; t_outlet **outs; if (nproxies < BUDDY_MINSLOTS) nproxies = BUDDY_MINSLOTS; if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) return (0); for (nslots = 0; nslots < nproxies; nslots++) if (!(proxies[nslots] = pd_new(buddy_proxy_class))) break; if (nslots < BUDDY_MINSLOTS || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs)))) { int i = nslots; while (i--) pd_free(proxies[i]); freebytes(proxies, nproxies * sizeof(*proxies)); return (0); } x = (t_buddy *)pd_new(buddy_class); x->x_nslots = nslots; x->x_nproxies = nproxies; x->x_proxies = proxies; x->x_outs = outs; for (i = 0; i < nslots; i++) { t_buddy_proxy *y = (t_buddy_proxy *)proxies[i]; y->p_master = x; y->p_selector = 0; y->p_float = 0; y->p_symbol = 0; y->p_pointer = 0; y->p_size = BUDDY_INISIZE; y->p_natoms = 0; y->p_message = y->p_messini; if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); x->x_outs[i] = outlet_new((t_object *)x, &s_anything); } return (x); } void buddy_setup(void) { buddy_class = class_new(gensym("buddy"), (t_newmethod)buddy_new, (t_method)buddy_free, sizeof(t_buddy), 0, A_DEFFLOAT, 0); class_addbang(buddy_class, buddy_bang); class_addfloat(buddy_class, buddy_float); class_addsymbol(buddy_class, buddy_symbol); class_addpointer(buddy_class, buddy_pointer); class_addlist(buddy_class, buddy_list); class_addanything(buddy_class, buddy_anything); class_addmethod(buddy_class, (t_method)buddy_clear, gensym("clear"), 0); buddy_proxy_class = class_new(gensym("_buddy_proxy"), 0, 0, sizeof(t_buddy_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(buddy_proxy_class, buddy_proxy_bang); class_addfloat(buddy_proxy_class, buddy_proxy_float); class_addsymbol(buddy_proxy_class, buddy_proxy_symbol); class_addpointer(buddy_proxy_class, buddy_proxy_pointer); class_addlist(buddy_proxy_class, buddy_proxy_list); class_addanything(buddy_proxy_class, buddy_proxy_anything); } cyclone-0.1-alpha55/cyclone/hammer/anal.c0000644000076500007650000000542011466617445016724 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/loud.h" #define ANAL_DEFSIZE 128 #define ANAL_MAXSIZE 1024 typedef struct _anal { t_object x_ob; int x_value; /* negative, if initialized or reset */ int x_size; int x_bytesize; int *x_table; /* CHECKED: the 'weight' count is a signed short (2 bytes), wrapping into negative domain without any warning. LATER consider complaining at == SHRT_MAX. */ } t_anal; static t_class *anal_class; static void anal_reset(t_anal *x) { x->x_value = -1; } static void anal_clear(t_anal *x) { memset(x->x_table, 0, x->x_bytesize); } static void anal_float(t_anal *x, t_float f) { int value; if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */ { /* CHECKED: any input negative or >= size is ignored with an error -- there is no output, and a previous state is kept. */ if (value >= 0 && value < x->x_size) { if (x->x_value >= 0) { t_atom at[3]; int ndx = x->x_value * x->x_size + value; x->x_table[ndx]++; SETFLOAT(at, x->x_value); SETFLOAT(&at[1], value); SETFLOAT(&at[2], x->x_table[ndx]); outlet_list(((t_object *)x)->ob_outlet, &s_list, 3, at); } x->x_value = value; } else loud_error((t_pd *)x, "%d outside of table bounds", value); } } static void anal_free(t_anal *x) { if (x->x_table) freebytes(x->x_table, x->x_bytesize); } static void *anal_new(t_floatarg f) { t_anal *x; int size = (int)f; int bytesize; int *table; if (size < 1) /* CHECKED: 1 is allowed (such an object rejects any nonzero input) */ size = ANAL_DEFSIZE; else if (size > ANAL_MAXSIZE) { /* CHECKED: */ loud_warning(&anal_class, 0, "size too large, using %d", ANAL_MAXSIZE); size = ANAL_MAXSIZE; /* LATER switch into a 'sparse' mode */ } /* CHECKED: actually the bytesize is size * size * sizeof(short), and it shows up in */ bytesize = size * size * sizeof(*table); if (!(table = (int *)getbytes(bytesize))) return (0); x = (t_anal *)pd_new(anal_class); x->x_size = size; x->x_bytesize = bytesize; x->x_table = table; outlet_new((t_object *)x, &s_list); anal_reset(x); anal_clear(x); return (x); } void anal_setup(void) { anal_class = class_new(gensym("anal"), (t_newmethod)anal_new, (t_method)anal_free, sizeof(t_anal), 0, A_DEFFLOAT, 0); class_addfloat(anal_class, anal_float); class_addmethod(anal_class, (t_method)anal_reset, gensym("reset"), 0); class_addmethod(anal_class, (t_method)anal_clear, gensym("clear"), 0); } cyclone-0.1-alpha55/cyclone/hammer/universal.c0000644000076500007650000001250011466617445020016 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "g_canvas.h" #include "unstable/pd_imp.h" #include "common/loud.h" /* LATER fragilize */ typedef struct _universal { t_object x_ob; t_glist *x_glist; t_int x_descend; } t_universal; static t_class *universal_class; static void universal_dobang(t_glist *glist, int descend, t_symbol *cname) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ pd_bang(&g->g_pd); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_dobang((t_glist *)g, descend, cname); } static void universal_dofloat(t_glist *glist, int descend, t_symbol *cname, t_float f) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ pd_float(&g->g_pd, f); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_dofloat((t_glist *)g, descend, cname, f); } static void universal_dosymbol(t_glist *glist, int descend, t_symbol *cname, t_symbol *s) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ pd_symbol(&g->g_pd, s); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_dosymbol((t_glist *)g, descend, cname, s); } static void universal_dopointer(t_glist *glist, int descend, t_symbol *cname, t_gpointer *gp) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ pd_pointer(&g->g_pd, gp); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_dopointer((t_glist *)g, descend, cname, gp); } static void universal_dolist(t_glist *glist, int descend, t_symbol *cname, int ac, t_atom *av) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ pd_list(&g->g_pd, &s_list, ac, av); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_dolist((t_glist *)g, descend, cname, ac, av); } static void universal_doanything(t_glist *glist, int descend, t_symbol *cname, t_symbol *s, int ac, t_atom *av) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ typedmess(&g->g_pd, s, ac, av); if (descend) for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ universal_doanything((t_glist *)g, descend, cname, s, ac, av); } /* LATER rethink type-checking -- it is borrowed from typedmess(). Anyway, do it once, before traversal, bypassing the generic mechanism performed for every object. */ static void universal_anything(t_universal *x, t_symbol *s, int ac, t_atom *av) { /* CHECKED selector without arguments ignored with no complaints */ if (x->x_glist && s && ac) { if (av->a_type == A_FLOAT) { if (ac > 1) universal_dolist(x->x_glist, x->x_descend, s, ac, av); else universal_dofloat(x->x_glist, x->x_descend, s, av->a_w.w_float); } else if (av->a_type == A_SYMBOL) { if (av->a_w.w_symbol == &s_bang) universal_dobang(x->x_glist, x->x_descend, s); else if (av->a_w.w_symbol == &s_float) { if (ac == 1) universal_dofloat(x->x_glist, x->x_descend, s, 0.); else if (av[1].a_type == A_FLOAT) universal_dofloat(x->x_glist, x->x_descend, s, av[1].a_w.w_float); else loud_error((t_pd *)x, "Bad argument for message 'float'"); } else if (av->a_w.w_symbol == &s_symbol) universal_dosymbol(x->x_glist, x->x_descend, s, (ac > 1 && av[1].a_type == A_SYMBOL ? av[1].a_w.w_symbol : &s_)); else if (av->a_w.w_symbol == &s_list) universal_dolist(x->x_glist, x->x_descend, s, ac - 1, av + 1); else universal_doanything(x->x_glist, x->x_descend, s, av->a_w.w_symbol, ac - 1, av + 1); } if (av->a_type == A_POINTER) universal_dopointer(x->x_glist, x->x_descend, s, av->a_w.w_gpointer); } } static void universal_send(t_universal *x, t_symbol *s, int ac, t_atom *av) { if (ac && av->a_type == A_SYMBOL) universal_anything(x, av->a_w.w_symbol, ac - 1, av + 1); /* CHECKED: else ignored without complaints */ } static void *universal_new(t_floatarg f) { t_universal *x = (t_universal *)pd_new(universal_class); x->x_glist = canvas_getcurrent(); x->x_descend = ((int)f != 0); /* CHECKED */ return (x); } void universal_setup(void) { universal_class = class_new(gensym("universal"), (t_newmethod)universal_new, 0, sizeof(t_universal), 0, A_DEFFLOAT, 0); class_addanything(universal_class, universal_anything); /* CHECKED: 'send', not 'sendmessage' */ class_addmethod(universal_class, (t_method)universal_send, gensym("send"), A_GIMME, 0); } cyclone-0.1-alpha55/cyclone/hammer/acos.c0000644000076500007650000000224211466617445016735 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define acosf acos #endif typedef struct _acos { t_object x_ob; float x_value; } t_acos; static t_class *acos_class; static void acos_bang(t_acos *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_value); } static void acos_float(t_acos *x, t_float f) { if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ outlet_float(((t_object *)x)->ob_outlet, x->x_value = acosf(f)); } static void *acos_new(t_floatarg f) { t_acos *x = (t_acos *)pd_new(acos_class); if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ x->x_value = acosf(f); outlet_new((t_object *)x, &s_float); return (x); } void acos_setup(void) { acos_class = class_new(gensym("acos"), (t_newmethod)acos_new, 0, sizeof(t_acos), 0, A_DEFFLOAT, 0); class_addbang(acos_class, acos_bang); class_addfloat(acos_class, acos_float); } cyclone-0.1-alpha55/cyclone/hammer/pd-lib-notes.txt0000644000076500007650000000402511466617445020703 0ustar hanshansmodifications to Joseph A. Sarlo's code (formerly part of `pd-lib') ------------------------------------------------------------------- LATER: more testing, max-checking, resolving reentrancy, gc, etc. accum: only cosmetics bangbang: - if argument > 2 the array is dynamically allocated - if argument > 40 (max in max), a warning is printed - accepts any message Bucket: - arrays are dynamically allocated, no upper limit (max has no limit too) - outlets output in right-to-left order - added: 'set' method, 'l2r' and 'r2l' aliases buddy: coded from scratch - using array of proxy objects (accepting any message) - no upper limit for number of slots capture: coded from scratch - text editor, savepanel - any size - circular buffering counter (rewritten entirely): - using proxies to handle bangs and floats in other inlets than first - new `engine', counter_dobang(), coded from scratch - various adjustments of things that turned out to work differently in max, too many to list here (and probably more are required -- please let me know!) cycle: - the array of outlets is dynamically allocated - fixing cycle_list()'s bugs - accepting (and sending) both floats and symbols, accepting anything - 'thresh' and 'set' methods - event-sensitive mode emulation (a temporary hack) Decode (rewritten entirely): - if argument > 8 the array is dynamically allocated (with a warning) - all outlets deliver after any action - outlets output in right-to-left order - while in all-off mode, input is stored, not ignored - out-of-range input is clipped, not ignored Histo (rewritten entirely): - creation argument added (size) - the array is dynamically allocated, no upper limit (max has no limit too) - check if input is in range, to prevent crashes :) - 'bang' method iter: - different method of memory allocation - dripping both floats and symbols (max4 feature) - 'anything' method match: coded from scratch - matching stream of both floats and symbols (max4 feature) - scanning all kinds of messages, not only separate floats - recognizing overlapping patterns cyclone-0.1-alpha55/cyclone/hammer/mtr.c0000644000076500007650000005116411466617445016621 0ustar hanshans/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* CHECKME undocumented: readbinbuf, writebinbuf (a clipboard-like thing?) */ #include #include #include #include "m_pd.h" #include "shared.h" #include "common/loud.h" #include "common/fitter.h" #include "hammer/file.h" #ifdef KRZYSZCZ //#define MTR_DEBUG #endif #define MTR_C74MAXTRACKS 32 #define MTR_FILEBUFSIZE 4096 #define MTR_FILEMAXCOLUMNS 78 enum { MTR_STEPMODE, MTR_RECMODE, MTR_PLAYMODE }; typedef struct _mtrack { t_pd tr_pd; struct _mtr *tr_owner; int tr_id; int tr_listed; int tr_mode; int tr_muted; int tr_restarted; t_atom *tr_atdelta; int tr_ixnext; t_binbuf *tr_binbuf; float tr_tempo; double tr_clockdelay; double tr_prevtime; t_clock *tr_clock; t_outlet *tr_trackout; t_outlet *tr_mainout; t_hammerfile *tr_filehandle; } t_mtrack; typedef void (*t_mtrackfn)(t_mtrack *tp); typedef struct _mtr { t_object x_ob; t_glist *x_glist; int x_ntracks; t_mtrack **x_tracks; t_hammerfile *x_filehandle; } t_mtr; static t_class *mtrack_class; static t_class *mtr_class; static void mtrack_donext(t_mtrack *tp) { if (tp->tr_ixnext < 0) goto endoftrack; while (1) { int natoms = binbuf_getnatom(tp->tr_binbuf); int ixmess = tp->tr_ixnext; t_atom *atmess; if (ixmess >= natoms) goto endoftrack; atmess = binbuf_getvec(tp->tr_binbuf) + ixmess; while (atmess->a_type == A_SEMI) { if (++ixmess >= natoms) goto endoftrack; atmess++; } if (!tp->tr_atdelta && atmess->a_type == A_FLOAT) { /* delta atom */ float delta = atmess->a_w.w_float; if (delta < 0.) delta = 0.; tp->tr_atdelta = atmess; tp->tr_ixnext = ixmess + 1; if (tp->tr_mode == MTR_PLAYMODE) { clock_delay(tp->tr_clock, tp->tr_clockdelay = delta * tp->tr_tempo); tp->tr_prevtime = clock_getlogicaltime(); } else if (ixmess < 2) /* LATER rethink */ continue; /* CHECKED first delta skipped */ else { /* CHECKED this is not blocked with the muted flag */ t_atom at[2]; SETFLOAT(&at[0], tp->tr_id); SETFLOAT(&at[1], delta); outlet_list(tp->tr_mainout, 0, 2, at); } return; } else { /* message beginning */ int wasrestarted = tp->tr_restarted; /* LATER rethink */ int ixnext = ixmess + 1; t_atom *atnext = atmess + 1; while (ixnext < natoms && atnext->a_type != A_SEMI) ixnext++, atnext++; tp->tr_restarted = 0; if (!tp->tr_muted) { int ac = ixnext - ixmess; if (ac > 1) { if (atmess->a_type == A_FLOAT) outlet_list(tp->tr_trackout, &s_list, ac, atmess); else if (atmess->a_type == A_SYMBOL) outlet_anything(tp->tr_trackout, atmess->a_w.w_symbol, ac-1, atmess+1); } else if (atmess->a_type == A_FLOAT) outlet_float(tp->tr_trackout, atmess->a_w.w_float); else if (atmess->a_type == A_SYMBOL) outlet_symbol(tp->tr_trackout, atmess->a_w.w_symbol); } tp->tr_atdelta = 0; tp->tr_ixnext = ixnext; if (tp->tr_restarted) return; tp->tr_restarted = wasrestarted; } } endoftrack: if (tp->tr_mode == MTR_PLAYMODE) tp->tr_ixnext = 0; /* CHECKED ready to go in step mode after play */ else { if (tp->tr_ixnext > 0) { t_atom at[2]; SETFLOAT(&at[0], tp->tr_id); SETFLOAT(&at[1], -1.); /* CHECKED eot marker */ outlet_list(tp->tr_mainout, 0, 2, at); } tp->tr_ixnext = -1; /* CHECKED no loop-over */ } tp->tr_atdelta = 0; tp->tr_prevtime = 0.; tp->tr_mode = MTR_STEPMODE; } static void mtrack_tick(t_mtrack *tp) { if (tp->tr_mode == MTR_PLAYMODE) { tp->tr_prevtime = 0.; mtrack_donext(tp); } } static void mtrack_setmode(t_mtrack *tp, int newmode) { if (tp->tr_mode == MTR_PLAYMODE) { clock_unset(tp->tr_clock); tp->tr_ixnext = 0; } switch (tp->tr_mode = newmode) { case MTR_STEPMODE: break; case MTR_RECMODE: binbuf_clear(tp->tr_binbuf); tp->tr_prevtime = clock_getlogicaltime(); break; case MTR_PLAYMODE: tp->tr_atdelta = 0; tp->tr_ixnext = 0; tp->tr_prevtime = 0.; mtrack_donext(tp); break; default: loudbug_bug("mtrack_setmode"); } } static void mtrack_doadd(t_mtrack *tp, int ac, t_atom *av) { if (tp->tr_prevtime > 0.) { t_binbuf *bb = tp->tr_binbuf; t_atom at; float elapsed = clock_gettimesince(tp->tr_prevtime); SETFLOAT(&at, elapsed); binbuf_add(bb, 1, &at); binbuf_add(bb, ac, av); SETSEMI(&at); binbuf_add(bb, 1, &at); tp->tr_prevtime = clock_getlogicaltime(); } } static void mtrack_float(t_mtrack *tp, t_float f) { if (tp->tr_mode == MTR_RECMODE) { t_atom at; SETFLOAT(&at, f); mtrack_doadd(tp, 1, &at); } } static void mtrack_symbol(t_mtrack *tp, t_symbol *s) { if (tp->tr_mode == MTR_RECMODE) { t_atom at; SETSYMBOL(&at, s); mtrack_doadd(tp, 1, &at); } } static void mtrack_list(t_mtrack *tp, t_symbol *s, int ac, t_atom *av) { if (tp->tr_mode == MTR_RECMODE) mtrack_doadd(tp, ac, av); } static void mtrack_record(t_mtrack *tp) { mtrack_setmode(tp, MTR_RECMODE); } static void mtrack_play(t_mtrack *tp) { mtrack_setmode(tp, MTR_PLAYMODE); } static void mtrack_stop(t_mtrack *tp) { mtrack_setmode(tp, MTR_STEPMODE); } static void mtrack_next(t_mtrack *tp) { if (tp->tr_mode == MTR_STEPMODE) mtrack_donext(tp); } static void mtrack_rewind(t_mtrack *tp) { if (tp->tr_mode == MTR_STEPMODE) { tp->tr_atdelta = 0; tp->tr_ixnext = 0; } } /* CHECKED step and play mode */ static void mtrack_mute(t_mtrack *tp) { tp->tr_muted = 1; } /* CHECKED step and play mode */ static void mtrack_unmute(t_mtrack *tp) { tp->tr_muted = 0; } static void mtrack_clear(t_mtrack *tp) { binbuf_clear(tp->tr_binbuf); } static t_atom *mtrack_getdelay(t_mtrack *tp) { int natoms = binbuf_getnatom(tp->tr_binbuf); if (natoms) { t_atom *ap = binbuf_getvec(tp->tr_binbuf); while (natoms--) { if (ap->a_type == A_FLOAT) return (ap); ap++; } loudbug_bug("mtrack_getdelay"); } return (0); } static void mtrack_delay(t_mtrack *tp, t_floatarg f) { t_atom *ap = mtrack_getdelay(tp); if (ap) ap->a_w.w_float = f; } static void mtrack_first(t_mtrack *tp, t_floatarg f) { mtrack_delay(tp, f); /* CHECKED */ } static void mtr_doread(t_mtr *x, t_mtrack *target, t_symbol *fname); static void mtr_dowrite(t_mtr *x, t_mtrack *source, t_symbol *fname); static void mtrack_readhook(t_pd *z, t_symbol *fname, int ac, t_atom *av) { t_mtrack *tp = (t_mtrack *)z; mtr_doread(tp->tr_owner, tp, fname); } static void mtrack_writehook(t_pd *z, t_symbol *fname, int ac, t_atom *av) { t_mtrack *tp = (t_mtrack *)z; mtr_dowrite(tp->tr_owner, tp, fname); } static void mtrack_read(t_mtrack *tp, t_symbol *s) { if (s && s != &s_) mtr_doread(tp->tr_owner, tp, s); else /* CHECKED no default */ hammerpanel_open(tp->tr_filehandle, 0); } static void mtrack_write(t_mtrack *tp, t_symbol *s) { if (s && s != &s_) mtr_dowrite(tp->tr_owner, tp, s); else /* CHECKED no default */ hammerpanel_save(tp->tr_filehandle, canvas_getdir(tp->tr_owner->x_glist), 0); } static void mtrack_tempo(t_mtrack *tp, t_floatarg f) { float newtempo; static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(mtr_class, "no 'tempo' control in Max"); warned = 1; } if (f < 1e-20) f = 1e-20; else if (f > 1e20) f = 1e20; newtempo = 1. / f; if (tp->tr_prevtime > 0.) { tp->tr_clockdelay -= clock_gettimesince(tp->tr_prevtime); tp->tr_clockdelay *= newtempo / tp->tr_tempo; if (tp->tr_clockdelay < 0.) tp->tr_clockdelay = 0.; clock_delay(tp->tr_clock, tp->tr_clockdelay); tp->tr_prevtime = clock_getlogicaltime(); } tp->tr_tempo = newtempo; } static void mtr_calltracks(t_mtr *x, t_mtrackfn fn, t_symbol *s, int ac, t_atom *av) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; if (ac) { /* FIXME: CHECKED tracks called in the order of being mentioned (without duplicates) */ while (ntracks--) (*tpp++)->tr_listed = 0; while (ac--) { /* CHECKED silently ignoring out-of-bounds and non-ints */ if (av->a_type == A_FLOAT) { int id = (int)av->a_w.w_float - 1; /* CHECKED 1-based */ if (id >= 0 && id < x->x_ntracks) x->x_tracks[id]->tr_listed = 1; } av++; } ntracks = x->x_ntracks; tpp = x->x_tracks; while (ntracks--) { if ((*tpp)->tr_listed) fn(*tpp); tpp++; } } else while (ntracks--) fn(*tpp++); } static void mtr_record(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_record, s, ac, av); } static void mtr_play(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_play, s, ac, av); } static void mtr_stop(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_stop, s, ac, av); } static void mtr_next(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_next, s, ac, av); } static void mtr_rewind(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_rewind, s, ac, av); } static void mtr_mute(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_mute, s, ac, av); } static void mtr_unmute(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_unmute, s, ac, av); } static void mtr_clear(t_mtr *x, t_symbol *s, int ac, t_atom *av) { mtr_calltracks(x, mtrack_clear, s, ac, av); } static void mtr_delay(t_mtr *x, t_floatarg f) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; while (ntracks--) mtrack_delay(*tpp++, f); } static void mtr_first(t_mtr *x, t_floatarg f) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; float delta = SHARED_FLT_MAX; if (f < 0.) f = 0.; while (ntracks--) { t_atom *ap = mtrack_getdelay(*tpp); if (ap) { if (delta > ap->a_w.w_float) delta = ap->a_w.w_float; (*tpp)->tr_listed = 1; } else (*tpp)->tr_listed = 0; tpp++; } ntracks = x->x_ntracks; tpp = x->x_tracks; delta -= f; while (ntracks--) { if ((*tpp)->tr_listed) { t_atom *ap = mtrack_getdelay(*tpp); if (ap) ap->a_w.w_float -= delta; } tpp++; } } static void mtr_doread(t_mtr *x, t_mtrack *target, t_symbol *fname) { char path[MAXPDSTRING]; FILE *fp; /* FIXME use open_via_path() */ if (x->x_glist) canvas_makefilename(x->x_glist, fname->s_name, path, MAXPDSTRING); else { strncpy(path, fname->s_name, MAXPDSTRING); path[MAXPDSTRING-1] = 0; } /* CHECKED no global message */ sys_bashfilename(path, path); if (fp = fopen(path, "r")) { t_mtrack *tp = 0; char linebuf[MTR_FILEBUFSIZE]; t_binbuf *bb = binbuf_new(); while (fgets(linebuf, MTR_FILEBUFSIZE, fp)) { char *line = linebuf; int linelen; while (*line && (*line == ' ' || *line == '\t')) line++; if (linelen = strlen(line)) { if (tp) { if (!strncmp(line, "end;", 4)) { post("ok"); tp = 0; } else { int ac; binbuf_text(bb, line, linelen); if (ac = binbuf_getnatom(bb)) { t_atom *ap = binbuf_getvec(bb); if (!binbuf_getnatom(tp->tr_binbuf)) { if (ap->a_type != A_FLOAT) { t_atom at; SETFLOAT(&at, 0.); binbuf_add(tp->tr_binbuf, 1, &at); } else if (ap->a_w.w_float < 0.) ap->a_w.w_float = 0.; } binbuf_add(tp->tr_binbuf, ac, ap); } } } else if (!strncmp(line, "track ", 6)) { int id = strtol(line + 6, 0, 10); startpost("Track %d... ", id); if (id < 1 || id > x->x_ntracks) post("no such track"); /* LATER rethink */ else if (target) { if (id == target->tr_id) tp = target; post("skipped"); /* LATER rethink */ } else tp = x->x_tracks[id - 1]; if (tp) { binbuf_clear(tp->tr_binbuf); } } } } fclose(fp); binbuf_free(bb); } else { /* CHECKED no complaint, open dialog not presented... */ /* LATER rethink */ hammerpanel_open(target ? target->tr_filehandle : x->x_filehandle, 0); } } static int mtr_writetrack(t_mtr *x, t_mtrack *tp, FILE *fp) { int natoms = binbuf_getnatom(tp->tr_binbuf); if (natoms) /* CHECKED empty tracks not stored */ { char sbuf[MTR_FILEBUFSIZE], *bp = sbuf, *ep = sbuf + MTR_FILEBUFSIZE; int ncolumn = 0; t_atom *ap = binbuf_getvec(tp->tr_binbuf); fprintf(fp, "track %d;\n", tp->tr_id); for (; natoms--; ap++) { int length; /* from binbuf_write(): ``estimate how many characters will be needed. Printing out symbols may need extra characters for inserting backslashes.'' */ if (ap->a_type == A_SYMBOL || ap->a_type == A_DOLLSYM) length = 80 + strlen(ap->a_w.w_symbol->s_name); else length = 40; if (bp > sbuf && ep - bp < length) { if (fwrite(sbuf, bp - sbuf, 1, fp) < 1) return (1); bp = sbuf; } if (ap->a_type == A_SEMI) { *bp++ = ';'; *bp++ = '\n'; ncolumn = 0; } else if (ap->a_type == A_COMMA) { *bp++ = ','; ncolumn++; } else { if (ncolumn) { *bp++ = ' '; ncolumn++; } atom_string(ap, bp, (ep - bp) - 2); length = strlen(bp); if (ncolumn && ncolumn + length > MTR_FILEMAXCOLUMNS) { bp[-1] = '\n'; ncolumn = length; } else ncolumn += length; bp += length; } } if (bp > sbuf && fwrite(sbuf, bp - sbuf, 1, fp) < 1) return (1); fputs("end;\n", fp); post("Track %d done", tp->tr_id); /* CHECKED (0-based: not emulated) */ } return (0); } /* CHECKED empty sequence stored as an empty file */ static void mtr_dowrite(t_mtr *x, t_mtrack *source, t_symbol *fname) { int failed = 0; char path[MAXPDSTRING]; FILE *fp; if (x->x_glist) canvas_makefilename(x->x_glist, fname->s_name, path, MAXPDSTRING); else { strncpy(path, fname->s_name, MAXPDSTRING); path[MAXPDSTRING-1] = 0; } /* CHECKED no global message */ sys_bashfilename(path, path); if (fp = fopen(path, "w")) { /* CHECKED single-track writing does not seem to work (a bug?) */ if (source) failed = mtr_writetrack(x, source, fp); else { int id; t_mtrack **tpp; for (id = 0, tpp = x->x_tracks; id < x->x_ntracks; id++, tpp++) if (failed = mtr_writetrack(x, *tpp, fp)) break; } if (failed) sys_unixerror(path); /* LATER rethink */ fclose(fp); } else { sys_unixerror(path); /* LATER rethink */ failed = 1; } if (failed) loud_error((t_pd *)x, "writing text file \"%s\" failed", path); } static void mtr_readhook(t_pd *z, t_symbol *fname, int ac, t_atom *av) { mtr_doread((t_mtr *)z, 0, fname); } static void mtr_writehook(t_pd *z, t_symbol *fname, int ac, t_atom *av) { mtr_dowrite((t_mtr *)z, 0, fname); } static void mtr_read(t_mtr *x, t_symbol *s) { if (s && s != &s_) mtr_doread(x, 0, s); else /* CHECKED no default */ hammerpanel_open(x->x_filehandle, 0); } static void mtr_write(t_mtr *x, t_symbol *s) { if (s && s != &s_) mtr_dowrite(x, 0, s); else /* CHECKED no default */ hammerpanel_save(x->x_filehandle, canvas_getdir(x->x_glist), 0); } static void mtr_tempo(t_mtr *x, t_floatarg f) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; while (ntracks--) mtrack_tempo(*tpp++, f); } #ifdef MTR_DEBUG static void mtr_debug(t_mtr *x) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; while (ntracks--) { loudbug_post("------- Track %d -------", (*tpp)->tr_id); loudbug_postbinbuf((*tpp++)->tr_binbuf); } } #endif static void mtr_free(t_mtr *x) { if (x->x_tracks) { int ntracks = x->x_ntracks; t_mtrack **tpp = x->x_tracks; while (ntracks--) { t_mtrack *tp = *tpp++; if (tp->tr_binbuf) binbuf_free(tp->tr_binbuf); if (tp->tr_clock) clock_free(tp->tr_clock); pd_free((t_pd *)tp); } freebytes(x->x_tracks, x->x_ntracks * sizeof(*x->x_tracks)); } } static void *mtr_new(t_floatarg f) { t_mtr *x = 0; int ntracks = (int)f; t_mtrack **tracks; if (ntracks < 1) ntracks = 1; if (tracks = getbytes(ntracks * sizeof(*tracks))) { int i; t_mtrack **tpp; for (i = 0, tpp = tracks; i < ntracks; i++, tpp++) { if (!(*tpp = (t_mtrack *)pd_new(mtrack_class)) || !((*tpp)->tr_binbuf = binbuf_new()) || !((*tpp)->tr_clock = clock_new(*tpp, (t_method)mtrack_tick))) { if (*tpp) pd_free((t_pd *)*tpp); if ((*tpp)->tr_binbuf) binbuf_free((*tpp)->tr_binbuf); while (i--) { tpp--; binbuf_free((*tpp)->tr_binbuf); clock_free((*tpp)->tr_clock); pd_free((t_pd *)*tpp); } return (0); } } if (x = (t_mtr *)pd_new(mtr_class)) { int id; t_outlet *mainout = outlet_new((t_object *)x, &s_list); x->x_glist = canvas_getcurrent(); x->x_filehandle = hammerfile_new((t_pd *)x, 0, mtr_readhook, mtr_writehook, 0); if (ntracks > MTR_C74MAXTRACKS) fittermax_rangewarning(mtr_class, MTR_C74MAXTRACKS, "tracks"); x->x_ntracks = ntracks; x->x_tracks = tracks; for (id = 1; id <= ntracks; id++, tracks++) /* CHECKED 1-based */ { t_mtrack *tp = *tracks; inlet_new((t_object *)x, (t_pd *)tp, 0, 0); tp->tr_trackout = outlet_new((t_object *)x, &s_); tp->tr_mainout = mainout; tp->tr_owner = x; tp->tr_id = id; tp->tr_listed = 0; tp->tr_filehandle = /* LATER rethink */ hammerfile_new((t_pd *)tp, 0, mtrack_readhook, mtrack_writehook, 0); tp->tr_mode = MTR_STEPMODE; tp->tr_muted = 0; tp->tr_restarted = 0; tp->tr_atdelta = 0; tp->tr_ixnext = 0; tp->tr_tempo = 1.; tp->tr_clockdelay = 0.; tp->tr_prevtime = 0.; } } } return (x); } void mtr_setup(void) { mtrack_class = class_new(gensym("_mtrack"), 0, 0, sizeof(t_mtrack), CLASS_PD | CLASS_NOINLET, 0); class_addfloat(mtrack_class, mtrack_float); class_addsymbol(mtrack_class, mtrack_symbol); class_addlist(mtrack_class, mtrack_list); class_addmethod(mtrack_class, (t_method)mtrack_record, gensym("record"), 0); class_addmethod(mtrack_class, (t_method)mtrack_play, gensym("play"), 0); class_addmethod(mtrack_class, (t_method)mtrack_stop, gensym("stop"), 0); class_addmethod(mtrack_class, (t_method)mtrack_next, gensym("next"), 0); class_addmethod(mtrack_class, (t_method)mtrack_rewind, gensym("rewind"), 0); class_addmethod(mtrack_class, (t_method)mtrack_mute, gensym("mute"), 0); class_addmethod(mtrack_class, (t_method)mtrack_unmute, gensym("unmute"), 0); class_addmethod(mtrack_class, (t_method)mtrack_clear, gensym("clear"), 0); class_addmethod(mtrack_class, (t_method)mtrack_delay, gensym("delay"), A_FLOAT, 0); class_addmethod(mtrack_class, (t_method)mtrack_first, gensym("first"), A_FLOAT, 0); class_addmethod(mtrack_class, (t_method)mtrack_read, gensym("read"), A_DEFSYM, 0); class_addmethod(mtrack_class, (t_method)mtrack_write, gensym("write"), A_DEFSYM, 0); class_addmethod(mtrack_class, (t_method)mtrack_tempo, gensym("tempo"), A_FLOAT, 0); mtr_class = class_new(gensym("mtr"), (t_newmethod)mtr_new, (t_method)mtr_free, sizeof(t_mtr), 0, A_DEFFLOAT, 0); class_addmethod(mtr_class, (t_method)mtr_record, gensym("record"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_play, gensym("play"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_stop, gensym("stop"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_next, gensym("next"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_rewind, gensym("rewind"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_mute, gensym("mute"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_unmute, gensym("unmute"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_clear, gensym("clear"), A_GIMME, 0); class_addmethod(mtr_class, (t_method)mtr_delay, gensym("delay"), A_FLOAT, 0); class_addmethod(mtr_class, (t_method)mtr_first, gensym("first"), A_FLOAT, 0); class_addmethod(mtr_class, (t_method)mtr_read, gensym("read"), A_DEFSYM, 0); class_addmethod(mtr_class, (t_method)mtr_write, gensym("write"), A_DEFSYM, 0); class_addmethod(mtr_class, (t_method)mtr_tempo, gensym("tempo"), A_FLOAT, 0); #ifdef MTR_DEBUG class_addmethod(mtr_class, (t_method)mtr_debug, gensym("debug"), 0); #endif hammerfile_setup(mtr_class, 0); fitter_setup(mtr_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/spray.c0000644000076500007650000000504411466617445017151 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #define SPRAY_MINOUTS 1 /* CHECKED: no upper limit */ #define SPRAY_DEFOUTS 2 typedef struct _spray { t_object x_ob; int x_offset; int x_nouts; t_outlet **x_outs; } t_spray; static t_class *spray_class; static void spray_float(t_spray *x, t_float f) { /* CHECKED: floats ignored (LATER rethink), ints loudly rejected */ if (f == (int)f) loud_error((t_pd *)x, "requires list"); } /* LATER decide, whether float in first atom is to be truncated, or causing a list to be ignored as in max (CHECKED) */ static void spray_list(t_spray *x, t_symbol *s, int ac, t_atom *av) { int ndx; if (ac >= 2 && av->a_type == A_FLOAT /* CHECKED: lists with negative effective ndx are ignored */ && (ndx = (int)av->a_w.w_float - x->x_offset) >= 0 && ndx < x->x_nouts) { /* CHECKED: ignored atoms (symbols and floats) are counted */ /* CHECKED: we must spray in right-to-left order */ t_atom *argp; t_outlet **outp; int last = ac - 1 + ndx; /* ndx of last outlet filled (first is 1) */ if (last > x->x_nouts) { argp = av + 1 + x->x_nouts - ndx; outp = x->x_outs + x->x_nouts; } else { argp = av + ac; outp = x->x_outs + last; } /* argp/outp now point to one after the first atom/outlet to deliver */ for (argp--, outp--; argp > av; argp--, outp--) if (argp->a_type == A_FLOAT) outlet_float(*outp, argp->a_w.w_float); } } static void spray_free(t_spray *x) { if (x->x_outs) freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); } static void *spray_new(t_floatarg f1, t_floatarg f2) { t_spray *x; int i, nouts = (int)f1; t_outlet **outs; if (nouts < SPRAY_MINOUTS) nouts = SPRAY_DEFOUTS; if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) return (0); x = (t_spray *)pd_new(spray_class); x->x_nouts = nouts; x->x_outs = outs; x->x_offset = (int)f2; for (i = 0; i < nouts; i++) x->x_outs[i] = outlet_new((t_object *)x, &s_float); return (x); } void spray_setup(void) { spray_class = class_new(gensym("spray"), (t_newmethod)spray_new, (t_method)spray_free, sizeof(t_spray), 0, A_DEFFLOAT, A_DEFFLOAT, 0); /* CHECKED: bang, symbol, anything -- ``doesn't understand'' */ class_addfloat(spray_class, spray_float); class_addlist(spray_class, spray_list); } cyclone-0.1-alpha55/cyclone/hammer/allhammers.c0000644000076500007650000000723211466617445020141 0ustar hanshans// Do not edit this file, run "make" instead. /* Copyright (c) 2002-2004 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ void Append_setup(void); void Borax_setup(void); void Bucket_setup(void); void Clip_setup(void); void Decode_setup(void); void Histo_setup(void); void MouseState_setup(void); void Peak_setup(void); void Table_setup(void); void TogEdge_setup(void); void Trough_setup(void); void Uzi_setup(void); void accum_setup(void); void acos_setup(void); void active_setup(void); void anal_setup(void); void asin_setup(void); void bangbang_setup(void); void bondo_setup(void); void buddy_setup(void); void capture_setup(void); void cartopol_setup(void); void coll_setup(void); void comment_setup(void); void cosh_setup(void); void counter_setup(void); void cycle_setup(void); void decide_setup(void); void drunk_setup(void); void flush_setup(void); void forward_setup(void); void fromsymbol_setup(void); void funbuff_setup(void); void funnel_setup(void); void gate_setup(void); void grab_setup(void); void iter_setup(void); void match_setup(void); void maximum_setup(void); void mean_setup(void); void midiflush_setup(void); void midiformat_setup(void); void midiparse_setup(void); void minimum_setup(void); void mousefilter_setup(void); void mtr_setup(void); void next_setup(void); void offer_setup(void); void onebang_setup(void); void past_setup(void); void poltocar_setup(void); void prepend_setup(void); void prob_setup(void); void pv_setup(void); void seq_setup(void); void sinh_setup(void); void speedlim_setup(void); void spell_setup(void); void split_setup(void); void spray_setup(void); void sprintf_setup(void); void substitute_setup(void); void sustain_setup(void); void switch_setup(void); void tanh_setup(void); void testmess_setup(void); void thresh_setup(void); void tosymbol_setup(void); void universal_setup(void); void urn_setup(void); void xbendin_setup(void); void xbendin2_setup(void); void xbendout_setup(void); void xbendout2_setup(void); void xnotein_setup(void); void xnoteout_setup(void); void zl_setup(void); void allhammers_setup(void) { Append_setup(); Borax_setup(); Bucket_setup(); Clip_setup(); Decode_setup(); Histo_setup(); MouseState_setup(); Peak_setup(); Table_setup(); TogEdge_setup(); Trough_setup(); Uzi_setup(); accum_setup(); acos_setup(); active_setup(); anal_setup(); asin_setup(); bangbang_setup(); bondo_setup(); buddy_setup(); capture_setup(); cartopol_setup(); coll_setup(); comment_setup(); cosh_setup(); counter_setup(); cycle_setup(); decide_setup(); drunk_setup(); flush_setup(); forward_setup(); fromsymbol_setup(); funbuff_setup(); funnel_setup(); gate_setup(); grab_setup(); iter_setup(); match_setup(); maximum_setup(); mean_setup(); midiflush_setup(); midiformat_setup(); midiparse_setup(); minimum_setup(); mousefilter_setup(); mtr_setup(); next_setup(); offer_setup(); onebang_setup(); past_setup(); poltocar_setup(); prepend_setup(); prob_setup(); pv_setup(); seq_setup(); sinh_setup(); speedlim_setup(); spell_setup(); split_setup(); spray_setup(); sprintf_setup(); substitute_setup(); sustain_setup(); switch_setup(); tanh_setup(); testmess_setup(); thresh_setup(); tosymbol_setup(); universal_setup(); urn_setup(); xbendin_setup(); xbendin2_setup(); xbendout_setup(); xbendout2_setup(); xnotein_setup(); xnoteout_setup(); zl_setup(); } cyclone-0.1-alpha55/cyclone/hammer/gate.c0000644000076500007650000001017211466617445016731 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" #include "common/loud.h" #include "common/fitter.h" #define GATE_MINOUTS 1 #define GATE_C74MAXOUTS 100 #define GATE_DEFOUTS 1 typedef struct _gate { t_object x_ob; int x_open; t_pd *x_proxy; int x_nouts; /* requested + 1 (as allocated) */ t_outlet **x_outs; } t_gate; typedef struct _gate_proxy { t_object p_ob; t_gate *p_master; } t_gate_proxy; static t_class *gate_class; static t_class *gate_proxy_class; static void gate_proxy_bang(t_gate_proxy *x) { t_gate *master = x->p_master; if (master->x_open) outlet_bang(master->x_outs[master->x_open]); } static void gate_proxy_float(t_gate_proxy *x, t_float f) { t_gate *master = x->p_master; if (master->x_open) outlet_float(master->x_outs[master->x_open], f); } static void gate_proxy_symbol(t_gate_proxy *x, t_symbol *s) { t_gate *master = x->p_master; if (master->x_open) outlet_symbol(master->x_outs[master->x_open], s); } static void gate_proxy_pointer(t_gate_proxy *x, t_gpointer *gp) { t_gate *master = x->p_master; if (master->x_open) outlet_pointer(master->x_outs[master->x_open], gp); } static void gate_proxy_list(t_gate_proxy *x, t_symbol *s, int ac, t_atom *av) { t_gate *master = x->p_master; if (master->x_open) outlet_list(master->x_outs[master->x_open], s, ac, av); } static void gate_proxy_anything(t_gate_proxy *x, t_symbol *s, int ac, t_atom *av) { t_gate *master = x->p_master; if (master->x_open) outlet_anything(master->x_outs[master->x_open], s, ac, av); } static void gate_float(t_gate *x, t_float f) { int i = (int)f; if (i < 0) i = 1; if (i >= x->x_nouts) i = x->x_nouts - 1; x->x_open = i; } static void gate_bang(t_gate *x) { outlet_float(x->x_outs[1], x->x_open); } static void gate_free(t_gate *x) { if (x->x_proxy) pd_free(x->x_proxy); if (x->x_outs) freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); } static void *gate_new(t_floatarg f1, t_floatarg f2) { t_gate *x; int i, nouts = (int)f1; t_outlet **outs; t_pd *proxy; if (nouts < GATE_MINOUTS) nouts = GATE_DEFOUTS; if (nouts > GATE_C74MAXOUTS) fittermax_rangewarning(gate_class, GATE_C74MAXOUTS, "outlets"); nouts++; /* for convenience (the cost is one pointer) */ if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) return (0); if (!(proxy = pd_new(gate_proxy_class))) { freebytes(outs, nouts * sizeof(*outs)); return (0); } x = (t_gate *)pd_new(gate_class); x->x_nouts = nouts; x->x_outs = outs; x->x_proxy = proxy; ((t_gate_proxy *)proxy)->p_master = x; /* from max sdk manual: ``The dst parameter can be changed (or set to 0) dynamically with the inlet_to function... The gate object uses this technique to assign its inlet to one of several outlets, or no outlet at all.'' We have to use a proxy, because Pd's outlet is not a t_pd (besides, Pd does not handle inlets with null destination). */ inlet_new((t_object *)x, proxy, 0, 0); for (i = 1; i < nouts; i++) x->x_outs[i] = outlet_new((t_object *)x, &s_anything); gate_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */ return (x); } void gate_setup(void) { gate_class = class_new(gensym("gate"), (t_newmethod)gate_new, (t_method)gate_free, sizeof(t_gate), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addfloat(gate_class, gate_float); class_addbang(gate_class, gate_bang); gate_proxy_class = class_new(gensym("_gate_proxy"), 0, 0, sizeof(t_gate_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addfloat(gate_proxy_class, gate_proxy_float); class_addbang(gate_proxy_class, gate_proxy_bang); class_addsymbol(gate_proxy_class, gate_proxy_symbol); class_addpointer(gate_proxy_class, gate_proxy_pointer); class_addlist(gate_proxy_class, gate_proxy_list); class_addanything(gate_proxy_class, gate_proxy_anything); fitter_setup(gate_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/urn.c0000644000076500007650000001026511466617445016620 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER think again about avoiding memory allocation overhead in run-time. One would need to use a creation argument greater than any future right inlet value. But this is incompatible (max uses a `static', max-size array), and should be put somewhere in the docs... */ #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" #include "common/fitter.h" #include "common/rand.h" #define URN_INISIZE 128 /* LATER rethink */ #define URN_C74MAXSIZE 4096 /* CHECKED */ #define URN_MAXSIZE 65536 /* LATER use USHRT_MAX */ typedef struct _urn { t_object x_ob; int x_count; int x_size; /* as allocated (in bytes) */ int x_range; /* as used */ unsigned short *x_urn; unsigned short x_urnini[URN_INISIZE]; unsigned int x_seed; t_outlet *x_bangout; } t_urn; static t_class *urn_class; static int urn_resize(t_urn *x, t_float f, int init) { int maxmax = URN_C74MAXSIZE; int range = (int)f; /* CHECKED silent truncation */ if (init) { maxmax--; /* CHECKED: max 4095 here (a bug, sort of) */ /* CHECKED in the constructor this is silent (also > maxmax clipped without complaining) */ if (range < 1) range = 1; } else if (range < 1) { /* CHECKED (the same for > maxmax) */ loud_error((t_pd *)x, "illegal size %d", f); return (0); } if (range > URN_MAXSIZE) { loud_warning((t_pd *)x, 0, "requested size (%d) clipped -- effective size is %d", range, URN_MAXSIZE); range = URN_MAXSIZE; } if (range > maxmax) fittermax_rangewarning(urn_class, maxmax, "elements"); x->x_range = range; if (range > x->x_size) x->x_urn = grow_nodata(&x->x_range, &x->x_size, x->x_urn, URN_INISIZE, x->x_urnini, sizeof(*x->x_urn)); return (1); } static void urn_bang(t_urn *x) { if (x->x_count) { int ndx = rand_int(&x->x_seed, x->x_count); unsigned short pick = x->x_urn[ndx]; x->x_urn[ndx] = x->x_urn[--x->x_count]; outlet_float(((t_object *)x)->ob_outlet, pick); } /* CHECKED: start banging when the first bang is input into an empty urn (and not when the last value is output). CHECKED: keep banging until cleared. */ else outlet_bang(x->x_bangout); } static void urn_clear(t_urn *x) { int i; x->x_count = x->x_range; for (i = 0; i < x->x_count; i++) x->x_urn[i] = i; } static void urn_float(t_urn *x, t_float f) { /* CHECKED: float loudly rejected, int (any value) same as bang */ int i; if (loud_checkint((t_pd *)x, f, &i, &s_float)) urn_bang(x); } static void urn_ft1(t_urn *x, t_floatarg f) { if (urn_resize(x, f, 0)) /* CHECKED cleared only if a legal resize */ urn_clear(x); } static void urn_seed(t_urn *x, t_floatarg f) { int i = (int)f; /* CHECKED */ if (i < 0) i = 1; /* CHECKED */ rand_seed(&x->x_seed, (unsigned int)i); } static void urn_free(t_urn *x) { if (x->x_urn != x->x_urnini) freebytes(x->x_urn, x->x_size * sizeof(*x->x_urn)); } static void *urn_new(t_floatarg f1, t_floatarg f2) { t_urn *x = (t_urn *)pd_new(urn_class); x->x_size = URN_INISIZE; x->x_urn = x->x_urnini; urn_resize(x, f1, 1); urn_seed(x, f2); /* CHECKME */ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_float); x->x_bangout = outlet_new((t_object *)x, &s_bang); urn_clear(x); return (x); } void urn_setup(void) { urn_class = class_new(gensym("urn"), (t_newmethod)urn_new, (t_method)urn_free, sizeof(t_urn), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(urn_class, urn_bang); class_addfloat(urn_class, urn_float); class_addmethod(urn_class, (t_method)urn_ft1, gensym("ft1"), A_FLOAT, 0); /* CHECKED list is auto-unfolded */ class_addmethod(urn_class, (t_method)urn_seed, gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */ class_addmethod(urn_class, (t_method)urn_clear, gensym("clear"), 0); fitter_setup(urn_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/flush.c0000644000076500007650000000351711466617445017137 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #define FLUSH_NPITCHES 128 typedef struct _flush { t_object x_ob; t_float x_velocity; unsigned char x_pitches[FLUSH_NPITCHES]; /* CHECKED */ t_outlet *x_voutlet; } t_flush; static t_class *flush_class; static void flush_float(t_flush *x, t_float f) { int pitch = (int)f; if (pitch >= 0 && pitch < FLUSH_NPITCHES) { outlet_float(x->x_voutlet, x->x_velocity); outlet_float(((t_object *)x)->ob_outlet, pitch); if (x->x_velocity != 0) { x->x_pitches[pitch]++; /* CHECKED (lame) */ } else if (x->x_pitches[pitch]) { x->x_pitches[pitch]--; /* CHECKED (lame) */ } } } static void flush_bang(t_flush *x) { int i; unsigned char *pp; for (i = 0, pp = x->x_pitches; i < FLUSH_NPITCHES; i++, pp++) { while (*pp) { outlet_float(x->x_voutlet, 0); outlet_float(((t_object *)x)->ob_outlet, i); (*pp)--; } } } static void flush_clear(t_flush *x) { memset(x->x_pitches, 0, sizeof(x->x_pitches)); } static void *flush_new(void) { t_flush *x = (t_flush *)pd_new(flush_class); x->x_velocity = 0; flush_clear(x); floatinlet_new((t_object *)x, &x->x_velocity); outlet_new((t_object *)x, &s_float); x->x_voutlet = outlet_new((t_object *)x, &s_float); return (x); } void flush_setup(void) { flush_class = class_new(gensym("flush"), (t_newmethod)flush_new, 0, /* CHECKED: no flushout */ sizeof(t_flush), 0, 0); class_addfloat(flush_class, flush_float); class_addbang(flush_class, flush_bang); class_addmethod(flush_class, (t_method)flush_clear, gensym("clear"), 0); } cyclone-0.1-alpha55/cyclone/hammer/speedlim.c0000644000076500007650000001125211466617445017613 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* LATER 'clock' method */ #include #include "m_pd.h" #include "common/grow.h" #define SPEEDLIM_INISIZE 32 /* LATER rethink */ #define SPEEDLIM_MAXSIZE 256 /* not used */ typedef struct _speedlim { t_object x_ob; int x_open; t_float x_delta; t_symbol *x_selector; t_float x_float; t_symbol *x_symbol; t_gpointer *x_pointer; int x_size; /* as allocated */ int x_natoms; /* as used */ t_atom *x_message; t_atom x_messini[SPEEDLIM_INISIZE]; int x_entered; t_clock *x_clock; } t_speedlim; static t_class *speedlim_class; static void speedlim_dooutput(t_speedlim *x, t_symbol *s, int ac, t_atom *av) { x->x_open = 0; /* so there will be no reentrant calls of dooutput */ x->x_entered = 1; /* this prevents a message from being overridden */ clock_unset(x->x_clock); if (s == &s_bang) outlet_bang(((t_object *)x)->ob_outlet); else if (s == &s_float) outlet_float(((t_object *)x)->ob_outlet, x->x_float); else if (s == &s_symbol && x->x_symbol) { /* if x_symbol is null, then symbol &s_ is passed by outlet_anything() -> typedmess() */ outlet_symbol(((t_object *)x)->ob_outlet, x->x_symbol); x->x_symbol = 0; } else if (s == &s_pointer && x->x_pointer) { /* LATER */ x->x_pointer = 0; } else if (s == &s_list) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else if (s) outlet_anything(((t_object *)x)->ob_outlet, s, ac, av); x->x_selector = 0; x->x_natoms = 0; if (x->x_delta > 0) clock_delay(x->x_clock, x->x_delta); else x->x_open = 1; x->x_entered = 0; } static void speedlim_tick(t_speedlim *x) { if (x->x_selector) speedlim_dooutput(x, x->x_selector, x->x_natoms, x->x_message); else x->x_open = 1; } static void speedlim_anything(t_speedlim *x, t_symbol *s, int ac, t_atom *av) { if (x->x_open) speedlim_dooutput(x, s, ac, av); else if (s && s != &s_ && !x->x_entered) { if (ac > x->x_size) /* MAXSIZE not used, not even a warning... LATER consider clipping */ x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, SPEEDLIM_INISIZE, x->x_messini, sizeof(*x->x_message)); x->x_selector = s; x->x_natoms = ac; if (ac) memcpy(x->x_message, av, ac * sizeof(*x->x_message)); } } static void speedlim_bang(t_speedlim *x) { x->x_selector = &s_bang; speedlim_anything(x, x->x_selector, 0, 0); } static void speedlim_float(t_speedlim *x, t_float f) { x->x_selector = &s_float; x->x_float = f; speedlim_anything(x, x->x_selector, 0, 0); } static void speedlim_symbol(t_speedlim *x, t_symbol *s) { x->x_selector = &s_symbol; x->x_symbol = s; speedlim_anything(x, x->x_selector, 0, 0); } /* LATER gpointer */ static void speedlim_list(t_speedlim *x, t_symbol *s, int ac, t_atom *av) { x->x_selector = &s_list; speedlim_anything(x, x->x_selector, ac, av); } static void speedlim_ft1(t_speedlim *x, t_floatarg f) { if (f < 0) f = 0; /* redundant (and CHECKED) */ x->x_delta = f; /* CHECKED: no rearming -- if clock is set, then new delta value is not used until next tick */ } static void speedlim_free(t_speedlim *x) { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); if (x->x_clock) clock_free(x->x_clock); } static void *speedlim_new(t_floatarg f) { t_speedlim *x = (t_speedlim *)pd_new(speedlim_class); x->x_open = 1; /* CHECKED */ x->x_delta = 0; x->x_selector = 0; x->x_float = 0; x->x_symbol = 0; x->x_pointer = 0; x->x_size = SPEEDLIM_INISIZE; x->x_natoms = 0; x->x_message = x->x_messini; x->x_entered = 0; inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); outlet_new((t_object *)x, &s_anything); x->x_clock = clock_new(x, (t_method)speedlim_tick); speedlim_ft1(x, f); return (x); } void speedlim_setup(void) { speedlim_class = class_new(gensym("speedlim"), (t_newmethod)speedlim_new, (t_method)speedlim_free, sizeof(t_speedlim), 0, A_DEFFLOAT, 0); class_addbang(speedlim_class, speedlim_bang); class_addfloat(speedlim_class, speedlim_float); class_addsymbol(speedlim_class, speedlim_symbol); class_addlist(speedlim_class, speedlim_list); class_addanything(speedlim_class, speedlim_anything); class_addmethod(speedlim_class, (t_method)speedlim_ft1, gensym("ft1"), A_FLOAT, 0); } cyclone-0.1-alpha55/cyclone/hammer/drunk.c0000644000076500007650000001033011466617445017130 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* The first version of this code was written by Nicola Bernardini. It was entirely reimplemented in the hope of adapting it to the cyclone's guidelines. */ #include "m_pd.h" #include "common/rand.h" #define DRUNK_DEFMAXVALUE 128 #define DRUNK_DEFMAXSTEP 2 typedef struct _drunk { t_object x_ob; int x_value; int x_maxvalue; int x_maxstep; int x_minstep; unsigned int x_seed; unsigned int x_bitseed; } t_drunk; static t_class *drunk_class; static void drunk_set(t_drunk *x, t_floatarg f) { int i = (int)f; /* CHECKED float silently truncated */ if (i > x->x_maxvalue) x->x_value = x->x_maxvalue; /* CHECKED */ else if (i < 0) x->x_value = 0; /* CHECKED */ else x->x_value = i; } /* CHECKED: this is a superposition of two rngs -- the random bit generator, and the random integer generator, which is the same (CHECKED) as the one used in the 'random' class (quite lame: period 35730773, nonuniform for large ranges, so I would rather not RE it...) */ #define RBIT1 1 #define RBIT2 2 #define RBIT5 16 #define RBIT18 131072 #define RBIT_MASK (RBIT1 + RBIT2 + RBIT5) static void drunk_bang(t_drunk *x) { int rnd = rand_int(&x->x_seed, x->x_maxstep) + x->x_minstep; int val; if (x->x_bitseed & RBIT18) { x->x_bitseed = ((x->x_bitseed ^ RBIT_MASK) << 1) | RBIT1; if ((val = x->x_value + rnd) > x->x_maxvalue) val = x->x_value - rnd; /* CHECKED */ if (val < 0) val = 0; /* CHECKED (needed for maxstep > maxvalue) */ } else { x->x_bitseed <<= 1; if ((val = x->x_value - rnd) < 0) val = x->x_value + rnd; /* CHECKED */ if (val > x->x_maxvalue) val = x->x_maxvalue; /* CHECKED (needed for maxstep > maxvalue) */ } outlet_float(((t_object *)x)->ob_outlet, x->x_value = val); } static void drunk_float(t_drunk *x, t_float f) { drunk_set(x, f); outlet_float(((t_object *)x)->ob_outlet, x->x_value); } static void drunk_ft1(t_drunk *x, t_floatarg f) { int i = (int)f; /* CHECKED float silently truncated */ x->x_maxvalue = (i < 0 ? 1 : i); /* CHECKED zero allowed */ /* CHECKED maxstep not updated */ } static void drunk_ft2(t_drunk *x, t_floatarg f) { int i = (int)f; /* CHECKED float silently truncated */ if (i < 0) { x->x_minstep = 1; i = -i; } else x->x_minstep = 0; /* CHECKED maxstep not clipped to the maxvalue */ x->x_maxstep = (x->x_minstep ? i - 1 : i); /* CHECKED zero allowed */ } /* apparently, bitseed cannot be controlled, but LATER recheck */ static void drunk_seed(t_drunk *x, t_floatarg f) { int i = (int)f; /* CHECKED */ if (i < 0) i = 1; /* CHECKED */ rand_seed(&x->x_seed, (unsigned int)i); } static void *drunk_new(t_floatarg f1, t_floatarg f2) { t_drunk *x = (t_drunk *)pd_new(drunk_class); x->x_maxvalue = ((int)f1 > 0 ? (int)f1 : 128); /* CHECKED */ x->x_maxstep = 2; x->x_minstep = 0; if ((int)f2) /* CHECKED */ drunk_ft2(x, f2); x->x_value = x->x_maxvalue / 2; /* CHECKED */ rand_seed(&x->x_seed, 0); /* CHECKED third arg silently ignored */ x->x_bitseed = 123456789; /* FIXME */ inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); outlet_new((t_object *)x, &s_float); return (x); } void drunk_setup(void) { drunk_class = class_new(gensym("drunk"), (t_newmethod)drunk_new, 0, sizeof(t_drunk), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(drunk_class, drunk_bang); class_addfloat(drunk_class, drunk_float); class_addmethod(drunk_class, (t_method)drunk_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(drunk_class, (t_method)drunk_ft2, gensym("ft2"), A_FLOAT, 0); /* CHECKED list is auto-unfolded */ class_addmethod(drunk_class, (t_method)drunk_seed, gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */ class_addmethod(drunk_class, (t_method)drunk_set, gensym("set"), A_FLOAT, 0); /* CHECKED arg obligatory */ } cyclone-0.1-alpha55/cyclone/hammer/Clip.c0000644000076500007650000000705611466617445016707 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/grow.h" #define CLIP_INISIZE 32 /* LATER rethink */ #define CLIP_MAXSIZE 256 typedef struct _clip { t_object x_ob; float x_f1; float x_f2; int x_size; /* as allocated */ t_atom *x_message; t_atom x_messini[CLIP_INISIZE]; int x_entered; } t_clip; static t_class *clip_class; /* CHECKED case of f1 > f2: x <= f2 => f1, x > f2 => f2 (Pd implementation of clip has it the other way around) */ static void clip_float(t_clip *x, t_float f) { outlet_float(((t_object *)x)->ob_outlet, (f > x->x_f2 ? x->x_f2 : (f < x->x_f1 ? x->x_f1 : f))); } static void clip_list(t_clip *x, t_symbol *s, int ac, t_atom *av) { if (ac) { int docopy = 0; int i; t_atom *ap; t_float f1 = x->x_f1; t_float f2 = x->x_f2; for (i = 0, ap = av; i < ac; i++, ap++) { t_float f; if (ap->a_type == A_FLOAT) f = ap->a_w.w_float; else { docopy = 1; /* CHECKED: symbols inside lists are converted to zeros */ f = 0; } if (f < f1 || f > f2) docopy = 1; } if (docopy) { t_atom *buf; t_atom *bp; int reentered = x->x_entered; int prealloc = !reentered; x->x_entered = 1; if (prealloc && ac > x->x_size) { if (ac > CLIP_MAXSIZE) prealloc = 0; else x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, CLIP_INISIZE, x->x_messini, sizeof(*x->x_message)); } if (prealloc) buf = x->x_message; else /* LATER consider using the stack if ntotal <= MAXSTACK */ buf = getbytes(ac * sizeof(*buf)); if (buf) { for (i = 0, ap = av, bp = buf; i < ac; i++, ap++, bp++) { t_float f = (ap->a_type == A_FLOAT ? ap->a_w.w_float : 0); if (f < f1) f = f1; else if (f > f2) f = f2; SETFLOAT(bp, f); } outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, buf); if (buf != x->x_message) freebytes(buf, ac * sizeof(*buf)); } if (!reentered) { x->x_entered = 0; } } else outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); } } static void clip_set(t_clip *x, t_symbol *s, int ac, t_atom *av) { x->x_f1 = 0; x->x_f2 = 0; if (ac) /* CHECKED: 'set' without arguments sets both values to 0 */ { if (av->a_type == A_FLOAT) /* CHECKED: symbol is converted to 0 */ x->x_f1 = av->a_w.w_float; av++; if (--ac) { if (av->a_type == A_FLOAT) x->x_f2 = av->a_w.w_float; } else x->x_f2 = x->x_f1; /* CHECKED */ } } static void clip_free(t_clip *x) { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); } static void *clip_new(t_symbol *s, int ac, t_atom *av) { t_clip *x = (t_clip *)pd_new(clip_class); x->x_f1 = 0; x->x_f2 = 0; x->x_size = CLIP_INISIZE; x->x_message = x->x_messini; x->x_entered = 0; floatinlet_new((t_object *)x, &x->x_f1); floatinlet_new((t_object *)x, &x->x_f2); outlet_new(&x->x_ob, &s_anything); clip_set(x, 0, ac, av); return (x); } void Clip_setup(void) { clip_class = class_new(gensym("Clip"), (t_newmethod)clip_new, (t_method)clip_free, sizeof(t_clip), 0, A_GIMME, 0); class_addfloat(clip_class, clip_float); class_addlist(clip_class, clip_list); class_addmethod(clip_class, (t_method)clip_set, gensym("set"), A_GIMME, 0); } cyclone-0.1-alpha55/cyclone/hammer/tanh.c0000644000076500007650000000212411466617445016741 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define tanhf tanh #endif typedef struct _tanh { t_object x_ob; float x_value; } t_tanh; static t_class *tanh_class; static void tanh_bang(t_tanh *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_value); } static void tanh_float(t_tanh *x, t_float f) { /* CHECKME large values */ outlet_float(((t_object *)x)->ob_outlet, x->x_value = tanhf(f)); } static void *tanh_new(t_floatarg f) { t_tanh *x = (t_tanh *)pd_new(tanh_class); /* CHECKME large values */ x->x_value = tanhf(f); outlet_new((t_object *)x, &s_float); return (x); } void tanh_setup(void) { tanh_class = class_new(gensym("tanh"), (t_newmethod)tanh_new, 0, sizeof(t_tanh), 0, A_DEFFLOAT, 0); class_addbang(tanh_class, tanh_bang); class_addfloat(tanh_class, tanh_float); } cyclone-0.1-alpha55/cyclone/hammer/midiformat.c0000644000076500007650000000726011466617445020150 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _midiformat { t_object x_ob; t_float x_channel; } t_midiformat; static t_class *midiformat_class; static int midiformat_channel(t_midiformat *x) { int ch = (int)x->x_channel; return (ch > 0 ? (ch - 1) & 0x0F : 0); } static void midiformat_note(t_midiformat *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) { int pitch = (int)av[0].a_w.w_float; /* CHECKED: anything goes */ int velocity = (int)av[1].a_w.w_float; outlet_float(((t_object *)x)->ob_outlet, 0x90 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, pitch); outlet_float(((t_object *)x)->ob_outlet, velocity); } } static void midiformat_polytouch(t_midiformat *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) { int touch = (int)av[0].a_w.w_float; int key = (int)av[1].a_w.w_float; outlet_float(((t_object *)x)->ob_outlet, 0xA0 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, key); outlet_float(((t_object *)x)->ob_outlet, touch); } } static void midiformat_controller(t_midiformat *x, t_symbol *s, int ac, t_atom *av) { if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) { int val = (int)av[0].a_w.w_float; int ctl = (int)av[1].a_w.w_float; outlet_float(((t_object *)x)->ob_outlet, 0xB0 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, ctl); outlet_float(((t_object *)x)->ob_outlet, val); } } static void midiformat_program(t_midiformat *x, t_floatarg f) { int pgm = (int)f; outlet_float(((t_object *)x)->ob_outlet, 0xC0 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, pgm); } static void midiformat_touch(t_midiformat *x, t_floatarg f) { int touch = (int)f; outlet_float(((t_object *)x)->ob_outlet, 0xD0 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, touch); } static void midiformat_bend(t_midiformat *x, t_floatarg f) { int val = (int)f; outlet_float(((t_object *)x)->ob_outlet, 0xE0 | midiformat_channel(x)); outlet_float(((t_object *)x)->ob_outlet, 0); outlet_float(((t_object *)x)->ob_outlet, val); } static void *midiformat_new(t_floatarg f) { t_midiformat *x = (t_midiformat *)pd_new(midiformat_class); x->x_channel = f; inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst1")); inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst2")); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft3")); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft4")); inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft5")); floatinlet_new((t_object *)x, &x->x_channel); outlet_new((t_object *)x, &s_float); return (x); } void midiformat_setup(void) { midiformat_class = class_new(gensym("midiformat"), (t_newmethod)midiformat_new, 0, sizeof(t_midiformat), 0, A_DEFFLOAT, 0); class_addlist(midiformat_class, midiformat_note); class_addmethod(midiformat_class, (t_method)midiformat_polytouch, gensym("lst1"), A_GIMME, 0); class_addmethod(midiformat_class, (t_method)midiformat_controller, gensym("lst2"), A_GIMME, 0); class_addmethod(midiformat_class, (t_method)midiformat_program, gensym("ft3"), A_FLOAT, 0); class_addmethod(midiformat_class, (t_method)midiformat_touch, gensym("ft4"), A_FLOAT, 0); class_addmethod(midiformat_class, (t_method)midiformat_bend, gensym("ft5"), A_FLOAT, 0); } cyclone-0.1-alpha55/cyclone/hammer/fromsymbol.c0000644000076500007650000000435711466617445020212 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" typedef struct _fromsymbol { t_object x_ob; } t_fromsymbol; static t_class *fromsymbol_class; static void fromsymbol_bang(t_fromsymbol *x) { outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */ } static void fromsymbol_float(t_fromsymbol *x, t_float f) { /* CHECKED: fromsymbol: doesn't understand "int", "float" */ } static void fromsymbol_symbol(t_fromsymbol *x, t_symbol *s) { static char zero = 0; char *sname = &zero; if (s) { sname = s->s_name; while (*sname == ' ' || *sname == '\t' || *sname == '\n' || *sname == '\r') sname++; } if (*sname) { t_binbuf *bb = binbuf_new(); int ac; t_atom *av; binbuf_text(bb, sname, strlen(sname)); ac = binbuf_getnatom(bb); av = binbuf_getvec(bb); if (ac) { if (av->a_type == A_SYMBOL) outlet_anything(((t_object *)x)->ob_outlet, av->a_w.w_symbol, ac - 1, av + 1); else if (av->a_type == A_FLOAT) { if (ac > 1) outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); else outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); } } binbuf_free(bb); } } static void fromsymbol_list(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av) { /* CHECKED: fromsymbol: doesn't understand "int", "float", 'list ' ignored without complaining. */ } static void fromsymbol_anything(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av) { fromsymbol_symbol(x, s); /* CHECKED */ } static void *fromsymbol_new(void) { t_fromsymbol *x = (t_fromsymbol *)pd_new(fromsymbol_class); outlet_new((t_object *)x, &s_anything); return (x); } void fromsymbol_setup(void) { fromsymbol_class = class_new(gensym("fromsymbol"), (t_newmethod)fromsymbol_new, 0, sizeof(t_fromsymbol), 0, 0); class_addbang(fromsymbol_class, fromsymbol_bang); class_addfloat(fromsymbol_class, fromsymbol_float); class_addsymbol(fromsymbol_class, fromsymbol_symbol); class_addlist(fromsymbol_class, fromsymbol_list); class_addanything(fromsymbol_class, fromsymbol_anything); } cyclone-0.1-alpha55/cyclone/hammer/active.c0000644000076500007650000000253511466617445017270 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "hammer/gui.h" typedef struct _active { t_object x_ob; t_symbol *x_cvname; int x_on; } t_active; static t_class *active_class; static void active_dofocus(t_active *x, t_symbol *s, t_floatarg f) { if ((int)f) { int on = (s == x->x_cvname); if (on != x->x_on) outlet_float(((t_object *)x)->ob_outlet, x->x_on = on); } else if (x->x_on && s == x->x_cvname) outlet_float(((t_object *)x)->ob_outlet, x->x_on = 0); } static void active_free(t_active *x) { hammergui_unbindfocus((t_pd *)x); } static void *active_new(void) { t_active *x = (t_active *)pd_new(active_class); char buf[32]; sprintf(buf, ".x%x.c", (int)canvas_getcurrent()); x->x_cvname = gensym(buf); x->x_on = 0; outlet_new((t_object *)x, &s_float); hammergui_bindfocus((t_pd *)x); return (x); } void active_setup(void) { active_class = class_new(gensym("active"), (t_newmethod)active_new, (t_method)active_free, sizeof(t_active), CLASS_NOINLET, 0); class_addmethod(active_class, (t_method)active_dofocus, gensym("_focus"), A_SYMBOL, A_FLOAT, 0); } cyclone-0.1-alpha55/cyclone/hammer/asin.c0000644000076500007650000000224211466617445016742 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define asinf asin #endif typedef struct _asin { t_object x_ob; float x_value; } t_asin; static t_class *asin_class; static void asin_bang(t_asin *x) { outlet_float(((t_object *)x)->ob_outlet, x->x_value); } static void asin_float(t_asin *x, t_float f) { if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ outlet_float(((t_object *)x)->ob_outlet, x->x_value = asinf(f)); } static void *asin_new(t_floatarg f) { t_asin *x = (t_asin *)pd_new(asin_class); if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ x->x_value = asinf(f); outlet_new((t_object *)x, &s_float); return (x); } void asin_setup(void) { asin_class = class_new(gensym("asin"), (t_newmethod)asin_new, 0, sizeof(t_asin), 0, A_DEFFLOAT, 0); class_addbang(asin_class, asin_bang); class_addfloat(asin_class, asin_float); } cyclone-0.1-alpha55/cyclone/hammer/iter.c0000644000076500007650000000550211466617445016755 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* This is a modified version of Joseph A. Sarlo's code. The most important changes are listed in "pd-lib-notes.txt" file. */ /* LATER compare with iter.c from max sdk */ /* LATER clean up buffer handling */ #include #include "m_pd.h" #include "common/grow.h" #define ITER_INISIZE 8 /* LATER rethink */ typedef struct _iter { t_object x_ob; int x_size; /* as allocated */ int x_natoms; /* as used */ t_symbol *x_selector; t_atom *x_message; t_atom x_messini[ITER_INISIZE]; } t_iter; static t_class *iter_class; /* CHECKED: both floats and symbols */ static void iter_dobang(t_iter *x, t_symbol *s, int ac, t_atom *av) { if (s && s != &s_) outlet_symbol(((t_object *)x)->ob_outlet, s); while (ac--) { if (av->a_type == A_FLOAT) outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); else if (av->a_type == A_SYMBOL) outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); av++; } } static void iter_bang(t_iter *x) { iter_dobang(x, x->x_selector, x->x_natoms, x->x_message); } static void iter_float(t_iter *x, t_float f) { outlet_float(((t_object *)x)->ob_outlet, f); x->x_selector = 0; x->x_natoms = 1; SETFLOAT(x->x_message, f); } /* CHECKME */ static void iter_symbol(t_iter *x, t_symbol *s) { outlet_symbol(((t_object *)x)->ob_outlet, s); x->x_selector = 0; x->x_natoms = 1; SETSYMBOL(x->x_message, s); } /* LATER gpointer */ static void iter_anything(t_iter *x, t_symbol *s, int ac, t_atom *av) { iter_dobang(x, s, ac, av); x->x_selector = s; if (ac > x->x_size) x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, ITER_INISIZE, x->x_messini, sizeof(*x->x_message)); x->x_natoms = ac; memcpy(x->x_message, av, ac * sizeof(*x->x_message)); } static void iter_list(t_iter *x, t_symbol *s, int ac, t_atom *av) { iter_anything(x, 0, ac, av); } static void iter_free(t_iter *x) { if (x->x_message != x->x_messini) freebytes(x->x_message, x->x_natoms * sizeof(*x->x_message)); } static void *iter_new(void) { t_iter *x = (t_iter *)pd_new(iter_class); x->x_size = ITER_INISIZE; x->x_natoms = 0; x->x_message = x->x_messini; outlet_new((t_object *)x, &s_anything); return (x); } void iter_setup(void) { iter_class = class_new(gensym("iter"), (t_newmethod)iter_new, (t_method)iter_free, sizeof(t_iter), 0, 0); class_addbang(iter_class, iter_bang); class_addfloat(iter_class, iter_float); class_addsymbol(iter_class, iter_symbol); class_addlist(iter_class, iter_list); class_addanything(iter_class, iter_anything); } cyclone-0.1-alpha55/cyclone/hammer/zl.c0000644000076500007650000005627711466617445016456 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* FIXME zl sub */ #include #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" /* CHECKME bang behaviour (every mode) */ /* LATER test reentrancy, tune speedwise */ #ifdef KRZYSZCZ //#define ZL_DEBUG #endif #define ZL_INISIZE 32 /* LATER rethink */ #define ZL_MAXSIZE 256 #define ZL_MAXMODES 16 #define ZL_DEFMODE 0 struct _zl; typedef int (*t_zlintargfn)(struct _zl *, int); typedef void (*t_zlanyargfn)(struct _zl *, t_symbol *, int, t_atom *); typedef int (*t_zlnatomsfn)(struct _zl *); typedef void (*t_zldoitfn)(struct _zl *, int, t_atom *, int); static int zl_nmodes = 0; static t_symbol *zl_modesym[ZL_MAXMODES]; static int zl_modeflags[ZL_MAXMODES]; static t_zlintargfn zl_intargfn[ZL_MAXMODES]; static t_zlanyargfn zl_anyargfn[ZL_MAXMODES]; static t_zlnatomsfn zl_natomsfn[ZL_MAXMODES]; static t_zldoitfn zl_doitfn[ZL_MAXMODES]; typedef struct _zldata { int d_size; /* as allocated */ int d_natoms; /* as used */ t_atom *d_buf; t_atom d_bufini[ZL_INISIZE]; } t_zldata; typedef struct _zl { t_object x_ob; struct _zlproxy *x_proxy; int x_entered; int x_locked; /* locking inbuf1 in modes: iter, reg, slice */ t_zldata x_inbuf1; t_zldata x_inbuf2; t_zldata x_outbuf; int x_mode; int x_modearg; t_outlet *x_out2; } t_zl; typedef struct _zlproxy { t_object p_ob; t_zl *p_master; } t_zlproxy; static t_class *zl_class; static t_class *zlproxy_class; static void zldata_init(t_zldata *d) { d->d_size = ZL_INISIZE; d->d_natoms = 0; d->d_buf = d->d_bufini; } static void zldata_free(t_zldata *d) { if (d->d_buf != d->d_bufini) freebytes(d->d_buf, d->d_size * sizeof(*d->d_buf)); } static void zldata_setfloat(t_zldata *d, t_float f) { SETFLOAT(d->d_buf, f); d->d_natoms = 1; } static void zldata_addfloat(t_zldata *d, t_float f) { int natoms = d->d_natoms; int nrequested = natoms + 1; if (nrequested > d->d_size) { d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (natoms >= nrequested) natoms = nrequested - 1; } SETFLOAT(d->d_buf + natoms, f); d->d_natoms = natoms + 1; } static void zldata_setsymbol(t_zldata *d, t_symbol *s) { SETSYMBOL(d->d_buf, s); d->d_natoms = 1; } static void zldata_addsymbol(t_zldata *d, t_symbol *s) { int natoms = d->d_natoms; int nrequested = natoms + 1; if (nrequested > d->d_size) { d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (natoms >= nrequested) natoms = nrequested - 1; } SETSYMBOL(d->d_buf + natoms, s); d->d_natoms = natoms + 1; } static void zldata_setlist(t_zldata *d, int ac, t_atom *av) { int nrequested = ac; if (nrequested > d->d_size) d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (d->d_natoms = nrequested) memcpy(d->d_buf, av, nrequested * sizeof(*d->d_buf)); } static void zldata_addlist(t_zldata *d, int ac, t_atom *av) { int natoms = d->d_natoms; int nrequested = natoms + ac; if (nrequested > d->d_size) { d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (natoms + ac > nrequested) { natoms = nrequested - ac; if (natoms < 0) natoms = 0, ac = nrequested; } } if (d->d_natoms = natoms + ac) memcpy(d->d_buf + natoms, av, ac * sizeof(*d->d_buf)); } static void zldata_set(t_zldata *d, t_symbol *s, int ac, t_atom *av) { if (s && s != &s_) { int nrequested = ac + 1; if (nrequested > d->d_size) d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (d->d_natoms = nrequested) { SETSYMBOL(d->d_buf, s); if (--nrequested) memcpy(d->d_buf + 1, av, nrequested * sizeof(*d->d_buf)); } } else zldata_setlist(d, ac, av); } static void zldata_add(t_zldata *d, t_symbol *s, int ac, t_atom *av) { if (s && s != &s_) { int natoms = d->d_natoms; int nrequested = natoms + 1 + ac; if (nrequested > d->d_size) { d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (natoms + 1 + ac > nrequested) { natoms = nrequested - 1 - ac; if (natoms < 0) natoms = 0, ac = nrequested - 1; } } if (d->d_natoms = natoms + 1 + ac) { SETSYMBOL(d->d_buf + natoms, s); if (ac > 0) memcpy(d->d_buf + natoms + 1, av, ac * sizeof(*d->d_buf)); } } else zldata_addlist(d, ac, av); } /* LATER rethink */ static void zl_dooutput(t_outlet *o, int ac, t_atom *av) { if (ac > 1) { if (av->a_type == A_FLOAT) outlet_list(o, &s_list, ac, av); else if (av->a_type == A_SYMBOL) outlet_anything(o, av->a_w.w_symbol, ac - 1, av + 1); } else if (ac) { if (av->a_type == A_FLOAT) outlet_float(o, av->a_w.w_float); else if (av->a_type == A_SYMBOL) #if 1 outlet_anything(o, av->a_w.w_symbol, 0, 0); /* CHECKED */ #else outlet_symbol(o, av->a_w.w_symbol); /* LATER rethink */ #endif } } static void zl_output(t_zl *x, int ac, t_atom *av) { zl_dooutput(((t_object *)x)->ob_outlet, ac, av); } static void zl_output2(t_zl *x, int ac, t_atom *av) { zl_dooutput(x->x_out2, ac, av); } static int zl_equal(t_atom *ap1, t_atom *ap2) { return (ap1->a_type == ap2->a_type && ((ap1->a_type == A_FLOAT && ap1->a_w.w_float == ap2->a_w.w_float) || (ap1->a_type == A_SYMBOL && ap1->a_w.w_symbol == ap2->a_w.w_symbol))); } /* Mode handlers: If zl__count's return value is positve, then the main routine uses an output buffer 'buf' (outbuf, or a separately allocated one). If zl__count's return value is zero, then the main routine is passed a null 'buf' (see below); if it is negative, then the main routine is not being called. zl_ (main routine) arguments: if 'buf' is null, 'natoms' is always zero -- in modes other than len (no buffer used), group, iter, reg, slice/ecils (inbuf1 used), there should be no output. If 'buf' is not null, then 'natoms' is guaranteed to be positive. */ static int zl_nop_count(t_zl *x) { return (0); } static void zl_nop(t_zl *x, int natoms, t_atom *buf, int banged) { loud_warning((t_pd *)x, 0, "unknown mode"); } static int zl_ecils_intarg(t_zl *x, int i) { return (i > 0 ? i : 0); /* CHECKED */ } static int zl_ecils_count(t_zl *x) { return (x->x_entered ? -1 : 0); } static void zl_ecils(t_zl *x, int natoms, t_atom *buf, int banged) { int cnt1, cnt2 = x->x_modearg; natoms = x->x_inbuf1.d_natoms; buf = x->x_inbuf1.d_buf; if (cnt2 > natoms) cnt2 = natoms, cnt1 = 0; /* CHECKED */ else cnt1 = natoms - cnt2; x->x_locked = 1; if (cnt2) zl_output2(x, cnt2, buf + cnt1); if (cnt1) zl_output(x, cnt1, buf); } static int zl_group_intarg(t_zl *x, int i) { return (i > 0 ? i : 0); /* CHECKED */ } static int zl_group_count(t_zl *x) { return (x->x_entered ? -1 : 0); } static void zl_group(t_zl *x, int natoms, t_atom *buf, int banged) { int cnt = x->x_modearg; if (cnt > 0) { natoms = x->x_inbuf1.d_natoms; buf = x->x_inbuf1.d_buf; if (natoms >= cnt) { t_atom *from; x->x_locked = 1; for (from = buf; natoms >= cnt; natoms -= cnt, from += cnt) zl_output(x, cnt, from); x->x_inbuf1.d_natoms = natoms; while (natoms--) *buf++ = *from++; } if (banged && x->x_inbuf1.d_natoms) { zl_output(x, x->x_inbuf1.d_natoms, buf); x->x_inbuf1.d_natoms = 0; } } else x->x_inbuf1.d_natoms = 0; /* CHECKED */ } static int zl_iter_intarg(t_zl *x, int i) { return (i > 0 ? i : 0); /* CHECKED */ } static int zl_iter_count(t_zl *x) { return (x->x_entered ? (x->x_modearg < x->x_inbuf1.d_natoms ? x->x_modearg : x->x_inbuf1.d_natoms) : 0); } static void zl_iter(t_zl *x, int natoms, t_atom *buf, int banged) { int nremaining = x->x_inbuf1.d_natoms; t_atom *ptr = x->x_inbuf1.d_buf; if (!buf) { if (natoms = (x->x_modearg < nremaining ? x->x_modearg : nremaining)) x->x_locked = 1; else return; } while (nremaining) { if (natoms > nremaining) natoms = nremaining; if (buf) { memcpy(buf, ptr, natoms * sizeof(*buf)); zl_output(x, natoms, buf); } else zl_output(x, natoms, ptr); nremaining -= natoms; ptr += natoms; } } static int zl_join_count(t_zl *x) { return (x->x_inbuf1.d_natoms + x->x_inbuf2.d_natoms); } static void zl_join(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) { int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms; if (ac1) memcpy(buf, x->x_inbuf1.d_buf, ac1 * sizeof(*buf)); if (ac2) memcpy(buf + ac1, x->x_inbuf2.d_buf, ac2 * sizeof(*buf)); zl_output(x, natoms, buf); } } static int zl_len_count(t_zl *x) { return (0); } static void zl_len(t_zl *x, int natoms, t_atom *buf, int banged) { /* CHECKED 'mode len, bang'->[zl]->[print] crashes max 4.0.7... */ if (!banged) /* CHECKED bang is a nop in len mode */ outlet_float(((t_object *)x)->ob_outlet, x->x_inbuf1.d_natoms); } static int zl_nth_intarg(t_zl *x, int i) { return (i > 0 ? i : 0); /* CHECKED */ } static void zl_nth_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (!s && ac && av->a_type == A_FLOAT) zldata_setlist(&x->x_inbuf2, ac - 1, av + 1); } static int zl_nth_count(t_zl *x) { int ac1 = x->x_inbuf1.d_natoms; if (ac1) { if (x->x_modearg > 0) return (ac1 - 1 + x->x_inbuf2.d_natoms); else return (x->x_entered ? ac1 : 0); } else return (-1); } static void zl_nth(t_zl *x, int natoms, t_atom *buf, int banged) { int ac1 = x->x_inbuf1.d_natoms, ndx = x->x_modearg - 1; /* CHECKED one-based */ if (ac1 && ndx < ac1) /* CHECKED */ { t_atom *av1 = x->x_inbuf1.d_buf; if (ndx < 0) { if (buf) memcpy(buf, av1, ac1 * sizeof(*buf)); else { buf = av1; x->x_locked = 1; } zl_output2(x, ac1, buf); } else { t_atom at = av1[ndx]; if (buf) { int ac2 = x->x_inbuf2.d_natoms, ntail = ac1 - ndx - 1; t_atom *ptr = buf; if (ndx) { memcpy(ptr, av1, ndx * sizeof(*buf)); ptr += ndx; } if (ac2) /* replacement */ { memcpy(ptr, x->x_inbuf2.d_buf, ac2 * sizeof(*buf)); ptr += ac2; } if (ntail) memcpy(ptr, av1 + ndx + 1, ntail * sizeof(*buf)); zl_output2(x, natoms, buf); } zl_output(x, 1, &at); } } } static void zl_reg_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (!x->x_locked) zldata_set(&x->x_inbuf1, s, ac, av); } static int zl_reg_count(t_zl *x) { return (x->x_entered ? x->x_inbuf1.d_natoms : 0); } static void zl_reg(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf)); else { natoms = x->x_inbuf1.d_natoms; buf = x->x_inbuf1.d_buf; x->x_locked = 1; } if (natoms) zl_output(x, natoms, buf); } static int zl_rev_count(t_zl *x) { return (x->x_inbuf1.d_natoms); } static void zl_rev(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) { t_atom *from = x->x_inbuf1.d_buf, *to = buf + natoms; while (to-- > buf) *to = *from++; zl_output(x, natoms, buf); } } static int zl_rot_intarg(t_zl *x, int i) { return (i); /* CHECKED anything goes (modulo) */ } static int zl_rot_count(t_zl *x) { return (x->x_inbuf1.d_natoms); } static void zl_rot(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) { int cnt1 = x->x_modearg, cnt2; if (cnt1) { if (cnt1 > 0) { cnt1 %= natoms; cnt2 = natoms - cnt1; } else { cnt2 = -cnt1 % natoms; cnt1 = natoms - cnt2; } /* CHECKED right rotation for positive args */ memcpy(buf, x->x_inbuf1.d_buf + cnt2, cnt1 * sizeof(*buf)); memcpy(buf + cnt1, x->x_inbuf1.d_buf, cnt2 * sizeof(*buf)); } else memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf)); zl_output(x, natoms, buf); } } /* LATER rethink */ static int zl_sect_count(t_zl *x) { int result = 0; int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1; t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *ap1; for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) { int i2; t_atom *testp; for (i2 = 0, testp = av1; i2 < i1; i2++, testp++) if (zl_equal(ap1, testp)) goto skip; for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++) { if (zl_equal(ap1, testp)) { result++; break; } } skip:; } return (result); } /* CHECKED in-buffer duplicates are skipped */ static void zl_sect(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) { int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1; t_atom *ap1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *to = buf; for (i1 = 0; i1 < ac1; i1++, ap1++) { int i2; t_atom *testp; for (testp = buf; testp < to; testp++) if (zl_equal(ap1, testp)) goto skip; for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++) { if (zl_equal(ap1, testp)) { *to++ = *ap1; break; } } skip:; } zl_output(x, natoms, buf); } } static int zl_slice_intarg(t_zl *x, int i) { return (i > 0 ? i : 0); /* CHECKED */ } static int zl_slice_count(t_zl *x) { return (x->x_entered ? -1 : 0); } static void zl_slice(t_zl *x, int natoms, t_atom *buf, int banged) { int cnt1 = x->x_modearg, cnt2; natoms = x->x_inbuf1.d_natoms; buf = x->x_inbuf1.d_buf; if (cnt1 > natoms) cnt1 = natoms, cnt2 = 0; /* CHECKED */ else cnt2 = natoms - cnt1; x->x_locked = 1; if (cnt2) zl_output2(x, cnt2, buf + cnt1); if (cnt1) zl_output(x, cnt1, buf); } static int zl_sub_count(t_zl *x) { return (0); } static void zl_sub(t_zl *x, int natoms, t_atom *buf, int banged) { int natoms2 = x->x_inbuf2.d_natoms; if (natoms2) { int ndx1, natoms1 = x->x_inbuf1.d_natoms; t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf; for (ndx1 = 0; ndx1 < natoms1; ndx1++, av1++) { int ndx2; t_atom *ap1 = av1, *ap2 = av2; for (ndx2 = 0; ndx2 < natoms2; ndx2++, ap1++, ap2++) if (!zl_equal(ap1, ap2)) break; if (ndx2 == natoms2) /* CHECKED output position is zero-based */ outlet_float(((t_object *)x)->ob_outlet, ndx1); } } } /* LATER rethink */ static int zl_union_count(t_zl *x) { int result, ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2; t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf; result = ac1 + ac2; for (i2 = 0; i2 < ac2; i2++, ap2++) { int i1; t_atom *ap1; for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) { if (zl_equal(ap1, ap2)) { result--; break; } } } return (result); } /* CHECKED in-buffer duplicates not skipped */ static void zl_union(t_zl *x, int natoms, t_atom *buf, int banged) { if (buf) { int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2; t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf; if (ac1) { t_atom *to = buf + ac1; memcpy(buf, av1, ac1 * sizeof(*buf)); for (i2 = 0; i2 < ac2; i2++, ap2++) { int i1; t_atom *ap1; for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) if (zl_equal(ap1, ap2)) break; if (i1 == ac1) *to++ = *ap2; } } else memcpy(buf, ap2, ac2 * sizeof(*buf)); zl_output(x, natoms, buf); } } static void zl_doit(t_zl *x, int banged) { int reentered = x->x_entered; int prealloc = !reentered; int natoms = (*zl_natomsfn[x->x_mode])(x); if (natoms < 0) return; x->x_entered = 1; if (natoms) { t_zldata *d = &x->x_outbuf; t_atom *buf; if (prealloc && natoms > d->d_size) { if (natoms > ZL_MAXSIZE) prealloc = 0; else { int nrequested = natoms; d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); if (nrequested != natoms) prealloc = 0; } } /* LATER consider using the stack if !prealloc && natoms <= MAXSTACK */ if (buf = (prealloc ? d->d_buf : getbytes(natoms * sizeof(*buf)))) { (*zl_doitfn[x->x_mode])(x, natoms, buf, banged); if (buf != d->d_buf) freebytes(buf, natoms * sizeof(*buf)); } } else (*zl_doitfn[x->x_mode])(x, 0, 0, banged); if (!reentered) x->x_entered = x->x_locked = 0; } static void zl_bang(t_zl *x) { zl_doit(x, 1); } static void zl_float(t_zl *x, t_float f) { if (!x->x_locked) { if (zl_modeflags[x->x_mode]) zldata_addfloat(&x->x_inbuf1, f); else zldata_setfloat(&x->x_inbuf1, f); } zl_doit(x, 0); } static void zl_symbol(t_zl *x, t_symbol *s) { if (!x->x_locked) { if (zl_modeflags[x->x_mode]) zldata_addsymbol(&x->x_inbuf1, s); else zldata_setsymbol(&x->x_inbuf1, s); } zl_doit(x, 0); } /* LATER gpointer */ static void zl_list(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (!x->x_locked) { if (zl_modeflags[x->x_mode]) zldata_addlist(&x->x_inbuf1, ac, av); else zldata_setlist(&x->x_inbuf1, ac, av); } zl_doit(x, 0); } static void zl_anything(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (!x->x_locked) { if (zl_modeflags[x->x_mode]) zldata_add(&x->x_inbuf1, s, ac, av); else zldata_set(&x->x_inbuf1, s, ac, av); } zl_doit(x, 0); } static int zl_modeargfn(t_zl *x) { return (zl_intargfn[x->x_mode] || zl_anyargfn[x->x_mode]); } static void zl_setmodearg(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (zl_intargfn[x->x_mode]) { int i = (!s && ac && av->a_type == A_FLOAT ? (int)av->a_w.w_float : /* CHECKED silent truncation */ 0); /* CHECKED current x->x_modearg not kept */ x->x_modearg = (*zl_intargfn[x->x_mode])(x, i); } if (zl_anyargfn[x->x_mode]) (*zl_anyargfn[x->x_mode])(x, s, ac, av); } static void zl_mode(t_zl *x, t_symbol *s, int ac, t_atom *av) { if (ac && av->a_type == A_SYMBOL) { t_symbol *modesym = av->a_w.w_symbol; int i; for (i = 0; i < zl_nmodes; i++) if (modesym == zl_modesym[i]) break; /* LATER consider making this compatible: CHECKED setting unknown mode makes a zl nop */ if (i && i < zl_nmodes) { x->x_mode = i; /* CHECKED incompatible (LATER warn): c74 rejects creation args, if not a single int */ zl_setmodearg(x, 0, ac - 1, av + 1); } } } static void zlproxy_bang(t_zlproxy *d) { /* CHECKED a nop */ } static void zlproxy_float(t_zlproxy *p, t_float f) { t_zl *x = p->p_master; if (zl_modeargfn(x)) { t_atom at; SETFLOAT(&at, f); zl_setmodearg(x, 0, 1, &at); } else /* CHECKED inbuf2 filled only when used */ zldata_setfloat(&x->x_inbuf2, f); } static void zlproxy_symbol(t_zlproxy *p, t_symbol *s) { t_zl *x = p->p_master; if (zl_modeargfn(x)) { t_atom at; SETSYMBOL(&at, s); zl_setmodearg(x, 0, 1, &at); } else /* CHECKED inbuf2 filled only when used */ zldata_setsymbol(&x->x_inbuf2, s); } /* LATER gpointer */ static void zlproxy_list(t_zlproxy *p, t_symbol *s, int ac, t_atom *av) { if (ac) { t_zl *x = p->p_master; if (zl_modeargfn(x)) zl_setmodearg(x, 0, ac, av); else /* CHECKED inbuf2 filled only when used */ zldata_setlist(&x->x_inbuf2, ac, av); } } static void zlproxy_anything(t_zlproxy *p, t_symbol *s, int ac, t_atom *av) { t_zl *x = p->p_master; if (zl_modeargfn(x)) zl_setmodearg(x, s, ac, av); else /* CHECKED inbuf2 filled only when used */ zldata_set(&x->x_inbuf2, s, ac, av); } #ifdef ZL_DEBUG static void zl_debug(t_zl *x, t_floatarg f) { loudbug_startpost("mode %s", zl_modesym[x->x_mode]->s_name); if (zl_intargfn[x->x_mode]) loudbug_post(" %d", x->x_modearg); else loudbug_endpost(); if ((int)f) { loudbug_startpost("first:"); loudbug_postatom(x->x_inbuf1.d_natoms, x->x_inbuf1.d_buf); loudbug_endpost(); loudbug_startpost("second:"); loudbug_postatom(x->x_inbuf2.d_natoms, x->x_inbuf2.d_buf); loudbug_endpost(); } } #endif static void zl_free(t_zl *x) { zldata_free(&x->x_inbuf1); zldata_free(&x->x_inbuf2); zldata_free(&x->x_outbuf); if (x->x_proxy) pd_free((t_pd *)x->x_proxy); } static void *zl_new(t_symbol *s, int ac, t_atom *av) { t_zl *x = (t_zl *)pd_new(zl_class); t_zlproxy *y = (t_zlproxy *)pd_new(zlproxy_class); x->x_proxy = y; y->p_master = x; x->x_entered = 0; x->x_locked = 0; zldata_init(&x->x_inbuf1); zldata_init(&x->x_inbuf2); zldata_init(&x->x_outbuf); x->x_mode = ZL_DEFMODE; zl_mode(x, s, ac, av); inlet_new((t_object *)x, (t_pd *)y, 0, 0); outlet_new((t_object *)x, &s_anything); x->x_out2 = outlet_new((t_object *)x, &s_anything); return (x); } static void zl_setupmode(char *id, int flags, t_zlintargfn ifn, t_zlanyargfn afn, t_zlnatomsfn nfn, t_zldoitfn dfn) { if (zl_nmodes < ZL_MAXMODES) { zl_modesym[zl_nmodes] = gensym(id); zl_modeflags[zl_nmodes] = flags; zl_intargfn[zl_nmodes] = ifn; zl_anyargfn[zl_nmodes] = afn; zl_natomsfn[zl_nmodes] = nfn; zl_doitfn[zl_nmodes] = dfn; zl_nmodes++; } else loudbug_bug("zl_setupmode"); } static void zl_setupallmodes(void) { zl_setupmode("unknown", 0, 0, 0, zl_nop_count, zl_nop); zl_setupmode("ecils", 0, zl_ecils_intarg, 0, zl_ecils_count, zl_ecils); zl_setupmode("group", 1, zl_group_intarg, 0, zl_group_count, zl_group); zl_setupmode("iter", 0, zl_iter_intarg, 0, zl_iter_count, zl_iter); zl_setupmode("join", 0, 0, 0, zl_join_count, zl_join); zl_setupmode("len", 0, 0, 0, zl_len_count, zl_len); zl_setupmode("nth", 0, zl_nth_intarg, zl_nth_anyarg, zl_nth_count, zl_nth); zl_setupmode("reg", 0, 0, zl_reg_anyarg, zl_reg_count, zl_reg); zl_setupmode("rev", 0, 0, 0, zl_rev_count, zl_rev); zl_setupmode("rot", /* CHECKED (refman's error) */ 0, zl_rot_intarg, 0, zl_rot_count, zl_rot); zl_setupmode("sect", 0, 0, 0, zl_sect_count, zl_sect); zl_setupmode("slice", 0, zl_slice_intarg, 0, zl_slice_count, zl_slice); zl_setupmode("sub", 0, 0, 0, zl_sub_count, zl_sub); zl_setupmode("union", 0, 0, 0, zl_union_count, zl_union); } void zl_setup(void) { zl_class = class_new(gensym("zl"), (t_newmethod)zl_new, (t_method)zl_free, sizeof(t_zl), 0, A_GIMME, 0); class_addbang(zl_class, zl_bang); class_addfloat(zl_class, zl_float); class_addsymbol(zl_class, zl_symbol); class_addlist(zl_class, zl_list); class_addanything(zl_class, zl_anything); class_addmethod(zl_class, (t_method)zl_mode, gensym("mode"), A_GIMME, 0); #ifdef ZL_DEBUG class_addmethod(zl_class, (t_method)zl_debug, gensym("debug"), A_DEFFLOAT, 0); #endif zlproxy_class = class_new(gensym("_zlproxy"), 0, 0, sizeof(t_zlproxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(zlproxy_class, zlproxy_bang); class_addfloat(zlproxy_class, zlproxy_float); class_addsymbol(zlproxy_class, zlproxy_symbol); class_addlist(zlproxy_class, zlproxy_list); class_addanything(zlproxy_class, zlproxy_anything); zl_setupallmodes(); } cyclone-0.1-alpha55/cyclone/hammer/mean.c0000644000076500007650000000344511466617445016736 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _mean { t_object x_ob; double x_accum; unsigned x_count; t_float x_mean; t_outlet *x_countout; } t_mean; static t_class *mean_class; static void mean_clear(t_mean *x) { x->x_accum = 0; x->x_count = 0; x->x_mean = 0; } static void mean_bang(t_mean *x) { /* CHECKED: count is always sent (first) */ outlet_float(x->x_countout, x->x_count); outlet_float(((t_object *)x)->ob_outlet, x->x_mean); } static void mean_float(t_mean *x, t_float f) { x->x_accum += f; if (++x->x_count) x->x_mean = (t_float)(x->x_accum / (double)x->x_count); else mean_clear(x); mean_bang(x); } static void mean_list(t_mean *x, t_symbol *s, int ac, t_atom *av) { mean_clear(x); while (ac--) { if (av->a_type == A_FLOAT) { x->x_accum += av->a_w.w_float; x->x_count++; } av++; } if (x->x_count) x->x_mean = (t_float)(x->x_accum / (double)x->x_count); else mean_clear(x); mean_bang(x); /* CHECKED: no clear after list -- subsequent floats are added */ } static void *mean_new(void) { t_mean *x = (t_mean *)pd_new(mean_class); mean_clear(x); outlet_new((t_object *)x, &s_float); x->x_countout = outlet_new((t_object *)x, &s_float); return (x); } void mean_setup(void) { mean_class = class_new(gensym("mean"), (t_newmethod)mean_new, 0, sizeof(t_mean), 0, 0); class_addbang(mean_class, mean_bang); class_addfloat(mean_class, mean_float); class_addlist(mean_class, mean_list); class_addmethod(mean_class, (t_method)mean_clear, gensym("clear"), 0); } cyclone-0.1-alpha55/cyclone/hammer/tosymbol.c0000644000076500007650000001120611466617445017660 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" #define TOSYMBOL_INISTRING 128 /* LATER rethink */ #define TOSYMBOL_MAXSTRING 2048 /* the refman says so, later CHECKME */ static char tosymbol_defseparator[] = " "; typedef struct _tosymbol { t_object x_ob; t_symbol *x_separator; int x_bufsize; char *x_buffer; char x_bufini[TOSYMBOL_INISTRING]; int x_entered; } t_tosymbol; static t_class *tosymbol_class; static char tosymbol_buffer[TOSYMBOL_MAXSTRING]; static int tosymbol_bufferlocked = 0; /* The idea is to prevent two different tosymbol objects from using the static buffer at the same time. In the current scenario this buffer is never used for output, so this lock is unnecessary... but it does no harm either... */ static void tosymbol_flushbuffer(t_tosymbol *x) { if (*x->x_buffer) { x->x_entered = 1; outlet_symbol(((t_object *)x)->ob_outlet, gensym(x->x_buffer)); x->x_entered = 0; } } static void tosymbol_bang(t_tosymbol *x) { outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */ } static void tosymbol_float(t_tosymbol *x, t_float f) { if (!x->x_entered) { sprintf(x->x_buffer, "%g", f); tosymbol_flushbuffer(x); } } static void tosymbol_symbol(t_tosymbol *x, t_symbol *s) { outlet_symbol(((t_object *)x)->ob_outlet, s); } static void tosymbol_pointer(t_tosymbol *x, t_gpointer *gp) { /* nop: otherwise gpointer would be converted to 'list ' */ } static int tosymbol_parse(t_symbol *s, int ac, t_atom *av, t_symbol *separator, int bufsize, char *buffer) { int nleft = bufsize - 1; int len; char *bp = buffer; bp[0] = bp[nleft] = 0; if (s) strncpy(bp, s->s_name, nleft); len = strlen(bp); nleft -= len; bp += len; if (ac && nleft > 0) { char *sepstring = (separator ? separator->s_name : tosymbol_defseparator); while (ac--) { if (*sepstring && bp > buffer) { strncpy(bp, sepstring, nleft); len = strlen(bp); nleft -= len; if (nleft <= 0) break; bp += len; } /* LATER rethink: type-checking */ atom_string(av, bp, nleft); len = strlen(bp); nleft -= len; bp += len; if (nleft <= 0) break; av++; } } if (nleft < 0) { loudbug_bug("tosymbol_parse"); return (bufsize); } return (bufsize - nleft); } static void tosymbol_anything(t_tosymbol *x, t_symbol *s, int ac, t_atom *av) { if (!x->x_entered) { if (tosymbol_bufferlocked) { loudbug_bug("tosymbol_anything"); tosymbol_parse(s, ac, av, x->x_separator, x->x_bufsize, x->x_buffer); } else { int ntotal; tosymbol_bufferlocked = 1; ntotal = tosymbol_parse(s, ac, av, x->x_separator, TOSYMBOL_MAXSTRING, tosymbol_buffer); if (ntotal > x->x_bufsize) { int newtotal = ntotal; x->x_buffer = grow_nodata(&newtotal, &x->x_bufsize, x->x_buffer, TOSYMBOL_INISTRING, x->x_bufini, sizeof(*x->x_buffer)); if (newtotal < ntotal) { ntotal = newtotal - 1; x->x_buffer[ntotal] = 0; } } memcpy(x->x_buffer, tosymbol_buffer, ntotal); tosymbol_bufferlocked = 0; } tosymbol_flushbuffer(x); } } static void tosymbol_list(t_tosymbol *x, t_symbol *s, int ac, t_atom *av) { tosymbol_anything(x, 0, ac, av); } static void tosymbol_separator(t_tosymbol *x, t_symbol *s) { x->x_separator = (s ? s : &s_); /* default: empty string */ } static void tosymbol_free(t_tosymbol *x) { if (x->x_buffer != x->x_bufini) freebytes(x->x_buffer, x->x_bufsize); } static void *tosymbol_new(void) { t_tosymbol *x = (t_tosymbol *)pd_new(tosymbol_class); x->x_separator = 0; /* default: a space */ x->x_bufsize = TOSYMBOL_INISTRING; x->x_buffer = x->x_bufini; x->x_entered = 0; outlet_new((t_object *)x, &s_symbol); return (x); } void tosymbol_setup(void) { tosymbol_class = class_new(gensym("tosymbol"), (t_newmethod)tosymbol_new, (t_method)tosymbol_free, sizeof(t_tosymbol), 0, 0); class_addbang(tosymbol_class, tosymbol_bang); class_addfloat(tosymbol_class, tosymbol_float); class_addsymbol(tosymbol_class, tosymbol_symbol); class_addpointer(tosymbol_class, tosymbol_pointer); class_addlist(tosymbol_class, tosymbol_list); class_addanything(tosymbol_class, tosymbol_anything); class_addmethod(tosymbol_class, (t_method)tosymbol_separator, gensym("separator"), A_DEFSYM, 0); } cyclone-0.1-alpha55/cyclone/hammer/poltocar.c0000644000076500007650000000214511466617445017635 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #if defined(NT) || defined(MACOSX) /* cf pd/src/x_arithmetic.c */ #define sinf sin #define cosf cos #endif typedef struct _poltocar { t_object x_ob; t_float x_phase; t_outlet *x_out2; } t_poltocar; static t_class *poltocar_class; static void poltocar_float(t_poltocar *x, t_float f) { outlet_float(x->x_out2, f * sinf(x->x_phase)); outlet_float(((t_object *)x)->ob_outlet, f * cosf(x->x_phase)); } static void *poltocar_new(void) { t_poltocar *x = (t_poltocar *)pd_new(poltocar_class); floatinlet_new((t_object *)x, &x->x_phase); outlet_new((t_object *)x, &s_float); x->x_out2 = outlet_new((t_object *)x, &s_float); return (x); } void poltocar_setup(void) { poltocar_class = class_new(gensym("poltocar"), (t_newmethod)poltocar_new, 0, sizeof(t_poltocar), 0, 0); class_addfloat(poltocar_class, poltocar_float); } cyclone-0.1-alpha55/cyclone/hammer/onebang.c0000644000076500007650000000211511466617445017420 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include "m_pd.h" typedef struct _onebang { t_object x_ob; int x_isopen; } t_onebang; static t_class *onebang_class; static void onebang_bang(t_onebang *x) { if (x->x_isopen) { outlet_bang(((t_object *)x)->ob_outlet); x->x_isopen = 0; } } static void onebang_bang1(t_onebang *x) { x->x_isopen = 1; } static void *onebang_new(t_floatarg f) { t_onebang *x = (t_onebang *)pd_new(onebang_class); x->x_isopen = ((int)f != 0); /* CHECKED */ inlet_new((t_object *)x, (t_pd *)x, &s_bang, gensym("bang1")); outlet_new((t_object *)x, &s_bang); return (x); } void onebang_setup(void) { onebang_class = class_new(gensym("onebang"), (t_newmethod)onebang_new, 0, sizeof(t_onebang), 0, A_DEFFLOAT, 0); class_addbang(onebang_class, onebang_bang); class_addmethod(onebang_class, (t_method)onebang_bang1, gensym("bang1"), 0); } cyclone-0.1-alpha55/cyclone/hammer/funnel.c0000644000076500007650000001160011466617445017275 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "common/grow.h" #define FUNNEL_MINSLOTS 2 #define FUNNEL_INISIZE 32 /* LATER rethink */ #define FUNNEL_MAXSIZE 256 typedef struct _funnel { t_object x_ob; int x_nslots; int x_nproxies; /* as requested (and allocated) */ t_pd **x_proxies; } t_funnel; typedef struct _funnel_proxy { t_object p_ob; t_outlet *p_out; /* master outlet (the same value for each slot) */ int p_id; /* adjusted according to an offset argument */ t_float p_value; int p_size; /* as allocated */ t_atom *p_message; t_atom p_messini[FUNNEL_INISIZE]; int p_entered; } t_funnel_proxy; static t_class *funnel_class; static t_class *funnel_proxy_class; static void funnel_proxy_bang(t_funnel_proxy *x) { t_atom at[2]; SETFLOAT(&at[0], x->p_id); SETFLOAT(&at[1], x->p_value); outlet_list(x->p_out, &s_list, 2, at); } static void funnel_proxy_float(t_funnel_proxy *x, t_float f) { x->p_value = f; funnel_proxy_bang(x); } static void funnel_proxy_list(t_funnel_proxy *x, t_symbol *s, int ac, t_atom *av) { int reentered = x->p_entered; int prealloc = !reentered; int ntotal = ac + 1; x->p_entered = 1; if (prealloc && ntotal > x->p_size) { if (ntotal > FUNNEL_MAXSIZE) prealloc = 0; else { x->p_message = grow_nodata(&ntotal, &x->p_size, x->p_message, FUNNEL_INISIZE, x->p_messini, sizeof(*x->p_message)); ac = ntotal - 1; } } /* LATER consider a compatibility warning if av->a_type != A_FLOAT */ x->p_value = ((ac && av->a_type == A_FLOAT) ? av->a_w.w_float : 0); if (prealloc) { SETFLOAT(x->p_message, x->p_id); if (ac) memcpy(x->p_message + 1, av, ac * sizeof(*x->p_message)); outlet_list(x->p_out, &s_list, ntotal, x->p_message); } else { /* LATER consider using the stack if ntotal <= MAXSTACK */ t_atom *buf = getbytes(ntotal * sizeof(*buf)); if (buf) { SETFLOAT(buf, x->p_id); if (ac) memcpy(buf + 1, av, ac * sizeof(*buf)); outlet_list(x->p_out, &s_list, ntotal, buf); freebytes(buf, ntotal * sizeof(*buf)); } } if (!reentered) x->p_entered = 0; } static void funnel_bang(t_funnel *x) { funnel_proxy_bang((t_funnel_proxy *)x->x_proxies[0]); } static void funnel_float(t_funnel *x, t_float f) { funnel_proxy_float((t_funnel_proxy *)x->x_proxies[0], f); } static void funnel_list(t_funnel *x, t_symbol *s, int ac, t_atom *av) { funnel_proxy_list((t_funnel_proxy *)x->x_proxies[0], s, ac, av); } static void funnel_free(t_funnel *x) { if (x->x_proxies) { int i = x->x_nslots; while (i--) { t_funnel_proxy *y = (t_funnel_proxy *)x->x_proxies[i]; if (y->p_message != y->p_messini) freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); pd_free((t_pd *)y); } freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); } } static void *funnel_new(t_floatarg f1, t_floatarg f2) { t_funnel *x; int i, nslots, nproxies = (int)f1; int offset = (int)f2; t_outlet *out; t_pd **proxies; if (nproxies < 1) /* CHECKED: one-slot funnel may be created */ nproxies = FUNNEL_MINSLOTS; if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) return (0); for (nslots = 0; nslots < nproxies; nslots++) if (!(proxies[nslots] = pd_new(funnel_proxy_class))) break; if (!nslots) { freebytes(proxies, nproxies * sizeof(*proxies)); return (0); } x = (t_funnel *)pd_new(funnel_class); x->x_nslots = nslots; x->x_nproxies = nproxies; x->x_proxies = proxies; out = outlet_new((t_object *)x, &s_list); for (i = 0; i < nslots; i++) { t_funnel_proxy *y = (t_funnel_proxy *)proxies[i]; y->p_out = out; y->p_id = offset++; y->p_value = 0; y->p_size = FUNNEL_INISIZE; y->p_message = y->p_messini; y->p_entered = 0; if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); } return (x); } void funnel_setup(void) { funnel_class = class_new(gensym("funnel"), (t_newmethod)funnel_new, (t_method)funnel_free, sizeof(t_funnel), 0, A_DEFFLOAT, A_DEFFLOAT, 0); class_addbang(funnel_class, funnel_bang); class_addfloat(funnel_class, funnel_float); class_addlist(funnel_class, funnel_list); /* CHECKED: funnel doesn't understand symbol, anything */ funnel_proxy_class = class_new(gensym("_funnel_proxy"), 0, 0, sizeof(t_funnel_proxy), CLASS_PD | CLASS_NOINLET, 0); class_addbang(funnel_proxy_class, funnel_proxy_bang); class_addfloat(funnel_proxy_class, funnel_proxy_float); class_addlist(funnel_proxy_class, funnel_proxy_list); /* CHECKED: funnel doesn't understand symbol, anything */ } cyclone-0.1-alpha55/cyclone/hammer/past.c0000644000076500007650000000665311466617445016771 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* CHECKED: bang for a float at > (refman error: >=) bang for a list if all >= (refman page says the same) bang for a list if any is >, even if the rest (but not previous) is < well... */ #include "m_pd.h" #include "common/loud.h" #include "common/grow.h" #include "common/fitter.h" #define PAST_C74MAXSIZE 8 /* CHECKED */ typedef struct past { t_object x_ob; int x_low; int x_size; /* as allocated */ int x_nthresh; /* as used */ t_atom *x_thresh; t_atom x_thrini[PAST_C74MAXSIZE]; } t_past; static t_class *past_class; static int past_compare(t_past *x, t_float f, t_atom *ap) { if (ap->a_type == A_FLOAT) { if (f > ap->a_w.w_float) return (1); else if (f == ap->a_w.w_float) return (0); else return (-1); } else /* CHECKED */ { if (f > 0.) return (1); else if (f == 0.) return (0); else return (-1); } } static void past_float(t_past *x, t_float f) { if (x->x_nthresh == 1) { if (past_compare(x, f, x->x_thresh) > 0) /* CHECKED: equal is low */ { if (x->x_low) { x->x_low = 0; outlet_bang(((t_object *)x)->ob_outlet); } } else x->x_low = 1; } else if (past_compare(x, f, x->x_thresh) < 0) x->x_low = 1; } /* CHECKME: x_low handling */ static void past_list(t_past *x, t_symbol *s, int ac, t_atom *av) { if (ac && ac <= x->x_nthresh) { int result; t_atom *vp = x->x_thresh; if (av->a_type == A_FLOAT && (result = past_compare(x, av->a_w.w_float, vp)) >= 0) { if (!result) { for (ac--, av++, vp++; ac; ac--, av++, vp++) { if (av->a_type != A_FLOAT || (result = past_compare(x, av->a_w.w_float, vp++)) < 0) { x->x_low = 1; return; } if (result) break; } } if (x->x_low) { x->x_low = 0; outlet_bang(((t_object *)x)->ob_outlet); } } else x->x_low = 1; } } static void past_clear(t_past *x) { x->x_low = 1; } static void past_set(t_past *x, t_symbol *s, int ac, t_atom *av) { if (ac) { t_atom *vp = x->x_thresh; if (ac > x->x_size) { fittermax_rangewarning(past_class, PAST_C74MAXSIZE, "guard points"); x->x_thresh = grow_nodata(&ac, &x->x_size, x->x_thresh, PAST_C74MAXSIZE, x->x_thrini, sizeof(*x->x_thresh)); } x->x_nthresh = ac; while (ac--) *vp++ = *av++; /* CHECKED: x_low is not set here */ } } static void past_free(t_past *x) { if (x->x_thresh != x->x_thrini) freebytes(x->x_thresh, x->x_size * sizeof(*x->x_thresh)); } static void *past_new(t_symbol *s, int ac, t_atom *av) { t_past *x = (t_past *)pd_new(past_class); x->x_low = 1; x->x_nthresh = 0; x->x_size = PAST_C74MAXSIZE; x->x_thresh = x->x_thrini; outlet_new((t_object *)x, &s_bang); past_set(x, 0, ac, av); return (x); } void past_setup(void) { past_class = class_new(gensym("past"), (t_newmethod)past_new, (t_method)past_free, sizeof(t_past), 0, A_GIMME, 0); class_addfloat(past_class, past_float); class_addlist(past_class, past_list); class_addmethod(past_class, (t_method)past_clear, gensym("clear"), 0); class_addmethod(past_class, (t_method)past_set, gensym("set"), A_GIMME, 0); fitter_setup(past_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/pv.c0000644000076500007650000002514311466617445016442 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* CHECKED (it cannot be emulated): creating [s/r ] prints "error:send/receive::already exists" */ #include #include "m_pd.h" #include "g_canvas.h" #include "common/loud.h" #include "common/grow.h" #define PV_INISIZE 32 /* LATER rethink */ #define PV_MAXSIZE 256 typedef struct _pvfamily { t_symbol *f_selector; t_float f_float; t_symbol *f_symbol; t_gpointer *f_pointer; int f_size; /* as allocated */ int f_natoms; /* as used */ t_atom *f_message; t_atom f_messini[PV_INISIZE]; t_glist *f_glist; /* root glist of a family */ t_symbol *f_name; struct _pvfamily *f_next; } t_pvfamily; typedef struct _pvlist { t_pd l_pd; int l_refcount; t_symbol *l_name; t_pvfamily *l_pvlist; } t_pvlist; typedef struct _pv { t_object x_ob; t_glist *x_glist; t_symbol *x_name; t_pvfamily *x_family; } t_pv; static t_class *pv_class; static t_class *pvlist_class; static void pvlist_decrement(t_pvlist *pl) { if (!--pl->l_refcount) { pd_unbind(&pl->l_pd, pl->l_name); pd_free(&pl->l_pd); } } static t_pvlist *pv_getlist(t_symbol *s, int create) { t_pvlist *pl = (t_pvlist *)pd_findbyclass(s, pvlist_class); if (pl) { if (create) pl->l_refcount++; } else { if (create) { pl = (t_pvlist *)pd_new(pvlist_class); pl->l_refcount = 1; pl->l_name = s; pl->l_pvlist = 0; pd_bind(&pl->l_pd, s); } else loudbug_bug("pv_getlist"); } return (pl); } static t_pvfamily *pv_newfamily(t_pvlist *pvlist) { t_pvfamily *pf = (t_pvfamily *)getbytes(sizeof(*pf)); pf->f_name = pvlist->l_name; pf->f_next = pvlist->l_pvlist; pvlist->l_pvlist = pf; pf->f_selector = 0; pf->f_float = 0; pf->f_symbol = 0; pf->f_pointer = 0; pf->f_size = PV_INISIZE; pf->f_natoms = 0; pf->f_message = pf->f_messini; return (pf); } static void pvfamily_free(t_pvfamily *pf) { if (pf->f_message != pf->f_messini) freebytes(pf->f_message, pf->f_size * sizeof(*pf->f_message)); freebytes(pf, sizeof(*pf)); } static void pv_update(t_glist *glist, t_pvfamily *pf) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ pv_update((t_glist *)g, pf); else if (pd_class(&g->g_pd) == pv_class && ((t_pv *)g)->x_name == pf->f_name) ((t_pv *)g)->x_family = pf; } static t_pvfamily *pvfamily_reusable; static void pv_breakup(t_pvlist *pvlist, t_glist *glist) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) { if (pd_class(&g->g_pd) == pv_class && ((t_pv *)g)->x_name == pvlist->l_name) { t_pvfamily *pf; if (!(pf = pvfamily_reusable)) pf = pv_newfamily(pvlist); else pvfamily_reusable = 0; pf->f_glist = glist; pv_update(glist, pf); /* LATER keep current value */ return; } } for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ pv_breakup(pvlist, (t_glist *)g); } /* join all families of a 'pvlist' rooted in any subglist of a 'glist' */ static t_pvfamily *pv_joinup(t_pvlist *pvlist, t_glist *glist) { t_pvfamily *result = 0; t_pvfamily *pf, *pfprev, *pfnext; for (pfprev = 0, pf = pvlist->l_pvlist; pf; pfprev = pf, pf = pfnext) { t_glist *gl; pfnext = pf->f_next; for (gl = pf->f_glist; gl; gl = gl->gl_owner) { if (gl == glist) { if (result) { pvfamily_free(pf); if (pfprev) pfprev->f_next = pfnext; else pvlist->l_pvlist = pfnext; pf = pfprev; } else result = pf; break; } } } return (result); } /* Called normally with either 'create' or 'destroy' set to 1, but it might be called with both set to 0 for testing. */ static t_pvfamily *pv_getfamily(t_glist *glist, t_symbol *s, int create, int destroy) { t_pvlist *pl = pv_getlist(s, create); if (pl) { if (destroy) { t_pvfamily *pf, *mypf; t_glist *gl; for (mypf = pl->l_pvlist; mypf; mypf = mypf->f_next) if (mypf->f_glist == glist) break; /* mypf is not null iff we are invoked via a [pv] in root */ /* now check if there is a family rooted in a super-branch */ for (gl = glist->gl_owner; gl; gl = gl->gl_owner) { for (pf = pl->l_pvlist; pf; pf = pf->f_next) { if (pf->f_glist == gl) { if (mypf) loudbug_bug("pv_getfamily 1: %s in %s", mypf->f_name->s_name, mypf->f_glist->gl_name->s_name); else return (0); } } } if (mypf) { pvfamily_reusable = mypf; pv_breakup(pl, glist); if (pvfamily_reusable == mypf) { pvfamily_reusable = 0; if (pl->l_pvlist == mypf) pl->l_pvlist = mypf->f_next; else { for (pf = pl->l_pvlist; pf; pf = pf->f_next) { if (pf->f_next == mypf) { pf->f_next = mypf->f_next; break; } } if (!pf) loudbug_bug("pv_getfamily 2"); } pvfamily_free(mypf); } } else loudbug_bug("pv_getfamily 3"); pvlist_decrement(pl); } else { t_pvfamily *pf; t_glist *gl; for (gl = glist; gl; gl = gl->gl_owner) for (pf = pl->l_pvlist; pf; pf = pf->f_next) if (pf->f_glist == gl) return (pf); if (create) { if (!(pf = pv_joinup(pl, glist))) pf = pv_newfamily(pl); pf->f_glist = glist; pv_update(glist, pf); return (pf); } else loudbug_bug("pv_getfamily 4"); } } else loudbug_bug("pv_getfamily 5"); return (0); } static t_pvfamily *pv_checkfamily(t_pv *x) { if (!x->x_family) { loudbug_bug("pv_checkfamily"); x->x_family = pv_getfamily(x->x_glist, x->x_name, 0, 0); } return (x->x_family); } static void pv_bang(t_pv *x) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { t_symbol *s = pf->f_selector; if (s == &s_bang) outlet_bang(((t_object *)x)->ob_outlet); else if (s == &s_float) outlet_float(((t_object *)x)->ob_outlet, pf->f_float); else if (s == &s_symbol && pf->f_symbol) outlet_symbol(((t_object *)x)->ob_outlet, pf->f_symbol); else if (s == &s_pointer) { /* LATER */ } else if (s == &s_list) outlet_list(((t_object *)x)->ob_outlet, s, pf->f_natoms, pf->f_message); else if (s) outlet_anything(((t_object *)x)->ob_outlet, s, pf->f_natoms, pf->f_message); } } static void pv_float(t_pv *x, t_float f) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { pf->f_selector = &s_float; pf->f_float = f; pf->f_natoms = 0; /* defensive */ } } static void pv_symbol(t_pv *x, t_symbol *s) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { pf->f_selector = &s_symbol; pf->f_symbol = s; pf->f_natoms = 0; /* defensive */ } } static void pv_pointer(t_pv *x, t_gpointer *gp) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { pf->f_selector = &s_pointer; pf->f_pointer = gp; pf->f_natoms = 0; /* defensive */ } } static void pvfamily_domessage(t_pvfamily *pf, int ac, t_atom *av) { if (ac > pf->f_size) { /* LATER consider using PV_MAXSIZE (and warning if exceeded) */ pf->f_message = grow_nodata(&ac, &pf->f_size, pf->f_message, PV_INISIZE, pf->f_messini, sizeof(*pf->f_message)); } pf->f_natoms = ac; memcpy(pf->f_message, av, ac * sizeof(*pf->f_message)); } static void pv_list(t_pv *x, t_symbol *s, int ac, t_atom *av) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { pf->f_selector = &s_list; /* LATER rethink */ pvfamily_domessage(pf, ac, av); } } static void pv_anything(t_pv *x, t_symbol *s, int ac, t_atom *av) { t_pvfamily *pf = pv_checkfamily(x); if (pf) { pf->f_selector = s; /* LATER rethink */ pvfamily_domessage(pf, ac, av); } } static void pv_objstatus(t_pv *x, t_glist *glist) { t_gobj *g; for (g = glist->gl_list; g; g = g->g_next) { if (g == (t_gobj *)x) post("%x (this object) owning patcher [%s]", (int)g, glist->gl_name->s_name); else if (pd_class(&g->g_pd) == pv_class && ((t_pv *)g)->x_name == x->x_name) post("%x owning patcher [%s]", (int)g, glist->gl_name->s_name); } } static void pv_status(t_pv *x) { t_pvlist *pl = pv_getlist(x->x_name, 0); post("pv status: Tied to %s", x->x_name->s_name); if (pl) { t_pvfamily *pf; int fcount; for (pf = pl->l_pvlist, fcount = 1; pf; pf = pf->f_next, fcount++) { t_glist *glist = pf->f_glist; t_gobj *g; post("Family %d:", fcount); pv_objstatus(x, glist); for (g = glist->gl_list; g; g = g->g_next) if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ pv_objstatus(x, (t_glist *)g); } } } static void pv_free(t_pv *x) { pv_getfamily(x->x_glist, x->x_name, 0, 1); } static void *pv_new(t_symbol *s, int ac, t_atom *av) { t_pv *x = 0; if (ac && av->a_type == A_SYMBOL) s = av->a_w.w_symbol; else s = 0; if (s && s != &s_) { t_glist *gl = canvas_getcurrent(); t_pvfamily *pf = pv_getfamily(gl, s, 1, 0); x = (t_pv *)pd_new(pv_class); x->x_glist = gl; x->x_name = s; x->x_family = pf; outlet_new((t_object *)x, &s_float); if (--ac) { av++; if (av->a_type == A_SYMBOL) { if (av->a_w.w_symbol == &s_symbol) { if (ac > 1 && av[1].a_type == A_SYMBOL) pv_symbol(x, av[1].a_w.w_symbol); } /* LATER rethink 'pv bang' (now it is accepted) */ else pv_anything(x, av->a_w.w_symbol, ac - 1, av + 1); } else if (av->a_type == A_FLOAT) { if (ac > 1) pv_list(x, &s_list, ac, av); else pv_float(x, av->a_w.w_float); } } } else /* CHECKED: "error: missing or bad arguments", a box is created without inlets and outlets */ loud_classarg(pv_class); return (x); } void pv_setup(void) { pv_class = class_new(gensym("pv"), (t_newmethod)pv_new, (t_method)pv_free, sizeof(t_pv), 0, A_GIMME, 0); class_addbang(pv_class, pv_bang); class_addfloat(pv_class, pv_float); class_addsymbol(pv_class, pv_symbol); class_addpointer(pv_class, pv_pointer); class_addlist(pv_class, pv_list); class_addanything(pv_class, pv_anything); class_addmethod(pv_class, (t_method)pv_status, gensym("status"), 0); /* CHECKED: sending bang (or int, list, status, etc.) with '; ' "error::doesn't understand bang" (class name is an empty string) */ pvlist_class = class_new(&s_, 0, 0, sizeof(t_pvlist), CLASS_PD, 0); } cyclone-0.1-alpha55/cyclone/hammer/testmess.c0000644000076500007650000002070511466617445017663 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include #include "m_pd.h" #include "unstable/fragile.h" #ifdef MSW #define snprintf _snprintf #endif #define TESTMESS_INISIZE 4 /* LATER rethink */ #define TESTMESS_STACKSIZE 256 typedef struct _testmess { t_object x_ob; t_symbol *x_method; void (*x_messfun)(struct _testmess *, t_symbol *s, int, t_atom *); int x_appendmode; int x_size; /* as allocated */ int x_natoms; /* as used */ int x_tailwise; /* data is moved to the end of a buffer */ t_atom *x_message; t_atom *x_messbuf; t_atom x_messini[TESTMESS_INISIZE]; } t_testmess; static t_class *testmess_class; static void testmess_setnatoms(t_testmess *x, int natoms) { if (x->x_tailwise) x->x_message = x->x_messbuf + x->x_size - natoms; else x->x_message = x->x_messbuf; x->x_natoms = natoms; } static int testmess_makeroom(t_testmess *x, int natoms, int preserve) { if (x->x_size < natoms) { int newsize = x->x_size * 2; while (newsize < natoms) newsize *= 2; /* post("makeroom %s %d %d %d", x->x_method->s_name, preserve, natoms, newsize);*/ if (x->x_messbuf == x->x_messini) { if (!(x->x_messbuf = (t_atom *)getbytes(newsize * sizeof(*x->x_messbuf)))) { x->x_messbuf = x->x_messini; testmess_setnatoms(x, preserve ? x->x_natoms : 0); return (0); } x->x_size = newsize; testmess_setnatoms(x, preserve ? x->x_natoms : 0); if (x->x_natoms) { if (x->x_tailwise) memcpy(x->x_message, x->x_messini + TESTMESS_INISIZE - x->x_natoms, x->x_natoms * sizeof(*x->x_message)); else memcpy(x->x_message, x->x_messini, x->x_natoms * sizeof(*x->x_message)); } } else { int oldsize = x->x_size; if (!(x->x_messbuf = (t_atom *)resizebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf), newsize * sizeof(*x->x_messbuf)))) { x->x_messbuf = x->x_messini; x->x_size = TESTMESS_INISIZE; testmess_setnatoms(x, 0); return (0); } x->x_size = newsize; testmess_setnatoms(x, preserve ? x->x_natoms : 0); if (x->x_natoms && x->x_tailwise) memmove(x->x_message, x->x_messbuf + oldsize - x->x_natoms, x->x_natoms * sizeof(*x->x_message)); } } return (1); } static void testmess_stackmess(t_testmess *x, t_symbol *s, int ac, t_atom *av) { t_atom buf[TESTMESS_STACKSIZE]; int natoms = x->x_natoms; if (x->x_appendmode) { int left = TESTMESS_STACKSIZE - ac; if (left < 0) ac = TESTMESS_STACKSIZE, natoms = 0; else if (natoms > left) natoms = left; if (ac) memcpy(buf, av, ac * sizeof(*buf)); if (natoms) memcpy(buf + ac, x->x_message, natoms * sizeof(*buf)); } else { int left = TESTMESS_STACKSIZE - natoms; if (left < 0) natoms = TESTMESS_STACKSIZE, ac = 0; else if (ac > left) ac = left; if (natoms) memcpy(buf, x->x_message, natoms * sizeof(*buf)); if (ac) memcpy(buf + natoms, av, ac * sizeof(*buf)); } outlet_anything(((t_object *)x)->ob_outlet, s, natoms + ac, buf); } static void testmess_heapmess(t_testmess *x, t_symbol *s, int ac, t_atom *av) { int ntotal = x->x_natoms + ac; t_atom *buf = getbytes(ntotal * sizeof(*buf)); if (buf) { if (x->x_appendmode) { if (ac) memcpy(buf, av, ac * sizeof(*buf)); if (x->x_natoms) memcpy(buf + ac, x->x_message, x->x_natoms * sizeof(*buf)); } else { if (x->x_natoms) memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf)); if (ac) memcpy(buf + x->x_natoms, av, ac * sizeof(*buf)); } outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); freebytes(buf, ntotal * sizeof(*buf)); } } static void testmess_premess(t_testmess *x, t_symbol *s, int ac, t_atom *av) { int ntotal = x->x_natoms + ac; if (testmess_makeroom(x, ntotal, 1)) { t_atom *buf; if (x->x_appendmode) { buf = x->x_messbuf + x->x_size - ntotal; if (ac) memcpy(buf, av, ac * sizeof(*buf)); } else { buf = x->x_messbuf; if (ac) memcpy(buf + x->x_natoms, av, ac * sizeof(*buf)); } outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); } } static void testmess_bang(t_testmess *x) { if (x->x_natoms) x->x_messfun(x, &s_list, 0, 0); } static void testmess_float(t_testmess *x, t_float f) { t_atom at; SETFLOAT(&at, f); x->x_messfun(x, (x->x_natoms ? &s_list : &s_float), 1, &at); } static void testmess_symbol(t_testmess *x, t_symbol *s) { x->x_messfun(x, s, 0, 0); } static void testmess_anything(t_testmess *x, t_symbol *s, int ac, t_atom *av) { x->x_messfun(x, s, ac, av); } static void testmess_setnumbers(t_testmess *x, int natoms, int start) { if (natoms <= 0) natoms = 100; if (testmess_makeroom(x, natoms * 2, 0)) { t_atom *ap; testmess_setnatoms(x, natoms); ap = x->x_message; while (natoms--) { SETFLOAT(ap, (t_float)start); start++; ap++; } } } #define FRAGILE_HASHSIZE 1024 static int fragile_hash(t_symbol *s) { unsigned int hash1 = 0, hash2 = 0; char *ptr = s->s_name; while (*ptr) { hash1 += *ptr++; hash2 += hash1; } return (hash2 & (FRAGILE_HASHSIZE-1)); } int fragile_symbol_count(void) { return (100); } void fragile_getsymbols(t_atom *av) { t_symbol *s = gensym("#N"); int i; for (i = 0, s -= fragile_hash(s); i < FRAGILE_HASHSIZE; i++, s++) { if (s->s_name) { t_symbol *s1; for (s1 = s; s1; s1 = s1->s_next) printf("%s\n", s1->s_name); } } } static void testmess_setnames(t_testmess *x, t_symbol *s, int natoms, int nchars) { if (!s) s = &s_; if (*s->s_name == 'c') { natoms = fragile_class_count(); if (natoms > 0 && testmess_makeroom(x, natoms * 2, 0)) { testmess_setnatoms(x, natoms); fragile_class_getnames(x->x_message, natoms); } } else { if (natoms <= 0) natoms = 100; if (nchars <= 0) nchars = 10; if (testmess_makeroom(x, natoms * 2, 0)) { char buf[MAXPDSTRING], fmt[16]; int i = 0; t_atom *ap; testmess_setnatoms(x, natoms); ap = x->x_message; sprintf(fmt, "%%.%dx", nchars); while (natoms--) { snprintf(buf, MAXPDSTRING-1, fmt, i); SETSYMBOL(ap, gensym(buf)); i++; ap++; } } } } static void testmess_set(t_testmess *x, t_symbol *s, int ac, t_atom *av) { t_symbol *csym = 0, *msym = 0; t_float f1 = 0., f2 = 0.; if (ac) { if (av->a_type == A_SYMBOL) csym = av->a_w.w_symbol; else if (av->a_type == A_FLOAT) f1 = av->a_w.w_float; if (ac > 1) { if (av[1].a_type == A_SYMBOL) msym = av[1].a_w.w_symbol; else if (av[1].a_type == A_FLOAT) { if (csym) f1 = av[1].a_w.w_float; else f2 = av[1].a_w.w_float; if (ac > 2) { if (av[2].a_type == A_SYMBOL) msym = av[2].a_w.w_symbol; else if (csym && av[2].a_type == A_FLOAT) f2 = av[2].a_w.w_float; } } } } if (msym == gensym("stack")) x->x_method = msym, x->x_messfun = testmess_stackmess; else if (msym == gensym("heap")) x->x_method = msym, x->x_messfun = testmess_heapmess; else { x->x_method = gensym("prealloc"); x->x_messfun = testmess_premess; x->x_tailwise = x->x_appendmode; } testmess_setnatoms(x, 0); if (csym) testmess_setnames(x, csym, (int)f1, (int)f2); else testmess_setnumbers(x, (int)f1, (int)f2); } static void testmess_free(t_testmess *x) { if (x->x_messbuf != x->x_messini) freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); } static void *testmess_new(t_symbol *s, int ac, t_atom *av) { t_testmess *x = (t_testmess *)pd_new(testmess_class); x->x_appendmode = 1; x->x_tailwise = 0; x->x_size = TESTMESS_INISIZE; x->x_messbuf = x->x_messini; outlet_new((t_object *)x, &s_anything); testmess_set(x, s, ac, av); return (x); } void testmess_setup(void) { testmess_class = class_new(gensym("testmess"), (t_newmethod)testmess_new, (t_method)testmess_free, sizeof(t_testmess), 0, A_GIMME, 0); class_addbang(testmess_class, testmess_bang); class_addfloat(testmess_class, testmess_float); class_addsymbol(testmess_class, testmess_symbol); class_addanything(testmess_class, testmess_anything); class_addmethod(testmess_class, (t_method)testmess_set, gensym("set"), A_GIMME, 0); } cyclone-0.1-alpha55/cyclone/hammer/Uzi.c0000644000076500007650000000537211466617445016566 0ustar hanshans/* Copyright (c) 2002-2003 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* CHECKME negative 'nbangs' value set during run-time */ #include "m_pd.h" typedef struct _Uzi { t_object x_obj; t_float x_nbangs; int x_count; int x_running; t_outlet *x_out2; t_outlet *x_out3; } t_Uzi; static t_class *Uzi_class; #define UZI_RUNNING 1 #define UZI_PAUSED 2 static void Uzi_dobang(t_Uzi *x) { /* CHECKME reentrancy */ if (!x->x_running) { int count, nbangs = (int)x->x_nbangs; x->x_running = UZI_RUNNING; for (count = x->x_count + 1; count <= nbangs; count++) { outlet_float(x->x_out3, count); outlet_bang(((t_object *)x)->ob_outlet); if (x->x_running == UZI_PAUSED) { /* CHECKED: carry bang not sent, even if this is last bang */ x->x_count = count; return; } } /* CHECKED: carry bang sent also when there are no left-outlet bangs */ /* CHECKED: sent after left outlet, not before */ outlet_bang(x->x_out2); x->x_count = 0; x->x_running = 0; } } static void Uzi_bang(t_Uzi *x) { /* CHECKED: always restarts (when paused too) */ x->x_count = 0; x->x_running = 0; Uzi_dobang(x); } static void Uzi_float(t_Uzi *x, t_float f) { /* CHECKED: always sets a new value and restarts (when paused too) */ x->x_nbangs = f; Uzi_bang(x); } /* CHECKED: 'pause, resume' (but not just 'resume') sends a carry bang when not running (a bug?) */ static void Uzi_pause(t_Uzi *x) { if (!x->x_running) x->x_count = (int)x->x_nbangs; /* bug emulation? */ x->x_running = UZI_PAUSED; } static void Uzi_resume(t_Uzi *x) { if (x->x_running == UZI_PAUSED) { x->x_running = 0; Uzi_dobang(x); } } static void *Uzi_new(t_floatarg f) { t_Uzi *x = (t_Uzi *)pd_new(Uzi_class); x->x_nbangs = (f > 1. ? f : 1.); x->x_count = 0; x->x_running = 0; /* CHECKED: set when paused, but then 'resume' is blocked (a bug?) */ floatinlet_new((t_object *)x, &x->x_nbangs); outlet_new((t_object *)x, &s_bang); x->x_out2 = outlet_new((t_object *)x, &s_bang); x->x_out3 = outlet_new((t_object *)x, &s_float); return (x); } void Uzi_setup(void) { Uzi_class = class_new(gensym("Uzi"), (t_newmethod)Uzi_new, 0, sizeof(t_Uzi), 0, A_DEFFLOAT, 0); class_addbang(Uzi_class, Uzi_bang); class_addfloat(Uzi_class, Uzi_float); class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("pause"), 0); class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("break"), 0); class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("resume"), 0); class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("continue"), 0); } cyclone-0.1-alpha55/cyclone/hammer/seq.c0000644000076500007650000010070511466617445016603 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* CHECKED no sharing of data among seq objects having the same creation arg */ #include #include #include #include "m_pd.h" #include "shared.h" #include "common/loud.h" #include "common/grow.h" #include "common/fitter.h" #include "common/mifi.h" #include "unstable/forky.h" #include "hammer/file.h" #ifdef KRZYSZCZ #define SEQ_DEBUG #endif #define SEQ_INISEQSIZE 256 /* LATER rethink */ #define SEQ_INITEMPOMAPSIZE 128 /* LATER rethink */ #define SEQ_EOM 255 /* end of message marker, LATER rethink */ #define SEQ_TICKSPERSEC 48 #define SEQ_MINTICKDELAY 1. /* LATER rethink */ #define SEQ_TICKEPSILON ((double).0001) #define SEQ_STARTEPSILON .0001 /* if inside: play unmodified */ #define SEQ_TEMPOEPSILON .0001 /* if inside: pause */ #define SEQ_ISRUNNING(x) ((x)->x_prevtime > (double).0001) #define SEQ_ISPAUSED(x) ((x)->x_prevtime <= (double).0001) enum { SEQ_IDLEMODE, SEQ_RECMODE, SEQ_PLAYMODE, SEQ_SLAVEMODE }; typedef struct _seqevent { double e_delta; unsigned char e_bytes[4]; } t_seqevent; typedef struct _seqtempo { double t_scoretime; /* score ticks from start */ double t_sr; /* score ticks per second */ } t_seqtempo; typedef struct _seq { t_object x_ob; t_canvas *x_canvas; t_symbol *x_defname; t_hammerfile *x_filehandle; int x_mode; int x_playhead; double x_nextscoretime; float x_timescale; float x_newtimescale; double x_prevtime; double x_slaveprevtime; double x_clockdelay; unsigned char x_status; int x_evelength; int x_expectedlength; int x_eventreadhead; int x_seqsize; /* as allocated */ int x_nevents; /* as used */ t_seqevent *x_sequence; t_seqevent x_seqini[SEQ_INISEQSIZE]; int x_temporeadhead; int x_tempomapsize; /* as allocated */ int x_ntempi; /* as used */ t_seqtempo *x_tempomap; t_seqtempo x_tempomapini[SEQ_INITEMPOMAPSIZE]; t_clock *x_clock; t_clock *x_slaveclock; t_outlet *x_bangout; } t_seq; static t_class *seq_class; static void seq_doclear(t_seq *x, int dofree) { if (dofree) { if (x->x_sequence != x->x_seqini) { freebytes(x->x_sequence, x->x_seqsize * sizeof(*x->x_sequence)); x->x_sequence = x->x_seqini; x->x_seqsize = SEQ_INISEQSIZE; } if (x->x_tempomap != x->x_tempomapini) { freebytes(x->x_tempomap, x->x_tempomapsize * sizeof(*x->x_tempomap)); x->x_tempomap = x->x_tempomapini; x->x_tempomapsize = SEQ_INITEMPOMAPSIZE; } } x->x_nevents = 0; x->x_ntempi = 0; } static int seq_dogrowing(t_seq *x, int nevents, int ntempi) { if (nevents > x->x_seqsize) { int nrequested = nevents; #ifdef SEQ_DEBUG loudbug_post("growing for %d events...", nevents); #endif x->x_sequence = grow_nodata(&nrequested, &x->x_seqsize, x->x_sequence, SEQ_INISEQSIZE, x->x_seqini, sizeof(*x->x_sequence)); if (nrequested < nevents) { x->x_nevents = 0; x->x_ntempi = 0; return (0); } } if (ntempi > x->x_tempomapsize) { int nrequested = ntempi; #ifdef SEQ_DEBUG loudbug_post("growing for %d tempi...", ntempi); #endif x->x_tempomap = grow_nodata(&nrequested, &x->x_tempomapsize, x->x_tempomap, SEQ_INITEMPOMAPSIZE, x->x_tempomapini, sizeof(*x->x_tempomap)); if (nrequested < ntempi) { x->x_ntempi = 0; return (0); } } x->x_nevents = nevents; x->x_ntempi = ntempi; return (1); } static void seq_complete(t_seq *x) { if (x->x_evelength < x->x_expectedlength) { /* CHECKED no warning if no data after status byte requiring data */ if (x->x_evelength > 1) post("seq: truncated midi message"); /* CHECKED */ /* CHECKED nothing stored */ } else { t_seqevent *ep = &x->x_sequence[x->x_nevents]; ep->e_delta = clock_gettimesince(x->x_prevtime); x->x_prevtime = clock_getlogicaltime(); if (x->x_evelength < 4) ep->e_bytes[x->x_evelength] = SEQ_EOM; x->x_nevents++; if (x->x_nevents >= x->x_seqsize) { int nexisting = x->x_seqsize; /* store-ahead scheme, LATER consider using x_currevent */ int nrequested = x->x_nevents + 1; #ifdef SEQ_DEBUG loudbug_post("growing..."); #endif x->x_sequence = grow_withdata(&nrequested, &nexisting, &x->x_seqsize, x->x_sequence, SEQ_INISEQSIZE, x->x_seqini, sizeof(*x->x_sequence)); if (nrequested <= x->x_nevents) x->x_nevents = 0; } } x->x_evelength = 0; } static void seq_checkstatus(t_seq *x, unsigned char c) { if (x->x_status && x->x_evelength > 1) /* LATER rethink */ seq_complete(x); if (c < 192) x->x_expectedlength = 3; else if (c < 224) x->x_expectedlength = 2; else if (c < 240) x->x_expectedlength = 3; else if (c < 248) { /* FIXME */ x->x_expectedlength = -1; } else { x->x_sequence[x->x_nevents].e_bytes[0] = c; x->x_evelength = x->x_expectedlength = 1; seq_complete(x); return; } x->x_status = x->x_sequence[x->x_nevents].e_bytes[0] = c; x->x_evelength = 1; } static void seq_addbyte(t_seq *x, unsigned char c, int docomplete) { x->x_sequence[x->x_nevents].e_bytes[x->x_evelength++] = c; if (x->x_evelength == x->x_expectedlength) { seq_complete(x); if (x->x_status) { x->x_sequence[x->x_nevents].e_bytes[0] = x->x_status; x->x_evelength = 1; } } else if (x->x_evelength == 4) { if (x->x_status != 240) loudbug_bug("seq_addbyte"); /* CHECKED sysex is broken into 4-byte packets marked with the actual delta time of last byte received in a packet */ seq_complete(x); } else if (docomplete) seq_complete(x); } static void seq_endofsysex(t_seq *x) { seq_addbyte(x, 247, 1); x->x_status = 0; } static void seq_stoprecording(t_seq *x) { if (x->x_status == 240) { post("seq: incomplete sysex"); /* CHECKED */ seq_endofsysex(x); /* CHECKED 247 added implicitly */ } else if (x->x_status) seq_complete(x); /* CHECKED running status used in recording, but not across recordings */ x->x_status = 0; } static void seq_stopplayback(t_seq *x) { /* FIXME */ /* CHECKED "seq: incomplete sysex" at playback stop, 247 added implicitly */ /* CHECKME resetting controllers, etc. */ /* CHECKED bang not sent if playback stopped early */ clock_unset(x->x_clock); x->x_playhead = 0; x->x_nextscoretime = 0.; } static void seq_stopslavery(t_seq *x) { /* FIXME */ clock_unset(x->x_clock); clock_unset(x->x_slaveclock); x->x_playhead = 0; x->x_nextscoretime = 0.; } static void seq_startrecording(t_seq *x, int modechanged) { x->x_prevtime = clock_getlogicaltime(); x->x_status = 0; x->x_evelength = 0; x->x_expectedlength = -1; /* LATER rethink */ } /* CHECKED running status not used in playback */ static void seq_startplayback(t_seq *x, int modechanged) { /* CHECKED bang not sent if sequence is empty */ if (x->x_nevents) { if (modechanged) { x->x_playhead = 0; x->x_nextscoretime = x->x_sequence->e_delta; /* playback data never sent within the scheduler event of a start message (even for the first delta <= 0), LATER rethink */ x->x_clockdelay = x->x_sequence->e_delta * x->x_newtimescale; } else { /* CHECKED timescale change */ if (SEQ_ISRUNNING(x)) x->x_clockdelay -= clock_gettimesince(x->x_prevtime); x->x_clockdelay *= x->x_newtimescale / x->x_timescale; } if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; x->x_timescale = x->x_newtimescale; clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); } else x->x_mode = SEQ_IDLEMODE; } static void seq_startslavery(t_seq *x, int modechanged) { if (x->x_nevents) { x->x_playhead = 0; x->x_nextscoretime = 0.; x->x_prevtime = 0.; x->x_slaveprevtime = 0.; } else x->x_mode = SEQ_IDLEMODE; } static void seq_setmode(t_seq *x, int newmode) { int changed = (x->x_mode != newmode); if (changed) { switch (x->x_mode) { case SEQ_IDLEMODE: break; case SEQ_RECMODE: seq_stoprecording(x); break; case SEQ_PLAYMODE: seq_stopplayback(x); break; case SEQ_SLAVEMODE: seq_stopslavery(x); break; default: loudbug_bug("seq_setmode (old)"); return; } x->x_mode = newmode; } switch (newmode) { case SEQ_IDLEMODE: break; case SEQ_RECMODE: seq_startrecording(x, changed); break; case SEQ_PLAYMODE: seq_startplayback(x, changed); break; case SEQ_SLAVEMODE: seq_startslavery(x, changed); break; default: loudbug_bug("seq_setmode (new)"); } } static void seq_settimescale(t_seq *x, float newtimescale) { if (newtimescale < 1e-20) x->x_newtimescale = 1e-20; else if (newtimescale > 1e20) x->x_newtimescale = 1e20; else x->x_newtimescale = newtimescale; } static void seq_clocktick(t_seq *x) { if (x->x_mode == SEQ_PLAYMODE || x->x_mode == SEQ_SLAVEMODE) { t_seqevent *ep = &x->x_sequence[x->x_playhead++]; unsigned char *bp = ep->e_bytes; nextevent: outlet_float(((t_object *)x)->ob_outlet, *bp++); if (*bp != SEQ_EOM) { outlet_float(((t_object *)x)->ob_outlet, *bp++); if (*bp != SEQ_EOM) { outlet_float(((t_object *)x)->ob_outlet, *bp++); if (*bp != SEQ_EOM) outlet_float(((t_object *)x)->ob_outlet, *bp++); } } if (x->x_mode != SEQ_PLAYMODE && x->x_mode != SEQ_SLAVEMODE) return; /* protecting against outlet -> 'stop' etc. */ if (x->x_playhead < x->x_nevents) { ep++; x->x_nextscoretime += ep->e_delta; if (ep->e_delta < SEQ_TICKEPSILON) /* continue output in the same scheduler event, LATER rethink */ { x->x_playhead++; bp = ep->e_bytes; goto nextevent; } else { x->x_clockdelay = ep->e_delta * x->x_timescale; if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); } } else { seq_setmode(x, SEQ_IDLEMODE); /* CHECKED bang sent immediately _after_ last byte */ outlet_bang(x->x_bangout); /* LATER think about reentrancy */ } } } /* timeout handler ('tick' is late) */ static void seq_slaveclocktick(t_seq *x) { if (x->x_mode == SEQ_SLAVEMODE) clock_unset(x->x_clock); } /* LATER dealing with self-invokation (outlet -> 'tick') */ static void seq_tick(t_seq *x) { if (x->x_mode == SEQ_SLAVEMODE) { if (x->x_slaveprevtime > 0) { double elapsed = clock_gettimesince(x->x_slaveprevtime); if (elapsed < SEQ_MINTICKDELAY) return; clock_delay(x->x_slaveclock, elapsed); seq_settimescale(x, (float)(elapsed * (SEQ_TICKSPERSEC / 1000.))); if (SEQ_ISRUNNING(x)) { x->x_clockdelay -= clock_gettimesince(x->x_prevtime); x->x_clockdelay *= x->x_newtimescale / x->x_timescale; } else x->x_clockdelay = x->x_sequence[x->x_playhead].e_delta * x->x_newtimescale; if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); x->x_slaveprevtime = x->x_prevtime; x->x_timescale = x->x_newtimescale; } else { x->x_clockdelay = 0.; /* redundant */ x->x_prevtime = 0.; /* redundant */ x->x_slaveprevtime = clock_getlogicaltime(); x->x_timescale = 1.; /* redundant */ } } } /* CHECKED bang does the same as 'start 1024', not 'start ' (also if already in SEQ_PLAYMODE) */ static void seq_bang(t_seq *x) { seq_settimescale(x, 1.); seq_setmode(x, SEQ_PLAYMODE); /* CHECKED 'bang' stops recording */ } static void seq_float(t_seq *x, t_float f) { if (x->x_mode == SEQ_RECMODE) { /* CHECKED noninteger and out of range silently truncated */ unsigned char c = (unsigned char)f; if (c < 128) { if (x->x_status) seq_addbyte(x, c, 0); } else if (c != 254) /* CHECKED active sensing ignored */ { if (x->x_status == 240) { if (c == 247) seq_endofsysex(x); else { /* CHECKED rt bytes alike */ post("seq: unterminated sysex"); /* CHECKED */ seq_endofsysex(x); /* CHECKED 247 added implicitly */ seq_checkstatus(x, c); } } else if (c != 247) seq_checkstatus(x, c); } } } static void seq_symbol(t_seq *x, t_symbol *s) { loud_nomethod((t_pd *)x, &s_symbol); /* CHECKED */ } static void seq_list(t_seq *x, t_symbol *s, int ac, t_atom *av) { if (ac && av->a_type == A_FLOAT) seq_float(x, av->a_w.w_float); /* CHECKED anything else/more silently ignored */ } static void seq_record(t_seq *x) { /* CHECKED 'record' stops playback, resets recording */ seq_doclear(x, 0); seq_setmode(x, SEQ_RECMODE); } static void seq_append(t_seq *x) { /* CHECKED 'append' stops playback */ /* CHECKED if in SEQ_RECMODE, 'append' resets the timer */ seq_setmode(x, SEQ_RECMODE); } static void seq_start(t_seq *x, t_floatarg f) { if (f < -SEQ_STARTEPSILON) { /* FIXME */ seq_setmode(x, SEQ_SLAVEMODE); } else { seq_settimescale(x, (f > SEQ_STARTEPSILON ? 1024. / f : 1.)); seq_setmode(x, SEQ_PLAYMODE); /* CHECKED 'start' stops recording */ } } static void seq_stop(t_seq *x) { seq_setmode(x, SEQ_IDLEMODE); } /* CHECKED first delta time is set permanently (it is stored in a file) */ static void seq_delay(t_seq *x, t_floatarg f) { if (x->x_nevents) /* CHECKED signed/unsigned bug (not emulated) */ x->x_sequence->e_delta = (f > SEQ_TICKEPSILON ? f : 0.); } /* CHECKED all delta times are set permanently (they are stored in a file) */ static void seq_hook(t_seq *x, t_floatarg f) { int nevents; if (nevents = x->x_nevents) { t_seqevent *ev = x->x_sequence; if (f < 0) f = 0; /* CHECKED signed/unsigned bug (not emulated) */ while (nevents--) ev++->e_delta *= f; } } static void seq_pause(t_seq *x) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'pause' not supported in Max"); warned = 1; } if (x->x_mode == SEQ_PLAYMODE && SEQ_ISRUNNING(x)) { x->x_clockdelay -= clock_gettimesince(x->x_prevtime); if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; clock_unset(x->x_clock); x->x_prevtime = 0.; } } static void seq_continue(t_seq *x) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'continue' not supported in Max"); warned = 1; } if (x->x_mode == SEQ_PLAYMODE && SEQ_ISPAUSED(x)) { if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); } } static void seq_goto(t_seq *x, t_floatarg f1, t_floatarg f2) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'goto' not supported in Max"); warned = 1; } if (x->x_nevents) { t_seqevent *ev; int ndx, nevents = x->x_nevents; double ms = (double)f1 * 1000. + f2, sum; if (ms <= SEQ_TICKEPSILON) ms = 0.; if (x->x_mode != SEQ_PLAYMODE) { seq_settimescale(x, x->x_timescale); seq_setmode(x, SEQ_PLAYMODE); /* clock_delay() has been called in setmode, LATER avoid */ clock_unset(x->x_clock); x->x_prevtime = 0.; } for (ndx = 0, ev = x->x_sequence, sum = SEQ_TICKEPSILON; ndx < nevents; ndx++, ev++) { if ((sum += ev->e_delta) >= ms) { x->x_playhead = ndx; x->x_nextscoretime = sum; x->x_clockdelay = sum - SEQ_TICKEPSILON - ms; if (x->x_clockdelay < 0.) x->x_clockdelay = 0.; if (SEQ_ISRUNNING(x)) { clock_delay(x->x_clock, x->x_clockdelay); x->x_prevtime = clock_getlogicaltime(); } break; } } } } static void seq_scoretime(t_seq *x, t_symbol *s) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'scoretime' not supported in Max"); warned = 1; } if (s && s->s_thing && x->x_mode == SEQ_PLAYMODE) /* LATER other modes */ { t_atom aout[2]; double ms, clockdelay = x->x_clockdelay; t_float f1, f2; if (SEQ_ISRUNNING(x)) clockdelay -= clock_gettimesince(x->x_prevtime); ms = x->x_nextscoretime - clockdelay / x->x_timescale; /* Send ms as a pair of floats (f1, f2) = (coarse in sec, fine in msec). Any ms may then be exactly reconstructed as (double)f1 * 1000. + f2. Currently, f2 may be negative. LATER consider truncating f1 so that only significant digits are on (when using 1 ms resolution, a float stores only up to 8.7 minutes without distortion, 100 ms resolution gives 14.5 hours of non-distorted floats, etc.) */ f1 = ms * .001; f2 = ms - (double)f1 * 1000.; if (f2 < .001 && f2 > -.001) f2 = 0.; SETFLOAT(&aout[0], f1); SETFLOAT(&aout[1], f2); pd_list(s->s_thing, &s_list, 2, aout); } } static void seq_tempo(t_seq *x, t_floatarg f) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'tempo' not supported in Max"); warned = 1; } if (f > SEQ_TEMPOEPSILON) { seq_settimescale(x, 1. / f); if (x->x_mode == SEQ_PLAYMODE) seq_startplayback(x, 0); } /* FIXME else pause, LATER reverse playback if (f < -SEQ_TEMPOEPSILON) */ } static void seq_cd(t_seq *x, t_symbol *s) { static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'cd' not supported in Max"); warned = 1; } hammerpanel_setopendir(x->x_filehandle, s); } static void seq_pwd(t_seq *x, t_symbol *s) { t_symbol *dir; static int warned = 0; if (fittermax_get() && !warned) { fittermax_warning(*(t_pd *)x, "'pwd' not supported in Max"); warned = 1; } if (s && s->s_thing && (dir = hammerpanel_getopendir(x->x_filehandle))) pd_symbol(s->s_thing, dir); } static int seq_eventcomparehook(const void *e1, const void *e2) { return (((t_seqevent *)e1)->e_delta > ((t_seqevent *)e2)->e_delta ? 1 : -1); } static int seq_tempocomparehook(const void *t1, const void *t2) { return (((t_seqtempo *)t1)->t_scoretime > ((t_seqtempo *)t2)->t_scoretime ? 1 : -1); } static int seq_mrhook(t_mifiread *mr, void *hookdata, int evtype) { t_seq *x = (t_seq *)hookdata; double scoretime = mifiread_getscoretime(mr); if (evtype >= 0xf0) { } else if (evtype >= 0x80) { if (x->x_eventreadhead < x->x_nevents) { t_seqevent *sev = &x->x_sequence[x->x_eventreadhead++]; int status = mifiread_getstatus(mr); sev->e_delta = scoretime; sev->e_bytes[0] = status | mifiread_getchannel(mr); sev->e_bytes[1] = mifiread_getdata1(mr); if (MIFI_ONEDATABYTE(status)) sev->e_bytes[2] = SEQ_EOM; else { sev->e_bytes[2] = mifiread_getdata2(mr); sev->e_bytes[3] = SEQ_EOM; } } else if (x->x_eventreadhead == x->x_nevents) { loudbug_bug("seq_mrhook 1"); x->x_eventreadhead++; } } else if (evtype == MIFIMETA_TEMPO) { if (x->x_temporeadhead < x->x_ntempi) { t_seqtempo *stm = &x->x_tempomap[x->x_temporeadhead++]; stm->t_scoretime = scoretime; stm->t_sr = mifiread_gettempo(mr); #ifdef SEQ_DEBUG loudbug_post("tempo %g at %g", stm->t_sr, scoretime); #endif } else if (x->x_temporeadhead == x->x_ntempi) { loudbug_bug("seq_mrhook 2"); x->x_temporeadhead++; } } return (1); } /* apply tempo and fold */ static void seq_foldtime(t_seq *x, double deftempo) { t_seqevent *sev; t_seqtempo *stm = x->x_tempomap; double coef = 1000. / deftempo; int ex, tx = 0; double prevscoretime = 0.; while (tx < x->x_ntempi && stm->t_scoretime < SEQ_TICKEPSILON) tx++, coef = 1000. / stm++->t_sr; for (ex = 0, sev = x->x_sequence; ex < x->x_nevents; ex++, sev++) { double clockdelta = 0.; while (tx < x->x_ntempi && stm->t_scoretime <= sev->e_delta) { clockdelta += (stm->t_scoretime - prevscoretime) * coef; prevscoretime = stm->t_scoretime; tx++; coef = 1000. / stm++->t_sr; } clockdelta += (sev->e_delta - prevscoretime) * coef; prevscoretime = sev->e_delta; sev->e_delta = clockdelta; } } static int seq_mfread(t_seq *x, char *path) { int result = 0; t_mifiread *mr = mifiread_new((t_pd *)x); if (!mifiread_open(mr, path, "", 0)) goto mfreadfailed; #ifdef SEQ_DEBUG loudbug_startpost("midifile (format %d): %d tracks, %d ticks", mifiread_getformat(mr), mifiread_gethdtracks(mr), mifiread_getbeatticks(mr)); if (mifiread_getnframes(mr)) loudbug_post(" (%d smpte frames)", mifiread_getnframes(mr)); else loudbug_post(" per beat"); #endif if (!seq_dogrowing(x, mifiread_getnevents(mr), mifiread_getntempi(mr))) goto mfreadfailed; x->x_eventreadhead = 0; x->x_temporeadhead = 0; if (mifiread_doit(mr, seq_mrhook, x) != MIFIREAD_EOF) goto mfreadfailed; if (x->x_eventreadhead < x->x_nevents) { loudbug_bug("seq_mfread 1"); loudbug_post("declared %d events, got %d", x->x_nevents, x->x_eventreadhead); x->x_nevents = x->x_eventreadhead; } if (x->x_nevents) qsort(x->x_sequence, x->x_nevents, sizeof(*x->x_sequence), seq_eventcomparehook); if (x->x_temporeadhead < x->x_ntempi) { loudbug_bug("seq_mfread 2"); loudbug_post("declared %d tempi, got %d", x->x_ntempi, x->x_temporeadhead); x->x_ntempi = x->x_temporeadhead; } if (x->x_ntempi) qsort(x->x_tempomap, x->x_ntempi, sizeof(*x->x_tempomap), seq_tempocomparehook); seq_foldtime(x, mifiread_getdeftempo(mr)); #ifdef SEQ_DEBUG loudbug_post("seq: got %d events from midi file", x->x_nevents); #endif result = 1; mfreadfailed: mifiread_free(mr); return (result); } static int seq_mfwrite(t_seq *x, char *path) { int result = 0; t_seqevent *sev = x->x_sequence; int nevents = x->x_nevents; t_mifiwrite *mw = mifiwrite_new((t_pd *)x); if (!mifiwrite_open(mw, path, "", 1, 1)) goto mfwritefailed; if (!mifiwrite_opentrack(mw, "seq-track", 1)) goto mfwritefailed; while (nevents--) { unsigned char *bp = sev->e_bytes; unsigned status = *bp & 0xf0; if (status > 127 && status < 240) { if (!mifiwrite_channelevent(mw, sev->e_delta, status, *bp & 0x0f, bp[1], bp[2])) /* SEQ_EOM ignored */ { loud_error((t_pd *)x, "cannot write channel event %d", status); goto mfwritefailed; } } /* FIXME system, sysex (first, and continuation) */ sev++; } if (!mifiwrite_closetrack(mw, 0., 1)) goto mfwritefailed; mifiwrite_close(mw); result = 1; mfwritefailed: if (!result) loud_errand((t_pd *)x, "while saving sequence into midi file \"%s\"", path); mifiwrite_free(mw); return (result); } /* CHECKED text file input: absolute timestamps, semi-terminated, verified */ /* FIXME prevent loading .pd files... */ static int seq_fromatoms(t_seq *x, int ac, t_atom *av, int abstime) { int i, nevents = 0; t_atom *ap; for (i = 0, ap = av; i < ac; i++, ap++) if (ap->a_type == A_SEMI) /* FIXME parsing */ nevents++; if (nevents) { t_seqevent *ep; float prevtime = 0; if (!seq_dogrowing(x, nevents, 0)) return (0); i = -1; nevents = 0; ep = x->x_sequence; while (ac--) { if (av->a_type == A_FLOAT) { if (i < 0) { if (abstime) { ep->e_delta = av->a_w.w_float - prevtime; prevtime = av->a_w.w_float; } else ep->e_delta = av->a_w.w_float; i = 0; } else if (i < 4) ep->e_bytes[i++] = av->a_w.w_float; /* CHECKME else */ } else if (av->a_type == A_SEMI && i > 0) { if (i < 4) ep->e_bytes[i] = SEQ_EOM; nevents++; ep++; i = -1; } /* CHECKME else */ av++; } x->x_nevents = nevents; } return (nevents); } static void seq_tobinbuf(t_seq *x, t_binbuf *bb) { int nevents = x->x_nevents; t_seqevent *ep = x->x_sequence; t_atom at[5]; float timestamp = 0; while (nevents--) { unsigned char *bp = ep->e_bytes; int i; t_atom *ap = at; timestamp += ep->e_delta; SETFLOAT(ap, timestamp); /* CHECKED same for sysex continuation */ ap++; SETFLOAT(ap, *bp); for (i = 0, ap++, bp++; i < 3 && *bp != SEQ_EOM; i++, ap++, bp++) SETFLOAT(ap, *bp); binbuf_add(bb, i + 2, at); binbuf_addsemi(bb); ep++; } } static void seq_textread(t_seq *x, char *path) { t_binbuf *bb; bb = binbuf_new(); if (binbuf_read(bb, path, "", 0)) { /* CHECKED no complaint, open dialog presented */ hammerpanel_open(x->x_filehandle, 0); /* LATER rethink */ } else { int nlines = /* CHECKED absolute timestamps */ seq_fromatoms(x, binbuf_getnatom(bb), binbuf_getvec(bb), 1); if (nlines < 0) /* CHECKED "bad MIDI file (truncated)" alert, even if a text file */ loud_error((t_pd *)x, "bad text file (truncated)"); else if (nlines == 0) { /* CHECKED no complaint, sequence erased, LATER rethink */ } } binbuf_free(bb); } static void seq_textwrite(t_seq *x, char *path) { t_binbuf *bb; bb = binbuf_new(); seq_tobinbuf(x, bb); /* CHECKED empty sequence stored as an empty file */ if (binbuf_write(bb, path, "", 0)) { /* CHECKME complaint and FIXME */ loud_error((t_pd *)x, "error writing text file"); } binbuf_free(bb); } static void seq_doread(t_seq *x, t_symbol *fn, int creation) { char buf[MAXPDSTRING]; /* FIXME use open_via_path() */ if (x->x_canvas) canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } if (creation) { /* loading during object creation -- CHECKED no warning if a file specified with an arg does not exist, LATER rethink */ FILE *fp; char path[MAXPDSTRING]; sys_bashfilename(buf, path); if (!(fp = fopen(path, "r"))) return; fclose(fp); } /* CHECKED all cases: arg or not, message and creation */ post("seq: reading %s", fn->s_name); if (!seq_mfread(x, buf)) seq_textread(x, buf); } static void seq_dowrite(t_seq *x, t_symbol *fn) { char buf[MAXPDSTRING], *dotp; if (x->x_canvas) canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); else { strncpy(buf, fn->s_name, MAXPDSTRING); buf[MAXPDSTRING-1] = 0; } post("seq: writing %s", fn->s_name); /* CHECKED arg or not */ /* save as text for any extension other then ".mid" */ if ((dotp = strrchr(fn->s_name, '.')) && strcmp(dotp + 1, "mid")) seq_textwrite(x, buf); else /* save as mf for ".mid" (FIXME ignore case?) or no extension at all, LATER rethink */ seq_mfwrite(x, buf); } static void seq_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { seq_doread((t_seq *)z, fn, 0); } static void seq_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) { seq_dowrite((t_seq *)z, fn); } static void seq_read(t_seq *x, t_symbol *s) { if (s && s != &s_) seq_doread(x, s, 0); else /* CHECKED no default file name */ /* start in a dir last read from, if any, otherwise in a canvas dir */ hammerpanel_open(x->x_filehandle, 0); } static void seq_write(t_seq *x, t_symbol *s) { if (s && s != &s_) seq_dowrite(x, s); else /* CHECKED creation arg is a default file name */ hammerpanel_save(x->x_filehandle, /* always start in canvas dir */ canvas_getdir(x->x_canvas), x->x_defname); } static void seq_eventstring(t_seq *x, char *buf, t_seqevent *ep, int editable) { unsigned char *bp = ep->e_bytes; int i; if (editable) sprintf(buf, "%g", ep->e_delta); else if (*bp < 128 || *bp == 247) sprintf(buf, "(%g)->", ep->e_delta); else sprintf(buf, "(%g)", ep->e_delta); buf += strlen(buf); sprintf(buf, " %g", (float)*bp); for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++) { buf += strlen(buf); sprintf(buf, " %g", (float)*bp); } } static void seq_print(t_seq *x) { int nevents = x->x_nevents; startpost("midiseq:"); /* CHECKED */ if (nevents) { t_seqevent *ep = x->x_sequence; char buf[MAXPDSTRING+2]; int truncated; if (nevents > 16) nevents = 16, truncated = 1; else truncated = 0; endpost(); while (nevents--) { /* CHECKED bytes are space-separated, no semi */ seq_eventstring(x, buf, ep, 0); post(buf); ep++; } if (truncated) post("..."); /* CHECKED */ } else post(" no sequence"); /* CHECKED */ } static void seq_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) { seq_fromatoms((t_seq *)z, ac, av, 0); } static void seq_click(t_seq *x, t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl, t_floatarg alt) { t_seqevent *ep = x->x_sequence; int nevents = x->x_nevents; char buf[MAXPDSTRING+2]; hammereditor_open(x->x_filehandle, (x->x_defname && x->x_defname != &s_ ? x->x_defname->s_name : ""), 0); while (nevents--) { /* LATER rethink sysex continuation */ seq_eventstring(x, buf, ep, 1); strcat(buf, ";\n"); hammereditor_append(x->x_filehandle, buf); ep++; } hammereditor_setdirty(x->x_filehandle, 0); } static void seq_free(t_seq *x) { if (x->x_clock) clock_free(x->x_clock); if (x->x_slaveclock) clock_free(x->x_slaveclock); if (x->x_filehandle) hammerfile_free(x->x_filehandle); if (x->x_sequence != x->x_seqini) freebytes(x->x_sequence, x->x_seqsize * sizeof(*x->x_sequence)); if (x->x_tempomap != x->x_tempomapini) freebytes(x->x_tempomap, x->x_tempomapsize * sizeof(*x->x_tempomap)); } static void *seq_new(t_symbol *s) { t_seq *x = (t_seq *)pd_new(seq_class); static int warned = 0; if (fittermax_get() && !warned) { loud_warning((t_pd *)x, 0, "seq is not ready yet"); warned = 1; } x->x_canvas = canvas_getcurrent(); x->x_filehandle = hammerfile_new((t_pd *)x, 0, seq_readhook, seq_writehook, seq_editorhook); x->x_timescale = 1.; x->x_newtimescale = 1.; x->x_prevtime = 0.; x->x_slaveprevtime = 0.; x->x_seqsize = SEQ_INISEQSIZE; x->x_nevents = 0; x->x_sequence = x->x_seqini; x->x_tempomapsize = SEQ_INITEMPOMAPSIZE; x->x_ntempi = 0; x->x_tempomap = x->x_tempomapini; outlet_new((t_object *)x, &s_anything); x->x_bangout = outlet_new((t_object *)x, &s_bang); if (s && s != &s_) { x->x_defname = s; /* CHECKME if 'read' changes this */ seq_doread(x, s, 1); } else x->x_defname = &s_; x->x_clock = clock_new(x, (t_method)seq_clocktick); x->x_slaveclock = clock_new(x, (t_method)seq_slaveclocktick); return (x); } void seq_setup(void) { seq_class = class_new(gensym("seq"), (t_newmethod)seq_new, (t_method)seq_free, sizeof(t_seq), 0, A_DEFSYM, 0); class_addbang(seq_class, seq_bang); class_addfloat(seq_class, seq_float); /* CHECKED symbol rejected */ class_addsymbol(seq_class, seq_symbol); /* CHECKED 1st atom of a list accepted if a float, ignored if a symbol */ class_addlist(seq_class, seq_list); class_addmethod(seq_class, (t_method)seq_record, gensym("record"), 0); class_addmethod(seq_class, (t_method)seq_append, gensym("append"), 0); class_addmethod(seq_class, (t_method)seq_start, gensym("start"), A_DEFFLOAT, 0); class_addmethod(seq_class, (t_method)seq_stop, gensym("stop"), 0); class_addmethod(seq_class, (t_method)seq_tick, gensym("tick"), 0); class_addmethod(seq_class, (t_method)seq_delay, gensym("delay"), A_FLOAT, 0); /* CHECKED arg obligatory */ class_addmethod(seq_class, (t_method)seq_hook, gensym("hook"), A_FLOAT, 0); /* CHECKED arg obligatory */ class_addmethod(seq_class, (t_method)seq_read, gensym("read"), A_DEFSYM, 0); class_addmethod(seq_class, (t_method)seq_write, gensym("write"), A_DEFSYM, 0); class_addmethod(seq_class, (t_method)seq_print, gensym("print"), 0); /* incompatible extensions */ class_addmethod(seq_class, (t_method)seq_pause, gensym("pause"), 0); class_addmethod(seq_class, (t_method)seq_continue, gensym("continue"), 0); class_addmethod(seq_class, (t_method)seq_goto, gensym("goto"), A_DEFFLOAT, A_DEFFLOAT, 0); class_addmethod(seq_class, (t_method)seq_scoretime, gensym("scoretime"), A_SYMBOL, 0); class_addmethod(seq_class, (t_method)seq_tempo, gensym("tempo"), A_FLOAT, 0); class_addmethod(seq_class, (t_method)seq_cd, gensym("cd"), A_DEFSYM, 0); class_addmethod(seq_class, (t_method)seq_pwd, gensym("pwd"), A_SYMBOL, 0); class_addmethod(seq_class, (t_method)seq_click, gensym("click"), A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); hammerfile_setup(seq_class, 0); fitter_setup(seq_class, 0); } cyclone-0.1-alpha55/cyclone/hammer/comment.c0000644000076500007650000006026311466617445017461 0ustar hanshans/* Copyright (c) 2002-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ /* FIXME creation lag (X-specific) */ /* LATER think about pushing text to the text editor (ctrl-t) -- not easy, because we are not 'textedfor' */ /* LATER think about making the