diff options
author | N.N. <krzyszcz@users.sourceforge.net> | 2003-09-24 10:46:19 +0000 |
---|---|---|
committer | N.N. <krzyszcz@users.sourceforge.net> | 2003-09-24 10:46:19 +0000 |
commit | 9680b47879dfc58f884208f7abf2f945b3b41d25 (patch) | |
tree | 93eda19deb61daff60c533a3bbd1efe79e9cdc9b /toxy/tot.c | |
parent | edab184352cd14788a37c76dce147ac19f7464b4 (diff) |
adding toxy project
svn path=/trunk/externals/miXed/; revision=1024
Diffstat (limited to 'toxy/tot.c')
-rw-r--r-- | toxy/tot.c | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/toxy/tot.c b/toxy/tot.c new file mode 100644 index 0000000..eced2b2 --- /dev/null +++ b/toxy/tot.c @@ -0,0 +1,530 @@ +/* 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. */ + +/* LATER handle stcriptlet's named arguments */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "hammer/file.h" +#include "hammer/gui.h" +#include "common/props.h" +#include "toxy/scriptlet.h" +#include "build_counter" + +//#define TOT_DEBUG + +/* probably much more than needed for canvas messages from gui */ +#define TOTSPY_MAXSIZE 32 + +typedef struct _tot +{ + t_object x_ob; + t_glist *x_glist; /* containing glist */ + t_symbol *x_cvremote; /* null if containing glist is our destination */ + t_symbol *x_cvname; + t_symbol *x_cvpathname; /* see tot_getpathname() */ + t_symbol *x_visedpathname; /* see tot__vised() */ + t_symbol *x_target; + int x_warned; + t_scriptlet *x_persistent; + t_scriptlet *x_transient; + t_outlet *x_out2; + t_outlet *x_out4; + t_symbol *x_defname; /* file name (if given as a creation arg) */ + t_hammerfile *x_filehandle; + t_pd *x_guidetached; + t_pd *x_guisink; + struct _totspy *x_spy; +} t_tot; + +typedef struct _totspy +{ + t_pd ts_pd; + int ts_on; + t_canvas *ts_cv; + t_symbol *ts_target; + t_symbol *ts_qsym; + double ts_lasttime; + t_symbol *ts_selector; + t_atom ts_outbuf[TOTSPY_MAXSIZE]; + t_outlet *ts_out3; +} t_totspy; + +static t_class *tot_class; +static t_class *totspy_class; +static t_class *totsink_class; +static t_class *tot_guiconnect_class = 0; + +static t_symbol *tot_ps_qpush; +static t_symbol *tot_ps_query; + +static t_canvas *tot_getcanvas(t_tot *x, int complain) +{ + t_canvas *cv = 0; + t_glist *glist = + (x->x_cvremote ? + (t_glist *)pd_findbyclass(x->x_cvremote, canvas_class) : x->x_glist); + if (glist) + cv = glist_getcanvas(glist); + else if (complain) + loud_error((t_pd *)x, "bad canvas name '%s'", x->x_cvname->s_name); + if (!x->x_warned && !x->x_cvremote) + { + x->x_warned = 1; + if (!cv) cv = x->x_glist; /* redundant */ + loud_warning((t_pd *)x, "using containing canvas ('%s')", + cv->gl_name->s_name); + } + return (cv); +} + +static t_canvas *tot_cvhook(t_pd *z) +{ + return (tot_getcanvas((t_tot *)z, 1)); +} + +static t_symbol *tot_dogetpathname(t_tot *x, int visedonly, int complain) +{ + t_canvas *cv = tot_getcanvas(x, complain); + if (cv) + { + if (visedonly && !glist_isvisible(cv)) + return (0); + else if (cv == x->x_glist) + /* containing glist is our destination, and we are not in a gop */ + return (x->x_cvpathname); + else + { + char buf[32]; + sprintf(buf, ".x%x.c", (int)cv); + return (gensym(buf)); + } + } + else return (0); +} + +static t_symbol *tot_getpathname(t_tot *x, int complain) +{ + return (tot_dogetpathname(x, 0, complain)); +} + +static t_symbol *tot_getvisedpathname(t_tot *x, int complain) +{ + return (tot_dogetpathname(x, 1, complain)); +} + +static void tot_reset(t_tot *x) +{ + scriptlet_reset(x->x_persistent); +} + +static void tot_prealloc(t_tot *x, t_floatarg f) +{ + int reqsize = (int)f; + scriptlet_prealloc(x->x_persistent, reqsize, 1); + scriptlet_prealloc(x->x_transient, reqsize, 1); /* LATER rethink */ +} + +static void tot_add(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + scriptlet_add(x->x_persistent, 0, 0, ac, av); +} + +static void tot_addnext(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + scriptlet_setseparator(x->x_persistent, '\n'); + scriptlet_add(x->x_persistent, 0, 0, ac, av); +} + +static void tot_push(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + if (scriptlet_evaluate(x->x_persistent, x->x_transient, 1, ac, av, 0)) + { + if (s == tot_ps_qpush) + scriptlet_qpush(x->x_transient); + else + scriptlet_push(x->x_transient); + } +} + +static void tot_tot(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_scriptlet *sp = x->x_transient; + scriptlet_reset(sp); + scriptlet_add(sp, 1, 1, ac, av); + if (s == tot_ps_query) + scriptlet_qpush(sp); + else + scriptlet_push(sp); + } +} + +static void tot_dooutput(t_tot *x, t_outlet *op, + t_symbol *s, int ac, t_atom *av) +{ + if (ac == 1) + { + if (av->a_type == A_FLOAT) + outlet_float(op, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(op, av->a_w.w_symbol); + } + else if (ac) + { + if (av->a_type == A_FLOAT) + outlet_list(op, &s_list, ac, av); + else if (av->a_type == A_SYMBOL) + outlet_anything(op, av->a_w.w_symbol, ac - 1, av + 1); + } + else outlet_bang(op); +} + +static void tot__reply(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + tot_dooutput(x, ((t_object *)x)->ob_outlet, s, ac, av); +} + +static void tot__callback(t_tot *x, t_symbol *s, int ac, t_atom *av) +{ + tot_dooutput(x, x->x_out2, s, ac, av); +} + +/* LATER use properties in widgetbehavior (if gop visibility rules change) */ +static void tot_click(t_tot *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + int nleft; + char *head = scriptlet_getcontents(x->x_persistent, &nleft); + char buf[MAXPDSTRING + 1]; + buf[MAXPDSTRING] = 0; + hammereditor_open(x->x_filehandle, "scriptlet editor"); + while (nleft > 0) + { + if (nleft > MAXPDSTRING) + { + strncpy(buf, head, MAXPDSTRING); + head += MAXPDSTRING; + nleft -= MAXPDSTRING; + } + else + { + strncpy(buf, head, nleft); + buf[nleft] = 0; + nleft = 0; + } + hammereditor_append(x->x_filehandle, buf); + } +} + +/* This is called for all Map (f==1) and all Destroy (f==0) events, + comming from any canvas. If visedpathname is zero, we assume our + canvas does not exist. So we ignore everything, waiting for a Map + event that fits tot_getpathname(). Once we spot it, we set + visedpathname, and ignore everything, waiting for a Destroy event + that fits visedpathname. Then we clear visedpathname, etc... */ +static void tot__vised(t_tot *x, t_symbol *s, t_floatarg f) +{ + int flag = f != 0.; +#ifdef TOT_DEBUG + t_symbol *pn = tot_getpathname(x, 0); + post("tot__vised %s %g (pathname %s) ", s->s_name, f, + (pn ? pn->s_name : "unknown")); +#endif + if (!x->x_visedpathname) + { + if (flag && s == tot_getpathname(x, 0)) + { + x->x_visedpathname = s; + outlet_bang(x->x_out4); + } + } + else if (!flag && s == x->x_visedpathname) + x->x_visedpathname = 0; /* LATER reconsider reporting this */ +} + +#ifdef TOT_DEBUG +static void tot_debug(t_tot *x) +{ + t_symbol *pn = tot_getpathname(x, 0); + int sz; + char *bp; + post("containing glist: %x", x->x_glist); + post("destination: %s", x->x_cvname->s_name); + post("pathname%s %s", (pn ? ":" : ""), (pn ? pn->s_name : "unknown")); + bp = scriptlet_getbuffer(x->x_transient, &sz); + post("transient buffer (size %d):\n\"%s\"", sz, bp); + bp = scriptlet_getbuffer(x->x_persistent, &sz); + post("persistent buffer (size %d):\n\"%s\"", sz, bp); +} +#endif + +static void tot_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_read(((t_tot *)z)->x_persistent, fn); +} + +static void tot_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + scriptlet_write(((t_tot *)z)->x_persistent, fn); +} + +static void tot_read(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_read(x->x_persistent, s); + else + hammerpanel_open(x->x_filehandle, 0); +} + +static void tot_write(t_tot *x, t_symbol *s) +{ + if (s && s != &s_) + scriptlet_write(x->x_persistent, s); + else + hammerpanel_save(x->x_filehandle, + canvas_getdir(x->x_glist), x->x_defname); +} + +static void tot_detach(t_tot *x) +{ + t_canvas *cv = tot_getcanvas(x, 1); + if (cv && glist_isvisible(cv)) + { + t_pd *gc; + t_symbol *target; + char buf[64]; + sprintf(buf, ".x%x", (int)cv); + target = gensym(buf); + if (!tot_guiconnect_class) + { + gc = (t_pd *)guiconnect_new(0, gensym("tot")); + tot_guiconnect_class = *gc; + typedmess(gc, gensym("signoff"), 0, 0); + } + if (gc = pd_findbyclass(target, tot_guiconnect_class)) + { + x->x_guidetached = gc; + pd_unbind(gc, target); + pd_bind(x->x_guisink, target); + } + } +} + +static void tot_attach(t_tot *x) +{ + t_canvas *cv = tot_getcanvas(x, 1); + if (cv && glist_isvisible(cv) && x->x_guidetached) + { + if (tot_guiconnect_class) + { + t_pd *gc; + t_symbol *target; + char buf[64]; + sprintf(buf, ".x%x", (int)cv); + target = gensym(buf); + if (gc = pd_findbyclass(target, tot_guiconnect_class)) + { + } + else + { /* assuming nobody else detached it in the meantime... */ + pd_unbind(x->x_guisink, target); + pd_bind(x->x_guidetached, target); + x->x_guidetached = 0; + } + } + else bug("tot_attach"); + } +} + +static void tot_capture(t_tot *x, t_symbol *s, t_floatarg f) +{ + t_totspy *ts = x->x_spy; + if ((int)f) + { + t_canvas *cv = tot_getcanvas(x, 1); + ts->ts_qsym = (s == &s_ ? 0 : s); + if (cv != ts->ts_cv) + { + if (ts->ts_target) + { + pd_unbind((t_pd *)ts, ts->ts_target); + ts->ts_cv = 0; + ts->ts_target = 0; + } + if (cv) + { + char buf[64]; + ts->ts_cv = cv; + sprintf(buf, ".x%x", (int)cv); + pd_bind((t_pd *)ts, ts->ts_target = gensym(buf)); + } + } + ts->ts_on = (ts->ts_target != 0); + if (ts->ts_on && ts->ts_qsym) + { + ts->ts_lasttime = clock_getlogicaltime(); + ts->ts_selector = gensym("add"); + SETFLOAT(&ts->ts_outbuf[0], 0); + SETSYMBOL(&ts->ts_outbuf[1], ts->ts_qsym); + SETSYMBOL(&ts->ts_outbuf[2], &s_); + outlet_anything(ts->ts_out3, gensym("clear"), 0, 0); + } + } + else ts->ts_on = 0; +} + +static void totspy_anything(t_totspy *ts, t_symbol *s, int ac, t_atom *av) +{ + if (ts->ts_on) + { + if (ts->ts_qsym) + { + int cnt = ac + 3; + if (cnt < TOTSPY_MAXSIZE) + { + t_atom *ap = ts->ts_outbuf; + ap++->a_w.w_float = (float)clock_gettimesince(ts->ts_lasttime); + ap++; + ap++->a_w.w_symbol = s; + while (ac--) *ap++ = *av++; + outlet_anything(ts->ts_out3, + ts->ts_selector, cnt, ts->ts_outbuf); + ts->ts_lasttime = clock_getlogicaltime(); + } + else loud_warning((t_pd *)ts, + "unexpectedly long message (\"%s...\"), ignored", + s->s_name); + } + else outlet_anything(ts->ts_out3, s, ac, av); + } +} + +static void totsink_anything(t_pd *x, t_symbol *s, int ac, t_atom *av) +{ + /* nop */ +} + +static void tot_free(t_tot *x) +{ + pd_unbind((t_pd *)x, x->x_target); + hammergui_unbindvised((t_pd *)x); + hammerfile_free(x->x_filehandle); + scriptlet_free(x->x_persistent); + scriptlet_free(x->x_transient); + if (x->x_spy->ts_target) + pd_unbind((t_pd *)x->x_spy, x->x_spy->ts_target); + pd_free((t_pd *)x->x_spy); + pd_free(x->x_guisink); +} + +static void *tot_new(t_symbol *s1, t_symbol *s2) +{ + t_tot *x = (t_tot *)pd_new(tot_class); + char buf[64]; + sprintf(buf, "tot%x", (int)x); + pd_bind((t_pd *)x, x->x_target = gensym(buf)); + x->x_transient = + scriptlet_new((t_pd *)x, x->x_target, x->x_target, 0, tot_cvhook); + x->x_persistent = + scriptlet_new((t_pd *)x, x->x_target, x->x_target, 0, tot_cvhook); + x->x_glist = canvas_getcurrent(); + if (s1 && s1 != &s_ && strcmp(s1->s_name, ".")) + { + x->x_cvremote = canvas_makebindsym(x->x_cvname = s1); + x->x_cvpathname = 0; + } + else + { + x->x_warned = (s1 && *s1->s_name == '.'); /* do not warn if explicit */ + x->x_cvremote = 0; + x->x_cvname = x->x_glist->gl_name; + sprintf(buf, ".x%x.c", (int)x->x_glist); + x->x_cvpathname = gensym(buf); + } + outlet_new((t_object *)x, &s_anything); + x->x_out2 = outlet_new((t_object *)x, &s_anything); + x->x_spy = (t_totspy *)pd_new(totspy_class); + x->x_spy->ts_on = 0; + x->x_spy->ts_cv = 0; + x->x_spy->ts_target = 0; + x->x_spy->ts_qsym = 0; + x->x_spy->ts_out3 = outlet_new((t_object *)x, &s_anything); + x->x_out4 = outlet_new((t_object *)x, &s_bang); + if (s2 && s2 != &s_) + { + x->x_defname = s2; + scriptlet_read(x->x_persistent, s2); + } + else x->x_defname = &s_; + x->x_filehandle = hammerfile_new((t_pd *)x, 0, + tot_readhook, tot_writehook, 0); + hammergui_bindvised((t_pd *)x); + x->x_visedpathname = tot_getvisedpathname(x, 0); + x->x_guidetached = 0; + x->x_guisink = pd_new(totsink_class); + return (x); +} + +void tot_setup(void) +{ + post("beware! this is tot %s, %s %s build...", + TOXY_VERSION, loud_ordinal(TOXY_BUILD), TOXY_RELEASE); + tot_ps_qpush = gensym("qpush"); + tot_ps_query = gensym("query"); + tot_class = class_new(gensym("tot"), + (t_newmethod)tot_new, + (t_method)tot_free, + sizeof(t_tot), 0, A_DEFSYM, A_DEFSYM, 0); + class_addmethod(tot_class, (t_method)tot_prealloc, + gensym("prealloc"), A_FLOAT, 0); + class_addmethod(tot_class, (t_method)tot_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(tot_class, (t_method)tot_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(tot_class, (t_method)tot_reset, + gensym("reset"), 0); + class_addmethod(tot_class, (t_method)tot_push, + gensym("push"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_push, + gensym("qpush"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_add, + gensym("add"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_addnext, + gensym("addnext"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_tot, + gensym("tot"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_tot, + gensym("query"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_detach, + gensym("detach"), 0); + class_addmethod(tot_class, (t_method)tot_attach, + gensym("attach"), 0); + class_addmethod(tot_class, (t_method)tot_capture, + gensym("capture"), A_FLOAT, A_DEFSYM, 0); + class_addmethod(tot_class, (t_method)tot__reply, + gensym("_rp"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot__callback, + gensym("_cb"), A_GIMME, 0); + class_addmethod(tot_class, (t_method)tot_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(tot_class, (t_method)tot__vised, + gensym("_vised"), A_SYMBOL, A_FLOAT, 0); +#ifdef TOT_DEBUG + class_addmethod(tot_class, (t_method)tot_debug, + gensym("debug"), 0); +#endif + hammerfile_setup(tot_class, 0); + totspy_class = class_new(gensym("tot spy"), 0, 0, + sizeof(t_totspy), CLASS_PD, 0); + class_addanything(totspy_class, totspy_anything); + totsink_class = class_new(gensym("tot sink"), 0, 0, + sizeof(t_pd), CLASS_PD, 0); + class_addanything(totsink_class, totsink_anything); +} |