aboutsummaryrefslogtreecommitdiff
path: root/toxy/tot.c
diff options
context:
space:
mode:
authorN.N. <krzyszcz@users.sourceforge.net>2003-09-24 10:46:19 +0000
committerN.N. <krzyszcz@users.sourceforge.net>2003-09-24 10:46:19 +0000
commit9680b47879dfc58f884208f7abf2f945b3b41d25 (patch)
tree93eda19deb61daff60c533a3bbd1efe79e9cdc9b /toxy/tot.c
parentedab184352cd14788a37c76dce147ac19f7464b4 (diff)
adding toxy project
svn path=/trunk/externals/miXed/; revision=1024
Diffstat (limited to 'toxy/tot.c')
-rw-r--r--toxy/tot.c530
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);
+}