aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas O Fredericks <mrtof@users.sourceforge.net>2008-03-31 15:41:33 +0000
committerThomas O Fredericks <mrtof@users.sourceforge.net>2008-03-31 15:41:33 +0000
commitbbde9edb23856238349150fd1038d3a540a2bd15 (patch)
treef988c12bb9cc9887a8de66246df1cba092cc3f8d
parent906c8c819e6089dcdde1925e82bdb88a10c3a5b1 (diff)
Added breakpoint and breakpoints to tof externals
svn path=/trunk/externals/tof/; revision=9639
-rwxr-xr-xhelp/breakpoints-help.pd86
-rwxr-xr-xhelp/breakpoints~-help.pd54
-rwxr-xr-xsrc/Makefile61
-rwxr-xr-xsrc/breakpoints.c449
-rwxr-xr-xsrc/breakpoints~.c479
-rwxr-xr-xsrc/breakpoints~.h63
-rwxr-xr-xsrc/g_canvas.h615
-rwxr-xr-xsrc/w_breakpoints.h569
8 files changed, 2376 insertions, 0 deletions
diff --git a/help/breakpoints-help.pd b/help/breakpoints-help.pd
new file mode 100755
index 0000000..e287bba
--- /dev/null
+++ b/help/breakpoints-help.pd
@@ -0,0 +1,86 @@
+#N canvas 1047 72 917 561 10;
+#X obj 89 148 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 31 251 breakpoints;
+#X obj 29 452 line~;
+#X obj 29 497 snapshot~;
+#X obj 75 447 loadbang;
+#X obj 75 471 metro 100;
+#X obj 29 529 nbx 5 28 -1e+037 1e+037 0 0 empty empty empty 0 -8 0
+22 -262144 -1 -1 0 256;
+#X msg 29 114 0 1125 0.671429 300 0.557143 700 0.571429 0 0.792857
+375 1 100 0.0857143 1250 0.492857 1150 0;
+#X obj 29 78 loadbang;
+#X obj 23 48 cnv 15 15 15 empty empty empty 20 12 0 14 -258113 -66577
+0;
+#X obj 509 45 cnv 15 15 15 empty empty empty 20 12 0 14 -258113 -66577
+0;
+#X text 525 43 Creation arguments;
+#X text 506 115 The following breakpoints was created with this line:
+breakpoints 100 50 3000 \$0r \$0s \$0d;
+#X obj 511 189 breakpoints 100 50 3000 \$0r \$0s \$0d;
+#X obj 694 176 r \$0s;
+#X obj 639 176 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X msg 640 224 dump;
+#X obj 696 224 r \$0d;
+#X obj 639 197 s \$0r;
+#X obj 640 246 s \$0r;
+#X text 639 150 The beakpoints can now be controlld remotely:;
+#X text 28 12 Description: A graphical breakpoint envelope generator
+based on envgen by ggee.;
+#X msg 110 175 duration 5000;
+#X text 39 42 Breakpoints delivers values for line or line~ when it
+is banged.;
+#X obj 189 452 line;
+#X obj 189 526 nbx 5 28 -1e+037 1e+037 0 0 empty empty empty 0 -8 0
+22 -262144 -1 -1 0 256;
+#X text 112 147 Deliver the point data to a line or line~;
+#X text 90 68 You can set the point data by sending a list with the
+following format: initialValue delay1 value1 delay2 value2 ...;
+#X msg 567 340 -1 500 3 100 -5;
+#X floatatom 516 284 5 0 600 0 - - -;
+#X obj 518 377 breakpoints 200 100;
+#X obj 567 312 loadbang;
+#X floatatom 516 493 5 0 0 0 - - -;
+#X text 554 279 By sending a float you can get the an interpolated
+point value for the corresponding duration.;
+#X text 673 339 Total duration is 600 (500+100);
+#X obj 715 499 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X msg 104 209 dump;
+#X text 144 208 Dump the current point data out the second outlet;
+#X obj 128 403 print DUMP;
+#X msg 272 267 1 100 -5;
+#X text 507 64 width height duration receive_symbol send_symbol dump_symbol
+change_symbol;
+#X obj 694 196 print data;
+#X obj 696 249 print dump;
+#X text 198 175 set the total duration in milliseconds;
+#X obj 228 403 bng 15 250 50 0 empty empty Change 17 7 0 10 -262144
+-1 -1;
+#X text 228 418 Bangs when gui is used.;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 1 0 24 0;
+#X connect 1 1 38 0;
+#X connect 1 2 44 0;
+#X connect 2 0 3 0;
+#X connect 3 0 6 0;
+#X connect 4 0 5 0;
+#X connect 5 0 3 0;
+#X connect 7 0 1 0;
+#X connect 8 0 7 0;
+#X connect 14 0 41 0;
+#X connect 15 0 18 0;
+#X connect 16 0 19 0;
+#X connect 17 0 42 0;
+#X connect 22 0 1 0;
+#X connect 24 0 25 0;
+#X connect 28 0 30 0;
+#X connect 29 0 30 0;
+#X connect 30 0 32 0;
+#X connect 30 2 35 0;
+#X connect 31 0 28 0;
+#X connect 36 0 1 0;
+#X connect 39 0 1 0;
diff --git a/help/breakpoints~-help.pd b/help/breakpoints~-help.pd
new file mode 100755
index 0000000..6415a69
--- /dev/null
+++ b/help/breakpoints~-help.pd
@@ -0,0 +1,54 @@
+#N canvas 10 20 849 503 10;
+#X floatatom 23 59 5 0 0 0 - - -;
+#X obj 18 447 dac~;
+#X obj 223 359 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+-1 -1;
+#X obj 440 208 cnv 15 15 15 empty empty empty 20 12 0 14 -258113 -66577
+0;
+#X text 456 206 Creation arguments;
+#X text 435 226 width height duration receive_symbol dump_symbol change_symbol
+;
+#X msg 575 330 dump;
+#X obj 629 379 r \$0d;
+#X obj 575 352 s \$0r;
+#X text 572 305 The beakpoints can now be controlld remotely:;
+#X text 439 270 The following breakpoints was created with this line:
+breakpoints~ 100 50 3000 \$0r \$0d \$0c;
+#X obj 629 403 print dump;
+#X obj 446 325 breakpoints~ 100 50 3000 \$0r \$0d \$0c;
+#X obj 26 204 breakpoints~;
+#X obj 627 331 r \$0c;
+#X obj 627 352 print change;
+#X obj 129 54 loadbang;
+#X text 131 97 You can set the point data by sending a list with the
+following format: initialValue delay1 value1 delay2 value2 ...;
+#X msg 129 78 0 50 1 50 -1 50 0;
+#X obj 24 126 *~ 150;
+#X obj 25 404 *~ 0.1;
+#X obj 61 381 hsl 128 15 0 1 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 0 1;
+#X text 28 7 Description: A signal~ graphical breakpoint envelope generator
+(based on envgen by ggee).;
+#X obj 23 101 phasor~ 200;
+#X msg 132 146 duration 150;
+#X text 220 146 set the total duration in milliseconds;
+#X msg 137 171 dump;
+#X text 177 170 Dump the current point data out the second outlet;
+#X text 220 374 Bangs when gui is changed;
+#X obj 123 356 print DUMP;
+#X connect 0 0 23 0;
+#X connect 6 0 8 0;
+#X connect 7 0 11 0;
+#X connect 13 0 20 0;
+#X connect 13 1 29 0;
+#X connect 13 2 2 0;
+#X connect 14 0 15 0;
+#X connect 16 0 18 0;
+#X connect 18 0 13 0;
+#X connect 19 0 13 0;
+#X connect 20 0 1 0;
+#X connect 20 0 1 1;
+#X connect 21 0 20 1;
+#X connect 23 0 19 0;
+#X connect 24 0 13 0;
+#X connect 26 0 13 0;
diff --git a/src/Makefile b/src/Makefile
new file mode 100755
index 0000000..cf2829c
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,61 @@
+current:
+ echo make pd_linux, pd_win, or pd_darwin
+
+clean: ; rm -f *.pd_linux *.o
+
+# ----------------------- WINDOWS -----------------------
+
+pd_win: breakpoints.dll breakpoints~.dll destroysend.dll folderpanel.dll getdollarzero.dll
+
+.SUFFIXES: .dll
+
+WINCFLAGS = -Wall -W -Wshadow -Wstrict-prototypes -DPD -DNT -W3 -WX -Wno-unused -mms-bitfields -Wno-parentheses -Wno-switch -O6 -funroll-loops -fomit-frame-pointer
+
+WINPDPATH = /d/pd/bin
+
+WININCLUDE = -I.. -I../include -I$(WINPDPATH)/src
+
+LDFLAGS = -shared
+
+.c.dll:
+ gcc -mms-bitfields $(WINCFLAGS) $(WININCLUDE) -o $*.o -c $*.c
+ gcc $(LDFLAGS) -o $*.dll $*.o $(WINPDPATH)/bin/pd.dll
+ strip --strip-unneeded $*.dll
+ rm -f $*.o
+
+
+
+# ----------------------- LINUX i386 -----------------------
+
+pd_linux: breakpoints.pd_linux breakpoints~.pd_linux destroysend.pd_linux folderpanel.pd_linux getdollarzero.pd_linux
+
+.SUFFIXES: .pd_linux
+
+PDPATH = /home/tom/pd/cvs/pd
+
+LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \
+ -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+LINUXINCLUDE = -I$(PDPATH)/src
+
+.c.pd_linux:
+ cc $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ ld -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
+ strip --strip-unneeded $*.pd_linux
+ rm $*.o
+
+# ----------------------- Mac OSX -----------------------
+
+pd_darwin: breakpoints~.pd_darwin breakpoints.pd_darwin destroysend.pd_darwin folderpanel.pd_darwin getdollarzero.pd_darwin
+
+.SUFFIXES: .pd_darwin
+
+DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
+ -Wno-unused -Wno-parentheses -Wno-switch
+
+.c.pd_darwin:
+ cc $(DARWINCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+ cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $*.o
+ rm -f $*.o
+
diff --git a/src/breakpoints.c b/src/breakpoints.c
new file mode 100755
index 0000000..d98753d
--- /dev/null
+++ b/src/breakpoints.c
@@ -0,0 +1,449 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+#include <m_pd.h>
+
+//#define DEBUG
+/* ------------------------ breakpoints~ ----------------------------- */
+
+#define NONE 0
+#define ATTACK 1
+#define SUSTAIN -1
+#define STATES 100
+
+
+
+#include "breakpoints~.h"
+
+#define BACKGROUNDWIDTH "1"
+#include "w_breakpoints.h"
+
+static t_class *breakpoints_class;
+
+
+#define OUT_LIST(x,nr,a) \
+ outlet_list(x->x_obj.ob_outlet,&s_list,nr,(t_atom*)&a);\
+ if (x->s_sym != &s_ && x->s_sym->s_thing) pd_list(x->s_sym->s_thing, &s_list, nr, (t_atom*)&a);
+
+
+char dumpy[2000];
+
+/* initialize envelope with argument vector */
+
+#include <stdio.h>
+
+/*
+ breakpoints crashes frequently when reallocating memory ....
+ I really don't know why, it crashes during resizebytes,
+ which means it is unable to realloc() the memory ?????
+ the pointer seems to be ok, I don't know what else could
+ cause the problem. for the moment we prevent from reallocating
+ by setting the STATES variable to 100 */
+
+void breakpoints_resize(t_breakpoints* x,int ns)
+{
+ if (ns > x->args) {
+ int newargs = ns*sizeof(t_float);
+
+ x->duration = resizebytes(x->duration,x->args*sizeof(t_float),newargs);
+ x->finalvalues = resizebytes(x->finalvalues,x->args*sizeof(t_float),newargs);
+ x->args = ns;
+ }
+}
+
+
+
+void breakpoints_totaldur(t_breakpoints* x,t_float dur)
+{
+ int i;
+ float f = dur/x->duration[x->last_state];
+
+ if (dur < 10) {
+ post("breakpoints: duration too small %f",dur);
+ return;
+ }
+
+ for (i=1;i<=x->last_state;i++)
+ x->duration[i]*=f;
+}
+
+
+static void breakpoints_dump(t_breakpoints* e)
+{
+ t_atom argv[50];
+ int argc= 0;
+ t_atom* a = argv;
+ int i;
+
+ SETFLOAT(a,e->finalvalues[0]);argc++;
+ for (i=1;i <= e->last_state;i++) {
+ SETFLOAT(argv+argc,e->duration[i] - e->duration[i-1]);
+ argc++;
+ SETFLOAT(argv+argc,e->finalvalues[i]);
+ argc++;
+ }
+ outlet_list(e->out2,&s_list,argc,(t_atom*)&argv);
+ if (e->d_sym != &s_) pd_list(e->d_sym->s_thing, &s_list, argc, argv);
+ //pd_float(x->s_sym->s_thing, val);
+ //EXTERN void pd_float(t_pd *x, t_float f);
+ //EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
+ //EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+ /////////////////////////////////////////////////////
+}
+
+void breakpoints_init(t_breakpoints *x,int argc,t_atom* argv)
+{
+ t_float* dur;
+ t_float* val;
+ t_float tdur = 0;
+
+ if (!argc) return;
+
+ x->duration[0] = 0;
+
+ x->last_state = argc>>1;
+ breakpoints_resize(x,argc>>1);
+
+ dur = x->duration;
+ val = x->finalvalues;
+
+ // get the first value
+ if (argc) {
+ *val = atom_getfloat(argv++);
+ *dur = 0.0;
+ x->max = *val;
+ x->min = *val;
+ }
+ dur++;val++;argc--;
+ // get the following
+ for (;argc > 0;argc--) {
+ tdur += atom_getfloat(argv++);
+#ifdef DEBUG
+ post("dur =%f",tdur);
+#endif
+ *dur++ = tdur;
+ argc--;
+ if (argc > 0) {
+ *val = atom_getfloat(argv++);
+ if (*val > x->max ) x->max = *val;
+ if (*val < x->min ) x->min = *val;
+ *val++;
+ } else {
+ *val = 0;
+ if (*val > x->max ) x->max = *val;
+ if (*val < x->min ) x->min = *val;
+ *val++;
+ }
+#ifdef DEBUG
+ post("val =%f",*(val-1));
+#endif
+
+ }
+
+
+
+ if ( x->max == x->min ) {
+ if ( x->max == 0 ) {
+ x->max = 1;
+ } else {
+ if (x->max > 0) {
+ x->min = 0;
+ } else {
+ x->max = 0;
+ }
+ }
+ }
+
+}
+
+
+
+
+
+void breakpoints_list(t_breakpoints *x,t_symbol* s, int argc,t_atom* argv)
+{
+ breakpoints_init(x,argc,argv);
+ if (glist_isvisible(x->w.glist)) {
+ breakpoints_drawme(x, x->w.glist, 0);
+ }
+}
+
+void breakpoints_setresize(t_breakpoints *x, t_floatarg f)
+{
+ x->resizeable = f;
+}
+
+
+
+
+
+void breakpoints_float(t_breakpoints *x, t_floatarg f)
+{
+ int state = 0;
+ float val;
+
+
+
+ while (x->duration[state] < f && state < x->last_state) state++;
+
+ if (state == 0 || f >= x->duration[x->last_state]) {
+ val = x->finalvalues[state];
+ outlet_float(x->x_obj.ob_outlet,val);
+ if (x->s_sym != &s_) pd_float(x->s_sym->s_thing, f);
+ return;
+ }
+
+ val = x->finalvalues[state-1] +
+ (f - x->duration[state-1])*
+ (x->finalvalues[state] - x->finalvalues[state-1])/
+ (x->duration[state] - x->duration[state-1]);
+
+ //val *= (x->max - x->min);
+ outlet_float(x->x_obj.ob_outlet,val);
+ if (x->s_sym != &s_) pd_float(x->s_sym->s_thing, val);
+}
+
+
+
+void breakpoints_bang(t_breakpoints *x)
+{
+ t_atom a[2];
+
+ SETFLOAT(a,x->finalvalues[NONE]);
+ SETFLOAT(a+1,0);
+
+ OUT_LIST(x,2,a);
+
+ // we don't force the first value anymore, so the first value
+ //is actually with what we have left off at the end ...
+ //this reduces clicks
+
+ x->x_state = ATTACK;
+ x->x_val = x->finalvalues[NONE];
+
+ SETFLOAT(a,x->finalvalues[x->x_state]);
+ SETFLOAT(a+1,x->duration[x->x_state]);
+
+ OUT_LIST(x,2,a);
+ clock_delay(x->x_clock,x->duration[x->x_state]);
+}
+
+/*
+
+void breakpoints_release(t_breakpoints* x) {
+ t_atom a[2];
+ float del = x->duration[x->x_state] - x->duration[x->x_state-1];
+ if (x->x_state <= x->sustain_state) {
+ x->x_state = x->sustain_state+1; // skip sustain state
+ clock_delay(x->x_clock,del);
+ SETFLOAT(a,x->finalvalues[x->x_state]*(x->max-x->min));
+ SETFLOAT(a+1,del);
+ OUT_LIST(x,2,a);
+ }
+}
+
+static void breakpoints_sustain(t_breakpoints *x, t_floatarg f)
+{
+ if (f > 0 && f < x->last_state)
+ x->sustain_state = f;
+ else
+ pd_error(x,"sustain value not betweem 0 and %f, ignoring message", x->last_state);
+}
+
+*/
+
+
+static void breakpoints_tick(t_breakpoints* x)
+{
+ t_atom a[2];
+ x->x_state++;
+ if (x->x_state <= x->last_state && x->x_state != x->sustain_state) {
+ float del = x->duration[x->x_state] - x->duration[x->x_state-1];
+ clock_delay(x->x_clock,del);
+ SETFLOAT(a,x->finalvalues[x->x_state]);
+ SETFLOAT(a+1,del);
+ OUT_LIST(x,2,a);
+ }
+// else
+// clock_unset(x->x_clock);
+}
+
+
+
+/*
+static void breakpoints_freeze(t_breakpoints* x, t_floatarg f)
+{
+ x->x_freeze = f;
+}
+*/
+
+static void bindsym(t_pd* x,t_symbol* o,t_symbol* s)
+{
+ if (o != &s_) pd_unbind(x,o);
+ o = s;
+ pd_bind(x,s);
+}
+
+
+
+
+
+
+
+
+
+static void *breakpoints_new(t_symbol *s,int argc,t_atom* argv)
+{
+ t_breakpoints *x = (t_breakpoints *)pd_new(breakpoints_class);
+
+
+
+ x->x_f = 0;
+ x->args = STATES;
+ x->finalvalues = getbytes( x->args*sizeof(t_float));
+ x->duration = getbytes( x->args*sizeof(t_float));
+#ifdef DEBUG
+ post("finalvalues %x",x->finalvalues);
+#endif
+ /* widget */
+
+ x->w.grabbed = 0;
+ x->resizing = 0;
+ x->resizeable = 0;
+ x->w.glist = (t_glist*) canvas_getcurrent();
+
+ x->w.width = 200;
+ if (argc) x->w.width = atom_getfloat(argv++),argc--;
+ x->w.height = 140;
+ if (argc) x->w.height = atom_getfloat(argv++),argc--;
+
+ t_float initialDuration = 100;
+ if (argc) initialDuration = atom_getfloat(argv++),argc--;
+
+ x->r_sym = &s_;
+ if (argc) {
+ t_symbol* n;
+
+ n = atom_getsymbol(argv++);
+ bindsym(&x->x_obj.ob_pd,x->r_sym,n);
+ x->r_sym = n;
+ argc--;
+ }
+ #ifdef DEBUG
+ post("recv %s",x->r_sym->s_name);
+#endif
+ x->s_sym = &s_;
+ if (argc) x->s_sym = atom_getsymbol(argv++),argc--;
+ #ifdef DEBUG
+ post("send %s",x->s_sym->s_name);
+ #endif
+ x->d_sym = &s_;
+ if (argc) x->d_sym = atom_getsymbol(argv++),argc--;
+ #ifdef DEBUG
+ post("send %s",x->d_sym->s_name);
+ #endif
+
+ x->c_sym = &s_;
+ if (argc) x->c_sym = atom_getsymbol(argv++),argc--;
+ #ifdef DEBUG
+ post("change %s",x->d_sym->s_name);
+ #endif
+
+ if (argc>2)
+ breakpoints_init(x,argc,argv);
+ else {
+ t_atom a[5];
+ SETFLOAT(a,0);
+ SETFLOAT(a+1,50);
+ SETFLOAT(a+2,1);
+ SETFLOAT(a+3,50);
+ SETFLOAT(a+4,0);
+ breakpoints_init(x,5,a);
+ }
+
+ x->x_val = 0.0;
+ x->x_state = NONE;
+ x->sustain_state = SUSTAIN;
+ x->x_freeze = 0;
+
+
+ breakpoints_totaldur(x,initialDuration);
+
+
+ //outlet_new(&x->x_obj, gensym("signal"));
+ outlet_new(&x->x_obj, &s_float);
+ x->out2 = outlet_new(&x->x_obj, &s_float);
+ x->out3 = outlet_new(&x->x_obj, &s_bang);
+
+ x->x_clock = clock_new(x, (t_method) breakpoints_tick);
+ return (x);
+}
+
+
+void breakpoints_motion(t_breakpoints *x, t_floatarg dx, t_floatarg dy);
+void breakpoints_click(t_breakpoints *x,
+ t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
+ t_floatarg alt);
+void breakpoints_key(t_breakpoints *x, t_floatarg f);
+
+t_widgetbehavior breakpoints_widgetbehavior;
+
+
+static void breakpoints_free(t_breakpoints *x) {
+
+
+ if (x->r_sym != &s_) pd_unbind(&x->x_obj.ob_pd, x->r_sym);
+
+}
+
+void breakpoints_setup(void)
+{
+ breakpoints_class = class_new(gensym("breakpoints"), (t_newmethod)breakpoints_new, (t_method)breakpoints_free,
+ sizeof(t_breakpoints), 0,A_GIMME,0);
+
+ //CLASS_MAINSIGNALIN(breakpoints_class, t_breakpoints, x_f);
+ /* here we tell Pd about the "dsp" method, which is called back
+ when DSP is turned on. */
+ //class_addmethod(breakpoints_class, (t_method)breakpointssig_dsp, gensym("dsp"), 0);
+
+
+ //class_addcreator((t_newmethod)breakpoints_new,gensym("breakpoints~"),A_GIMME,0);
+
+ class_addfloat(breakpoints_class, breakpoints_float);
+
+ class_addbang(breakpoints_class,breakpoints_bang);
+ class_addlist(breakpoints_class,breakpoints_list);
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_sustain,gensym("sustain"),A_FLOAT,A_NULL);
+
+ class_addmethod(breakpoints_class, (t_method)breakpoints_motion, gensym("motion"),A_FLOAT, A_FLOAT, 0);
+ class_addmethod(breakpoints_class, (t_method)breakpoints_key, gensym("key"),
+ A_FLOAT, 0);
+
+ class_addmethod(breakpoints_class,(t_method)breakpoints_totaldur,gensym("duration"),A_FLOAT,NULL);
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_freeze,gensym("freeze"),A_FLOAT,NULL);
+ class_addmethod(breakpoints_class,(t_method)breakpoints_setresize,gensym("resize"),A_FLOAT,A_NULL);
+
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_release,gensym("release"),A_NULL);
+ breakpoints_widgetbehavior.w_getrectfn = breakpoints_getrect;
+ breakpoints_widgetbehavior.w_displacefn = breakpoints_displace;
+ breakpoints_widgetbehavior.w_selectfn = breakpoints_select;
+ breakpoints_widgetbehavior.w_activatefn = breakpoints_activate;
+ breakpoints_widgetbehavior.w_deletefn = breakpoints_delete;
+ breakpoints_widgetbehavior.w_visfn = breakpoints_vis;
+ breakpoints_widgetbehavior.w_clickfn = (t_clickfn) breakpoints_newclick;
+ //breakpoints_widgetbehavior.w_clickfn = NULL;
+#if PD_MINOR_VERSION < 37
+ breakpoints_widgetbehavior.w_propertiesfn = NULL;
+ //breakpoints_widgetbehavior.w_savefn = breakpoints_save;
+ breakpoints_widgetbehavior.w_savefn = NULL;
+#endif
+
+ class_setwidget(breakpoints_class,&breakpoints_widgetbehavior);
+#if PD_MINOR_VERSION >= 37
+ //class_setsavefn(breakpoints_class,&breakpoints_save);
+#endif
+ class_addmethod(breakpoints_class,(t_method)breakpoints_dump,gensym("dump"),A_NULL);
+
+
+}
+
+
diff --git a/src/breakpoints~.c b/src/breakpoints~.c
new file mode 100755
index 0000000..b7135b2
--- /dev/null
+++ b/src/breakpoints~.c
@@ -0,0 +1,479 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+#include <m_pd.h>
+
+//#define DEBUG
+/* ------------------------ breakpoints~ ----------------------------- */
+
+#define NONE 0
+#define ATTACK 1
+#define SUSTAIN -1
+#define STATES 100
+
+
+
+#include "breakpoints~.h"
+
+#define BACKGROUNDWIDTH "2"
+#include "w_breakpoints.h"
+
+static t_class *breakpoints_class;
+
+
+#define OUT_LIST(x,nr,a) \
+ outlet_list(x->x_obj.ob_outlet,&s_list,nr,(t_atom*)&a);\
+ if (x->s_sym != &s_ && x->s_sym->s_thing) pd_list(x->s_sym->s_thing, &s_list, nr, (t_atom*)&a);
+
+
+char dumpy[2000];
+
+/* initialize envelope with argument vector */
+
+#include <stdio.h>
+
+/*
+ breakpoints crashes frequently when reallocating memory ....
+ I really don't know why, it crashes during resizebytes,
+ which means it is unable to realloc() the memory ?????
+ the pointer seems to be ok, I don't know what else could
+ cause the problem. for the moment we prevent from reallocating
+ by setting the STATES variable to 100 */
+
+void breakpoints_resize(t_breakpoints* x,int ns)
+{
+ if (ns > x->args) {
+ int newargs = ns*sizeof(t_float);
+
+ x->duration = resizebytes(x->duration,x->args*sizeof(t_float),newargs);
+ x->finalvalues = resizebytes(x->finalvalues,x->args*sizeof(t_float),newargs);
+ x->args = ns;
+ }
+}
+
+ /* this is the actual performance routine which acts on the samples.
+ It's called with a single pointer "w" which is our location in the
+ DSP call list. We return a new "w" which will point to the next item
+ after us. Meanwhile, w[0] is just a pointer to dsp-perform itself
+ (no use to us), w[1] and w[2] are the input and output vector locations,
+ and w[3] is the number of points to calculate. */
+static t_int *breakpointssig_perform(t_int *w)
+{
+
+ t_breakpoints *x = (t_breakpoints *)(w[1]);
+ t_float *in = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int n = (int)(w[4]);
+
+ int state;
+ float f;
+ float val;
+
+ while (n--)
+ {
+
+ // STUFF
+ state = 0;
+ f = *(in++);
+
+ while (x->duration[state] < f && state < x->last_state) state++;
+
+ if (state == 0 || f >= x->duration[x->last_state]) {
+ val = x->finalvalues[state];
+
+ } else {
+ val = x->finalvalues[state-1] + (f - x->duration[state-1]) *
+ (x->finalvalues[state] - x->finalvalues[state-1]) /
+ (x->duration[state] - x->duration[state-1]);
+
+
+
+ }
+ // STUFF END
+
+
+ *out++ = val;
+ }
+ return (w+5);
+}
+
+
+
+ /* called to start DSP. Here we call Pd back to add our perform
+ routine to a linear callback list which Pd in turn calls to grind
+ out the samples. */
+static void breakpointssig_dsp(t_breakpoints *x, t_signal **sp)
+{
+ dsp_add(breakpointssig_perform, 4, x,sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+void breakpoints_totaldur(t_breakpoints* x,t_float dur)
+{
+ int i;
+ float f = dur/x->duration[x->last_state];
+
+ if (dur < 10) {
+ post("breakpoints: duration too small %f",dur);
+ return;
+ }
+
+ for (i=1;i<=x->last_state;i++)
+ x->duration[i]*=f;
+}
+
+
+static void breakpoints_dump(t_breakpoints* e)
+{
+ t_atom argv[50];
+ int argc= 0;
+ t_atom* a = argv;
+ int i;
+
+ SETFLOAT(a,e->finalvalues[0]);argc++;
+ for (i=1;i <= e->last_state;i++) {
+ SETFLOAT(argv+argc,e->duration[i] - e->duration[i-1]);
+ argc++;
+ SETFLOAT(argv+argc,e->finalvalues[i]);
+ argc++;
+ }
+ outlet_list(e->out2,&s_list,argc,(t_atom*)&argv);
+ if (e->d_sym != &s_) pd_list(e->d_sym->s_thing, &s_list, argc, argv);
+ //pd_float(x->s_sym->s_thing, val);
+ //EXTERN void pd_float(t_pd *x, t_float f);
+ //EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
+ //EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+ /////////////////////////////////////////////////////
+}
+
+void breakpoints_init(t_breakpoints *x,int argc,t_atom* argv)
+{
+ t_float* dur;
+ t_float* val;
+ t_float tdur = 0;
+
+ if (!argc) return;
+
+ x->duration[0] = 0;
+
+ x->last_state = argc>>1;
+ breakpoints_resize(x,argc>>1);
+
+ dur = x->duration;
+ val = x->finalvalues;
+
+ // get the first value
+ if (argc) {
+ *val = atom_getfloat(argv++);
+ *dur = 0.0;
+ x->max = *val;
+ x->min = *val;
+ }
+ dur++;val++;argc--;
+ // get the following
+ for (;argc > 0;argc--) {
+ tdur += atom_getfloat(argv++);
+#ifdef DEBUG
+ post("dur =%f",tdur);
+#endif
+ *dur++ = tdur;
+ argc--;
+ if (argc > 0) {
+ *val = atom_getfloat(argv++);
+ if (*val > x->max ) x->max = *val;
+ if (*val < x->min ) x->min = *val;
+ *val++;
+ } else {
+ *val = 0;
+ if (*val > x->max ) x->max = *val;
+ if (*val < x->min ) x->min = *val;
+ *val++;
+ }
+#ifdef DEBUG
+ post("val =%f",*(val-1));
+#endif
+
+ }
+
+ if ( x->max == x->min ) {
+ if ( x->max == 0 ) {
+ x->max = 1;
+ } else {
+ if (x->max > 0) {
+ x->min = 0;
+ } else {
+ x->max = 0;
+ }
+ }
+ }
+
+}
+
+
+
+
+
+void breakpoints_list(t_breakpoints *x,t_symbol* s, int argc,t_atom* argv)
+{
+ breakpoints_init(x,argc,argv);
+ if (glist_isvisible(x->w.glist)) {
+ breakpoints_drawme(x, x->w.glist, 0);
+ }
+}
+
+void breakpoints_setresize(t_breakpoints *x, t_floatarg f)
+{
+ x->resizeable = f;
+}
+
+
+
+
+
+void breakpoints_float(t_breakpoints *x, t_floatarg f)
+{
+ int state = 0;
+ float val;
+
+
+
+ while (x->duration[state] < f && state < x->last_state) state++;
+
+ if (state == 0 || f >= x->duration[x->last_state]) {
+ val = x->finalvalues[state]*(x->max-x->min);
+ outlet_float(x->x_obj.ob_outlet,f);
+ if (x->s_sym != &s_) pd_float(x->s_sym->s_thing, f);
+ return;
+ }
+
+ val = x->finalvalues[state-1] +
+ (f - x->duration[state-1])*
+ (x->finalvalues[state] - x->finalvalues[state-1])/
+ (x->duration[state] - x->duration[state-1]);
+
+ val *= (x->max - x->min);
+ outlet_float(x->x_obj.ob_outlet,val);
+ if (x->s_sym != &s_) pd_float(x->s_sym->s_thing, val);
+}
+
+
+
+
+
+
+/*
+
+void breakpoints_release(t_breakpoints* x) {
+ t_atom a[2];
+ float del = x->duration[x->x_state] - x->duration[x->x_state-1];
+ if (x->x_state <= x->sustain_state) {
+ x->x_state = x->sustain_state+1; // skip sustain state
+ clock_delay(x->x_clock,del);
+ SETFLOAT(a,x->finalvalues[x->x_state]*(x->max-x->min));
+ SETFLOAT(a+1,del);
+ OUT_LIST(x,2,a);
+ }
+}
+
+static void breakpoints_sustain(t_breakpoints *x, t_floatarg f)
+{
+ if (f > 0 && f < x->last_state)
+ x->sustain_state = f;
+ else
+ pd_error(x,"sustain value not betweem 0 and %f, ignoring message", x->last_state);
+}
+
+*/
+
+/*
+static void breakpoints_tick(t_breakpoints* x)
+{
+ t_atom a[2];
+ x->x_state++;
+ if (x->x_state <= x->last_state && x->x_state != x->sustain_state) {
+ float del = x->duration[x->x_state] - x->duration[x->x_state-1];
+ clock_delay(x->x_clock,del);
+ SETFLOAT(a,x->finalvalues[x->x_state]*(x->max-x->min));
+ SETFLOAT(a+1,del);
+ OUT_LIST(x,2,a);
+ }
+// else
+// clock_unset(x->x_clock);
+}
+
+*/
+
+/*
+static void breakpoints_freeze(t_breakpoints* x, t_floatarg f)
+{
+ x->x_freeze = f;
+}
+*/
+
+static void bindsym(t_pd* x,t_symbol* o,t_symbol* s)
+{
+ if (o != &s_) pd_unbind(x,o);
+ o = s;
+ pd_bind(x,s);
+}
+
+
+
+
+
+
+
+
+static void *breakpoints_new(t_symbol *s,int argc,t_atom* argv)
+{
+ t_breakpoints *x = (t_breakpoints *)pd_new(breakpoints_class);
+
+
+
+ x->x_f = 0;
+ x->args = STATES;
+ x->finalvalues = getbytes( x->args*sizeof(t_float));
+ x->duration = getbytes( x->args*sizeof(t_float));
+#ifdef DEBUG
+ post("finalvalues %x",x->finalvalues);
+#endif
+ /* widget */
+
+ x->w.grabbed = 0;
+ x->resizing = 0;
+ x->resizeable = 0;
+ x->w.glist = (t_glist*) canvas_getcurrent();
+
+ x->w.width = 200;
+ if (argc) x->w.width = atom_getfloat(argv++),argc--;
+ x->w.height = 140;
+ if (argc) x->w.height = atom_getfloat(argv++),argc--;
+
+ t_float initialDuration = 100;
+ if (argc) initialDuration = atom_getfloat(argv++),argc--;
+
+ x->r_sym = &s_;
+ if (argc) {
+ t_symbol* n;
+
+ n = atom_getsymbol(argv++);
+ bindsym(&x->x_obj.ob_pd,x->r_sym,n);
+ x->r_sym = n;
+ argc--;
+ }
+ #ifdef DEBUG
+ post("recv %s",x->r_sym->s_name);
+ #endif
+ /*
+ x->s_sym = &s_;
+ if (argc) x->s_sym = atom_getsymbol(argv++),argc--;
+ #ifdef DEBUG
+ post("send %s",x->s_sym->s_name);
+ #endif
+ */
+ x->d_sym = &s_;
+ if (argc) x->d_sym = atom_getsymbol(argv++),argc--;
+ #ifdef DEBUG
+ post("dump %s",x->d_sym->s_name);
+ #endif
+
+ x->c_sym = &s_;
+ if (argc) x->c_sym = atom_getsymbol(argv++),argc--;
+
+ if (argc>2)
+ breakpoints_init(x,argc,argv);
+ else {
+ t_atom a[5];
+ SETFLOAT(a,0);
+ SETFLOAT(a+1,50);
+ SETFLOAT(a+2,1);
+ SETFLOAT(a+3,50);
+ SETFLOAT(a+4,0);
+ breakpoints_init(x,5,a);
+ }
+
+ x->x_val = 0.0;
+ x->x_state = NONE;
+ x->sustain_state = SUSTAIN;
+ x->x_freeze = 0;
+
+ breakpoints_totaldur(x,initialDuration);
+
+ outlet_new(&x->x_obj, gensym("signal"));
+ //outlet_new(&x->x_obj, &s_float);
+ x->out2 = outlet_new(&x->x_obj, &s_float);
+ x->out3 = outlet_new(&x->x_obj, &s_bang);
+
+ //x->x_clock = clock_new(x, (t_method) breakpoints_tick);
+ return (x);
+}
+
+
+
+
+void breakpoints_motion(t_breakpoints *x, t_floatarg dx, t_floatarg dy);
+void breakpoints_click(t_breakpoints *x,
+ t_floatarg xpos, t_floatarg ypos, t_floatarg shift, t_floatarg ctrl,
+ t_floatarg alt);
+void breakpoints_key(t_breakpoints *x, t_floatarg f);
+
+t_widgetbehavior breakpoints_widgetbehavior;
+
+
+
+static void breakpoints_free(t_breakpoints *x) {
+
+
+ if (x->r_sym != &s_) pd_unbind(&x->x_obj.ob_pd, x->r_sym);
+
+}
+
+void breakpoints_tilde_setup(void)
+{
+ breakpoints_class = class_new(gensym("breakpoints~"), (t_newmethod)breakpoints_new, (t_method)breakpoints_free,
+ sizeof(t_breakpoints), 0,A_GIMME,0);
+
+ CLASS_MAINSIGNALIN(breakpoints_class, t_breakpoints, x_f);
+ /* here we tell Pd about the "dsp" method, which is called back
+ when DSP is turned on. */
+ class_addmethod(breakpoints_class, (t_method)breakpointssig_dsp, gensym("dsp"), 0);
+
+
+ //class_addcreator((t_newmethod)breakpoints_new,gensym("breakpoints~"),A_GIMME,0);
+ //class_addfloat(breakpoints_class, breakpoints_float);
+
+ //class_addbang(breakpoints_class,breakpoints_bang);
+ class_addlist(breakpoints_class,breakpoints_list);
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_sustain,gensym("sustain"),A_FLOAT,A_NULL);
+
+ class_addmethod(breakpoints_class, (t_method)breakpoints_motion, gensym("motion"),A_FLOAT, A_FLOAT, 0);
+ class_addmethod(breakpoints_class, (t_method)breakpoints_key, gensym("key"),
+ A_FLOAT, 0);
+
+ class_addmethod(breakpoints_class,(t_method)breakpoints_totaldur,gensym("duration"),A_FLOAT,NULL);
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_freeze,gensym("freeze"),A_FLOAT,NULL);
+ class_addmethod(breakpoints_class,(t_method)breakpoints_setresize,gensym("resize"),A_FLOAT,A_NULL);
+
+ //class_addmethod(breakpoints_class,(t_method)breakpoints_release,gensym("release"),A_NULL);
+ breakpoints_widgetbehavior.w_getrectfn = breakpoints_getrect;
+ breakpoints_widgetbehavior.w_displacefn = breakpoints_displace;
+ breakpoints_widgetbehavior.w_selectfn = breakpoints_select;
+ breakpoints_widgetbehavior.w_activatefn = breakpoints_activate;
+ breakpoints_widgetbehavior.w_deletefn = breakpoints_delete;
+ breakpoints_widgetbehavior.w_visfn = breakpoints_vis;
+ breakpoints_widgetbehavior.w_clickfn = (t_clickfn) breakpoints_newclick;
+ //breakpoints_widgetbehavior.w_clickfn = NULL;
+#if PD_MINOR_VERSION < 37
+ breakpoints_widgetbehavior.w_propertiesfn = NULL;
+ //breakpoints_widgetbehavior.w_savefn = breakpoints_save;
+ breakpoints_widgetbehavior.w_savefn = NULL;
+#endif
+
+ class_setwidget(breakpoints_class,&breakpoints_widgetbehavior);
+#if PD_MINOR_VERSION >= 37
+ //class_setsavefn(breakpoints_class,&breakpoints_save);
+#endif
+ class_addmethod(breakpoints_class,(t_method)breakpoints_dump,gensym("dump"),A_NULL);
+
+
+}
+
+
diff --git a/src/breakpoints~.h b/src/breakpoints~.h
new file mode 100755
index 0000000..27d6a6d
--- /dev/null
+++ b/src/breakpoints~.h
@@ -0,0 +1,63 @@
+#ifndef __GG_breakpoints_H__
+#define __GG_breakpoints_H__
+
+#include "g_canvas.h"
+
+typedef struct _wbreakpoints {
+ t_glist* glist;
+ int width;
+ int height;
+ int numdoodles;
+ int grabbed; /* for moving points */
+ int shift; /* move 100th */
+ float pointerx;
+ float pointery;
+
+ t_clock* numclock;
+} t_wbreakpoints;
+
+typedef struct _breakpoints
+{
+ t_object x_obj;
+
+ t_float x_val;
+
+ int x_state;
+ int last_state;
+ int sustain_state;
+ int envchanged;
+
+ t_float* finalvalues;
+ t_float* duration;
+ t_float totaldur;
+ t_int args; /* get rid of that */
+ t_int resizing;
+ t_int resizeable;
+
+ t_symbol* r_sym; //receive symbol
+ t_symbol* s_sym; //send symbol
+ t_symbol* d_sym; //dump symbol
+ t_symbol* c_sym; //change symbol
+
+ t_float min;
+ t_float max;
+
+ t_clock* x_clock;
+ t_float x_freeze;
+
+ t_float x_f; /* place to hold inlet's value if it's set by message */
+
+
+ t_outlet* out2;
+ t_outlet* out3;
+ /* widget parameters */
+ t_wbreakpoints w;
+} t_breakpoints;
+
+
+t_widgetbehavior breakpoints_widgetbehavior;
+void breakpoints_drawme(t_breakpoints *x, t_glist *glist, int firsttime);
+int breakpoints_set_values(t_breakpoints * x);
+void breakpoints_resize(t_breakpoints* x,int ns);
+
+#endif
diff --git a/src/g_canvas.h b/src/g_canvas.h
new file mode 100755
index 0000000..712aebf
--- /dev/null
+++ b/src/g_canvas.h
@@ -0,0 +1,615 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* this file defines the structure for "glists" and related structures and
+functions. "Glists" and "canvases" and "graphs" used to be different
+structures until being unified in version 0.35.
+
+A glist occupies its own window if the "gl_havewindow" flag is set. Its
+appearance on its "parent" or "owner" (if it has one) is as a graph if
+"gl_isgraph" is set, and otherwise as a text box.
+
+A glist is "root" if it has no owner, i.e., a document window. In this
+case "gl_havewindow" is always set.
+
+We maintain a list of root windows, so that we can traverse the whole
+collection of everything in a Pd process.
+
+If a glist has a window it may still not be "mapped." Miniaturized
+windows aren't mapped, for example, but a window is also not mapped
+immediately upon creation. In either case gl_havewindow is true but
+gl_mapped is false.
+
+Closing a non-root window makes it invisible; closing a root destroys it.
+
+A glist that's just a text object on its parent is always "toplevel." An
+embedded glist can switch back and forth to appear as a toplevel by double-
+clicking on it. Single-clicking a text box makes the toplevel become visible
+and raises the window it's in.
+
+If a glist shows up as a graph on its parent, the graph is blanked while the
+glist has its own window, even if miniaturized.
+
+*/
+
+/* NOTE: this file describes Pd implementation details which may change
+in future releases. The public (stable) API is in m_pd.h. */
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#endif
+
+/* --------------------- geometry ---------------------------- */
+#define IOWIDTH 7 /* width of an inlet/outlet in pixels */
+#define IOMIDDLE ((IOWIDTH-1)/2)
+#define GLIST_DEFGRAPHWIDTH 200
+#define GLIST_DEFGRAPHHEIGHT 140
+/* ----------------------- data ------------------------------- */
+
+typedef struct _updateheader
+{
+ struct _updateheader *upd_next;
+ unsigned int upd_array:1; /* true if array, false if glist */
+ unsigned int upd_queued:1; /* true if we're queued */
+} t_updateheader;
+
+ /* types to support glists grabbing mouse motion or keys from parent */
+typedef void (*t_glistmotionfn)(void *z, t_floatarg dx, t_floatarg dy);
+typedef void (*t_glistkeyfn)(void *z, t_floatarg key);
+
+EXTERN_STRUCT _rtext;
+#define t_rtext struct _rtext
+
+EXTERN_STRUCT _gtemplate;
+#define t_gtemplate struct _gtemplate
+
+EXTERN_STRUCT _guiconnect;
+#define t_guiconnect struct _guiconnect
+
+EXTERN_STRUCT _tscalar;
+#define t_tscalar struct _tscalar
+
+EXTERN_STRUCT _canvasenvironment;
+#define t_canvasenvironment struct _canvasenvironment
+
+EXTERN_STRUCT _fielddesc;
+#define t_fielddesc struct _fielddesc
+
+typedef struct _selection
+{
+ t_gobj *sel_what;
+ struct _selection *sel_next;
+} t_selection;
+
+ /* this structure is instantiated whenever a glist becomes visible. */
+typedef struct _editor
+{
+ t_updateheader e_upd; /* update header structure */
+ t_selection *e_updlist; /* list of objects to update */
+ t_rtext *e_rtext; /* text responder linked list */
+ t_selection *e_selection; /* head of the selection list */
+ t_rtext *e_textedfor; /* the rtext if any that we are editing */
+ t_gobj *e_grab; /* object being "dragged" */
+ t_glistmotionfn e_motionfn; /* ... motion callback */
+ t_glistkeyfn e_keyfn; /* ... keypress callback */
+ t_binbuf *e_connectbuf; /* connections to deleted objects */
+ t_binbuf *e_deleted; /* last stuff we deleted */
+ t_guiconnect *e_guiconnect; /* GUI connection for filtering messages */
+ struct _glist *e_glist; /* glist which owns this */
+ int e_xwas; /* xpos on last mousedown or motion event */
+ int e_ywas; /* ypos, similarly */
+ int e_selectline_index1; /* indices for the selected line if any */
+ int e_selectline_outno; /* (only valid if e_selectedline is set) */
+ int e_selectline_index2;
+ int e_selectline_inno;
+ t_outconnect *e_selectline_tag;
+ unsigned int e_onmotion: 3; /* action to take on motion */
+ unsigned int e_lastmoved: 1; /* one if mouse has moved since click */
+ unsigned int e_textdirty: 1; /* one if e_textedfor has changed */
+ unsigned int e_selectedline: 1; /* one if a line is selected */
+} t_editor;
+
+#define MA_NONE 0 /* e_onmotion: do nothing on mouse motion */
+#define MA_MOVE 1 /* drag the selection around */
+#define MA_CONNECT 2 /* make a connection */
+#define MA_REGION 3 /* selection region */
+#define MA_PASSOUT 4 /* send on to e_grab */
+#define MA_DRAGTEXT 5 /* drag in text editor to alter selection */
+
+/* editor structure for "garrays". We don't bother to delete and regenerate
+this structure when the "garray" becomes invisible or visible, although we
+could do so if the structure gets big (like the "editor" above.) */
+
+typedef struct _arrayvis
+{
+ t_updateheader av_upd; /* update header structure */
+ t_garray *av_garray; /* owning structure */
+} t_arrayvis;
+
+/* the t_tick structure describes where to draw x and y "ticks" for a glist */
+
+typedef struct _tick /* where to put ticks on x or y axes */
+{
+ float k_point; /* one point to draw a big tick at */
+ float k_inc; /* x or y increment per little tick */
+ int k_lperb; /* little ticks per big; 0 if no ticks to draw */
+} t_tick;
+
+/* the t_glist structure, which describes a list of elements that live on an
+area of a window.
+
+*/
+
+struct _glist
+{
+ t_object gl_obj; /* header in case we're a glist */
+ t_gobj *gl_list; /* the actual data */
+ struct _gstub *gl_stub; /* safe pointer handler */
+ int gl_valid; /* incremented when pointers might be stale */
+ struct _glist *gl_owner; /* parent glist, supercanvas, or 0 if none */
+ int gl_pixwidth; /* width in pixels (on parent, if a graph) */
+ int gl_pixheight;
+ float gl_x1; /* bounding rectangle in our own coordinates */
+ float gl_y1;
+ float gl_x2;
+ float gl_y2;
+ int gl_screenx1; /* screen coordinates when toplevel */
+ int gl_screeny1;
+ int gl_screenx2;
+ int gl_screeny2;
+ int gl_xmargin; /* origin for GOP rectangle */
+ int gl_ymargin;
+ t_tick gl_xtick; /* ticks marking X values */
+ int gl_nxlabels; /* number of X coordinate labels */
+ t_symbol **gl_xlabel; /* ... an array to hold them */
+ float gl_xlabely; /* ... and their Y coordinates */
+ t_tick gl_ytick; /* same as above for Y ticks and labels */
+ int gl_nylabels;
+ t_symbol **gl_ylabel;
+ float gl_ylabelx;
+ t_editor *gl_editor; /* editor structure when visible */
+ t_symbol *gl_name; /* symbol bound here */
+ int gl_font; /* nominal font size in points, e.g., 10 */
+ struct _glist *gl_next; /* link in list of toplevels */
+ t_canvasenvironment *gl_env; /* root canvases and abstractions only */
+ unsigned int gl_havewindow:1; /* true if we own a window */
+ unsigned int gl_mapped:1; /* true if, moreover, it's "mapped" */
+ unsigned int gl_dirty:1; /* (root canvas only:) patch has changed */
+ unsigned int gl_loading:1; /* am now loading from file */
+ unsigned int gl_willvis:1; /* make me visible after loading */
+ unsigned int gl_edit:1; /* edit mode */
+ unsigned int gl_isdeleting:1; /* we're inside glist_delete -- hack! */
+ unsigned int gl_goprect:1; /* draw rectangle for graph-on-parent */
+ unsigned int gl_isgraph:1; /* show as graph on parent */
+};
+
+#define gl_gobj gl_obj.te_g
+#define gl_pd gl_gobj.g_pd
+
+/* a data structure to describe a field in a pure datum */
+
+#define DT_FLOAT 0
+#define DT_SYMBOL 1
+#define DT_LIST 2
+#define DT_ARRAY 3
+
+typedef struct _dataslot
+{
+ int ds_type;
+ t_symbol *ds_name;
+ t_symbol *ds_arraytemplate; /* filled in for arrays only */
+} t_dataslot;
+
+typedef struct _template
+{
+ t_pd t_pdobj; /* header */
+ struct _gtemplate *t_list; /* list of "struct"/gtemplate objects */
+ t_symbol *t_sym; /* name */
+ int t_n; /* number of dataslots (fields) */
+ t_dataslot *t_vec; /* array of dataslots */
+} t_template;
+
+struct _array
+{
+ int a_n; /* number of elements */
+ int a_elemsize; /* size in bytes; LATER get this from template */
+ char *a_vec; /* array of elements */
+ t_symbol *a_templatesym; /* template for elements */
+ int a_valid; /* protection against stale pointers into array */
+ t_gpointer a_gp; /* pointer to scalar or array element we're in */
+ t_gstub *a_stub; /* stub for pointing into this array */
+};
+
+ /* structure for traversing all the connections in a glist */
+typedef struct _linetraverser
+{
+ t_canvas *tr_x;
+ t_object *tr_ob;
+ int tr_nout;
+ int tr_outno;
+ t_object *tr_ob2;
+ t_outlet *tr_outlet;
+ t_inlet *tr_inlet;
+ int tr_nin;
+ int tr_inno;
+ int tr_x11, tr_y11, tr_x12, tr_y12;
+ int tr_x21, tr_y21, tr_x22, tr_y22;
+ int tr_lx1, tr_ly1, tr_lx2, tr_ly2;
+ t_outconnect *tr_nextoc;
+ int tr_nextoutno;
+} t_linetraverser;
+
+/* function types used to define graphical behavior for gobjs, a bit like X
+widgets. We don't use Pd methods because Pd's typechecking can't specify the
+types of pointer arguments. Also it's more convenient this way, since
+every "patchable" object can just get the "text" behaviors. */
+
+ /* Call this to get a gobj's bounding rectangle in pixels */
+typedef void (*t_getrectfn)(t_gobj *x, struct _glist *glist,
+ int *x1, int *y1, int *x2, int *y2);
+ /* and this to displace a gobj: */
+typedef void (*t_displacefn)(t_gobj *x, struct _glist *glist, int dx, int dy);
+ /* change color to show selection: */
+typedef void (*t_selectfn)(t_gobj *x, struct _glist *glist, int state);
+ /* change appearance to show activation/deactivation: */
+typedef void (*t_activatefn)(t_gobj *x, struct _glist *glist, int state);
+ /* warn a gobj it's about to be deleted */
+typedef void (*t_deletefn)(t_gobj *x, struct _glist *glist);
+ /* making visible or invisible */
+typedef void (*t_visfn)(t_gobj *x, struct _glist *glist, int flag);
+ /* field a mouse click (when not in "edit" mode) */
+typedef int (*t_clickfn)(t_gobj *x, struct _glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+ /* ... and later, resizing; getting/setting font or color... */
+
+struct _widgetbehavior
+{
+ t_getrectfn w_getrectfn;
+ t_displacefn w_displacefn;
+ t_selectfn w_selectfn;
+ t_activatefn w_activatefn;
+ t_deletefn w_deletefn;
+ t_visfn w_visfn;
+ t_clickfn w_clickfn;
+};
+
+/* -------- behaviors for scalars defined by objects in template --------- */
+/* these are set by "drawing commands" in g_template.c which add appearance to
+scalars, which live in some other window. If the scalar is just included
+in a canvas the "parent" is a misnomer. There is also a text scalar object
+which really does draw the scalar on the parent window; see g_scalar.c. */
+
+/* note how the click function wants the whole scalar, not the "data", so
+doesn't work on array elements... LATER reconsider this */
+
+ /* bounding rectangle: */
+typedef void (*t_parentgetrectfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int *x1, int *y1, int *x2, int *y2);
+ /* displace it */
+typedef void (*t_parentdisplacefn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int dx, int dy);
+ /* change color to show selection */
+typedef void (*t_parentselectfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int state);
+ /* change appearance to show activation/deactivation: */
+typedef void (*t_parentactivatefn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int state);
+ /* making visible or invisible */
+typedef void (*t_parentvisfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, float basex, float basey,
+ int flag);
+ /* field a mouse click */
+typedef int (*t_parentclickfn)(t_gobj *x, struct _glist *glist,
+ t_word *data, t_template *tmpl, t_scalar *sc, t_array *ap,
+ float basex, float basey,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+
+struct _parentwidgetbehavior
+{
+ t_parentgetrectfn w_parentgetrectfn;
+ t_parentdisplacefn w_parentdisplacefn;
+ t_parentselectfn w_parentselectfn;
+ t_parentactivatefn w_parentactivatefn;
+ t_parentvisfn w_parentvisfn;
+ t_parentclickfn w_parentclickfn;
+};
+
+ /* cursor definitions; used as return value for t_parentclickfn */
+#define CURSOR_RUNMODE_NOTHING 0
+#define CURSOR_RUNMODE_CLICKME 1
+#define CURSOR_RUNMODE_THICKEN 2
+#define CURSOR_RUNMODE_ADDPOINT 3
+#define CURSOR_EDITMODE_NOTHING 4
+#define CURSOR_EDITMODE_CONNECT 5
+#define CURSOR_EDITMODE_DISCONNECT 6
+EXTERN void canvas_setcursor(t_glist *x, unsigned int cursornum);
+
+extern t_canvas *canvas_editing; /* last canvas to start text edting */
+extern t_canvas *canvas_whichfind; /* last canvas we did a find in */
+extern t_canvas *canvas_list; /* list of all root canvases */
+extern t_class *vinlet_class, *voutlet_class;
+extern int glist_valid; /* incremented when pointers might be stale */
+
+#define PLOTSTYLE_POINTS 0 /* plotting styles for arrays */
+#define PLOTSTYLE_POLY 1
+#define PLOTSTYLE_BEZ 2
+
+/* ------------------- functions on any gobj ----------------------------- */
+EXTERN void gobj_getrect(t_gobj *x, t_glist *owner, int *x1, int *y1,
+ int *x2, int *y2);
+EXTERN void gobj_displace(t_gobj *x, t_glist *owner, int dx, int dy);
+EXTERN void gobj_select(t_gobj *x, t_glist *owner, int state);
+EXTERN void gobj_activate(t_gobj *x, t_glist *owner, int state);
+EXTERN void gobj_delete(t_gobj *x, t_glist *owner);
+EXTERN void gobj_vis(t_gobj *x, t_glist *glist, int flag);
+EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
+EXTERN void gobj_properties(t_gobj *x, struct _glist *glist);
+EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
+
+/* -------------------- functions on glists --------------------- */
+EXTERN t_glist *glist_new( void);
+EXTERN void glist_init(t_glist *x);
+EXTERN void glist_add(t_glist *x, t_gobj *g);
+EXTERN void glist_cleanup(t_glist *x);
+EXTERN void glist_free(t_glist *x);
+
+EXTERN void glist_clear(t_glist *x);
+EXTERN t_canvas *glist_getcanvas(t_glist *x);
+EXTERN int glist_isselected(t_glist *x, t_gobj *y);
+EXTERN void glist_select(t_glist *x, t_gobj *y);
+EXTERN void glist_deselect(t_glist *x, t_gobj *y);
+EXTERN void glist_noselect(t_glist *x);
+EXTERN void glist_selectall(t_glist *x);
+EXTERN void glist_delete(t_glist *x, t_gobj *y);
+EXTERN void glist_retext(t_glist *x, t_text *y);
+EXTERN void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
+ t_glistkeyfn keyfn, int xpos, int ypos);
+EXTERN int glist_isvisible(t_glist *x);
+EXTERN int glist_istoplevel(t_glist *x);
+EXTERN t_glist *glist_findgraph(t_glist *x);
+EXTERN int glist_getfont(t_glist *x);
+EXTERN void glist_sort(t_glist *canvas);
+EXTERN void glist_read(t_glist *x, t_symbol *filename, t_symbol *format);
+EXTERN void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format);
+
+EXTERN float glist_pixelstox(t_glist *x, float xpix);
+EXTERN float glist_pixelstoy(t_glist *x, float ypix);
+EXTERN float glist_xtopixels(t_glist *x, float xval);
+EXTERN float glist_ytopixels(t_glist *x, float yval);
+EXTERN float glist_dpixtodx(t_glist *x, float dxpix);
+EXTERN float glist_dpixtody(t_glist *x, float dypix);
+
+EXTERN void glist_getnextxy(t_glist *gl, int *xval, int *yval);
+EXTERN void glist_glist(t_glist *g, t_symbol *s, int argc, t_atom *argv);
+EXTERN t_glist *glist_addglist(t_glist *g, t_symbol *sym,
+ float x1, float y1, float x2, float y2,
+ float px1, float py1, float px2, float py2);
+EXTERN void glist_arraydialog(t_glist *parent, t_symbol *name,
+ t_floatarg size, t_floatarg saveit, t_floatarg newgraph);
+EXTERN t_binbuf *glist_writetobinbuf(t_glist *x, int wholething);
+EXTERN int glist_isgraph(t_glist *x);
+EXTERN void glist_redraw(t_glist *x);
+EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
+ char *tag, int x1, int y1, int x2, int y2);
+EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag);
+EXTERN void canvas_create_editor(t_glist *x, int createit);
+void canvas_deletelinesforio(t_canvas *x, t_text *text,
+ t_inlet *inp, t_outlet *outp);
+
+
+/* -------------------- functions on texts ------------------------- */
+EXTERN void text_setto(t_text *x, t_glist *glist, char *buf, int bufsize);
+EXTERN void text_drawborder(t_text *x, t_glist *glist, char *tag,
+ int width, int height, int firsttime);
+EXTERN void text_eraseborder(t_text *x, t_glist *glist, char *tag);
+EXTERN int text_xcoord(t_text *x, t_glist *glist);
+EXTERN int text_ycoord(t_text *x, t_glist *glist);
+EXTERN int text_xpix(t_text *x, t_glist *glist);
+EXTERN int text_ypix(t_text *x, t_glist *glist);
+EXTERN int text_shouldvis(t_text *x, t_glist *glist);
+
+/* -------------------- functions on rtexts ------------------------- */
+#define RTEXT_DOWN 1
+#define RTEXT_DRAG 2
+#define RTEXT_DBL 3
+#define RTEXT_SHIFT 4
+
+EXTERN t_rtext *rtext_new(t_glist *glist, t_text *who);
+EXTERN t_rtext *glist_findrtext(t_glist *gl, t_text *who);
+EXTERN void rtext_draw(t_rtext *x);
+EXTERN void rtext_erase(t_rtext *x);
+EXTERN t_rtext *rtext_remove(t_rtext *first, t_rtext *x);
+EXTERN int rtext_height(t_rtext *x);
+EXTERN void rtext_displace(t_rtext *x, int dx, int dy);
+EXTERN void rtext_select(t_rtext *x, int state);
+EXTERN void rtext_activate(t_rtext *x, int state);
+EXTERN void rtext_free(t_rtext *x);
+EXTERN void rtext_key(t_rtext *x, int n, t_symbol *s);
+EXTERN void rtext_mouse(t_rtext *x, int xval, int yval, int flag);
+EXTERN void rtext_retext(t_rtext *x);
+EXTERN int rtext_width(t_rtext *x);
+EXTERN int rtext_height(t_rtext *x);
+EXTERN char *rtext_gettag(t_rtext *x);
+EXTERN void rtext_gettext(t_rtext *x, char **buf, int *bufsize);
+EXTERN void rtext_getseltext(t_rtext *x, char **buf, int *bufsize);
+
+/* -------------------- functions on canvases ------------------------ */
+EXTERN t_class *canvas_class;
+
+EXTERN t_canvas *canvas_new(void *dummy, t_symbol *sel, int argc, t_atom *argv);
+EXTERN t_symbol *canvas_makebindsym(t_symbol *s);
+EXTERN void canvas_vistext(t_canvas *x, t_text *y);
+EXTERN void canvas_fixlinesfor(t_canvas *x, t_text *text);
+EXTERN void canvas_deletelinesfor(t_canvas *x, t_text *text);
+EXTERN void canvas_stowconnections(t_canvas *x);
+EXTERN void canvas_restoreconnections(t_canvas *x);
+EXTERN void canvas_redraw(t_canvas *x);
+
+EXTERN t_inlet *canvas_addinlet(t_canvas *x, t_pd *who, t_symbol *sym);
+EXTERN void canvas_rminlet(t_canvas *x, t_inlet *ip);
+EXTERN t_outlet *canvas_addoutlet(t_canvas *x, t_pd *who, t_symbol *sym);
+EXTERN void canvas_rmoutlet(t_canvas *x, t_outlet *op);
+EXTERN void canvas_redrawallfortemplate(t_template *tmpl, int action);
+EXTERN void canvas_redrawallfortemplatecanvas(t_canvas *x, int action);
+EXTERN void canvas_zapallfortemplate(t_canvas *tmpl);
+EXTERN void canvas_setusedastemplate(t_canvas *x);
+EXTERN t_canvas *canvas_getcurrent(void);
+EXTERN void canvas_setcurrent(t_canvas *x);
+EXTERN void canvas_unsetcurrent(t_canvas *x);
+EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
+EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
+EXTERN void canvas_dirty(t_canvas *x, t_int n);
+EXTERN int canvas_getfont(t_canvas *x);
+typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3);
+
+EXTERN t_int *canvas_recurapply(t_canvas *x, t_canvasapply *fn,
+ t_int x1, t_int x2, t_int x3);
+
+EXTERN void canvas_resortinlets(t_canvas *x);
+EXTERN void canvas_resortoutlets(t_canvas *x);
+EXTERN void canvas_free(t_canvas *x);
+EXTERN void canvas_updatewindowlist( void);
+EXTERN void canvas_editmode(t_canvas *x, t_floatarg yesplease);
+EXTERN int canvas_isabstraction(t_canvas *x);
+EXTERN int canvas_istable(t_canvas *x);
+EXTERN int canvas_showtext(t_canvas *x);
+EXTERN void canvas_vis(t_canvas *x, t_floatarg f);
+EXTERN t_canvasenvironment *canvas_getenv(t_canvas *x);
+EXTERN void canvas_rename(t_canvas *x, t_symbol *s, t_symbol *dir);
+EXTERN void canvas_loadbang(t_canvas *x);
+EXTERN int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
+ int *x1p, int *y1p, int *x2p, int *y2p);
+EXTERN int canvas_setdeleting(t_canvas *x, int flag);
+
+typedef void (*t_undofn)(t_canvas *canvas, void *buf,
+ int action); /* a function that does UNDO/REDO */
+#define UNDO_FREE 0 /* free current undo/redo buffer */
+#define UNDO_UNDO 1 /* undo */
+#define UNDO_REDO 2 /* redo */
+EXTERN void canvas_setundo(t_canvas *x, t_undofn undofn, void *buf,
+ const char *name);
+EXTERN void canvas_noundo(t_canvas *x);
+EXTERN int canvas_getindex(t_canvas *x, t_gobj *y);
+
+EXTERN void canvas_connect(t_canvas *x,
+ t_floatarg fwhoout, t_floatarg foutno,t_floatarg fwhoin, t_floatarg finno);
+EXTERN void canvas_disconnect(t_canvas *x,
+ float index1, float outno, float index2, float inno);
+EXTERN int canvas_isconnected (t_canvas *x,
+ t_text *ob1, int n1, t_text *ob2, int n2);
+EXTERN void canvas_selectinrect(t_canvas *x, int lox, int loy, int hix, int hiy);
+
+
+/* ---- functions on canvasses as objects --------------------- */
+
+EXTERN void canvas_fattenforscalars(t_canvas *x,
+ int *x1, int *y1, int *x2, int *y2);
+EXTERN void canvas_visforscalars(t_canvas *x, t_glist *glist, int vis);
+EXTERN int canvas_clicksub(t_canvas *x, int xpix, int ypix, int shift,
+ int alt, int dbl, int doit);
+EXTERN t_glist *canvas_getglistonsuper(void);
+
+EXTERN void linetraverser_start(t_linetraverser *t, t_canvas *x);
+EXTERN t_outconnect *linetraverser_next(t_linetraverser *t);
+EXTERN void linetraverser_skipobject(t_linetraverser *t);
+
+/* --------- functions on garrays (graphical arrays) -------------------- */
+
+EXTERN t_template *garray_template(t_garray *x);
+
+/* -------------------- arrays --------------------- */
+EXTERN t_garray *graph_array(t_glist *gl, t_symbol *s, t_symbol *tmpl,
+ t_floatarg f, t_floatarg saveit);
+EXTERN t_array *array_new(t_symbol *templatesym, t_gpointer *parent);
+EXTERN void array_resize(t_array *x, int n);
+EXTERN void array_free(t_array *x);
+
+/* --------------------- gpointers and stubs ---------------- */
+EXTERN t_gstub *gstub_new(t_glist *gl, t_array *a);
+EXTERN void gstub_cutoff(t_gstub *gs);
+EXTERN void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x);
+
+/* --------------------- scalars ------------------------- */
+EXTERN void word_init(t_word *wp, t_template *tmpl, t_gpointer *gp);
+EXTERN void word_restore(t_word *wp, t_template *tmpl,
+ int argc, t_atom *argv);
+EXTERN t_scalar *scalar_new(t_glist *owner,
+ t_symbol *templatesym);
+EXTERN void word_free(t_word *wp, t_template *tmpl);
+EXTERN void scalar_getbasexy(t_scalar *x, float *basex, float *basey);
+EXTERN void scalar_redraw(t_scalar *x, t_glist *glist);
+
+/* ------helper routines for "garrays" and "plots" -------------- */
+EXTERN int array_doclick(t_array *array, t_glist *glist, t_scalar *sc, t_array *ap,
+ t_symbol *elemtemplatesym,
+ float linewidth, float xloc, float xinc, float yloc, float scalarvis,
+ t_fielddesc *xfield, t_fielddesc *yfield, t_fielddesc *wfield,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit);
+
+EXTERN void array_getcoordinate(t_glist *glist,
+ char *elem, int xonset, int yonset, int wonset, int indx,
+ float basex, float basey, float xinc,
+ t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
+ float *xp, float *yp, float *wp);
+
+EXTERN int array_getfields(t_symbol *elemtemplatesym,
+ t_canvas **elemtemplatecanvasp,
+ t_template **elemtemplatep, int *elemsizep,
+ t_fielddesc *xfielddesc, t_fielddesc *yfielddesc, t_fielddesc *wfielddesc,
+ int *xonsetp, int *yonsetp, int *wonsetp);
+
+/* --------------------- templates ------------------------- */
+EXTERN t_template *template_new(t_symbol *sym, int argc, t_atom *argv);
+EXTERN void template_free(t_template *x);
+EXTERN int template_match(t_template *x1, t_template *x2);
+EXTERN int template_find_field(t_template *x, t_symbol *name, int *p_onset,
+ int *p_type, t_symbol **p_arraytype);
+EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname, t_word *wp,
+ int loud);
+EXTERN void template_setfloat(t_template *x, t_symbol *fieldname, t_word *wp,
+ t_float f, int loud);
+EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_symbol *s, int loud);
+
+EXTERN t_template *gtemplate_get(t_gtemplate *x);
+EXTERN t_template *template_findbyname(t_symbol *s);
+EXTERN t_canvas *template_findcanvas(t_template *tmpl);
+EXTERN void template_notify(t_template *tmpl,
+ t_symbol *s, int argc, t_atom *argv);
+
+EXTERN t_float template_getfloat(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setfloat(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_float f, int loud);
+EXTERN t_symbol *template_getsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, int loud);
+EXTERN void template_setsymbol(t_template *x, t_symbol *fieldname,
+ t_word *wp, t_symbol *s, int loud);
+EXTERN t_float fielddesc_getcoord(t_fielddesc *f, t_template *tmpl,
+ t_word *wp, int loud);
+EXTERN void fielddesc_setcoord(t_fielddesc *f, t_template *tmpl,
+ t_word *wp, float pix, int loud);
+EXTERN t_float fielddesc_cvttocoord(t_fielddesc *f, float val);
+EXTERN float fielddesc_cvtfromcoord(t_fielddesc *f, float coord);
+
+
+/* ----------------------- guiconnects, g_guiconnect.c --------- */
+EXTERN t_guiconnect *guiconnect_new(t_pd *who, t_symbol *sym);
+EXTERN void guiconnect_notarget(t_guiconnect *x, double timedelay);
+
+/* ------------- IEMGUI routines used in other g_ files ---------------- */
+EXTERN t_symbol *iemgui_raute2dollar(t_symbol *s);
+EXTERN t_symbol *iemgui_dollar2raute(t_symbol *s);
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+}
+#endif
diff --git a/src/w_breakpoints.h b/src/w_breakpoints.h
new file mode 100755
index 0000000..f7d8754
--- /dev/null
+++ b/src/w_breakpoints.h
@@ -0,0 +1,569 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifdef _WIN32
+//#pragma warning( disable : 4244 )
+//#pragma warning( disable : 4305 )
+#define abs fabs
+#endif
+
+#define BACKGROUNDCOLOR "grey"
+#define LINECOLOR "grey30"
+#ifndef BACKGROUNDWIDTH
+#define BACKGROUNDWIDTH "1"
+#endif
+#define BORDER 2
+
+
+static void draw_inlets(t_breakpoints *x, t_glist *glist, int firsttime, int nin, int nout)
+{
+
+ if (x->r_sym == &s_) {
+ int n = nout;
+ int nplus, i;
+ int xpos = text_xpix(&x->x_obj,glist);
+ int ypos = text_ypix(&x->x_obj,glist);
+
+ nplus = (n == 1 ? 1 : n-1);
+ for (i = 0; i < n; i++)
+ {
+ int onset = xpos + (x->w.width - IOWIDTH + 3 * BORDER) * i / nplus - BORDER;
+ // OUTLETS
+ if (firsttime)
+ sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d \n",
+ glist_getcanvas(glist),
+ onset, ypos + x->w.height - 2 + 2*BORDER,
+ onset + IOWIDTH, ypos + x->w.height - 1+ 2*BORDER,
+ x, i);
+ else
+ sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n",
+ glist_getcanvas(glist), x, i,
+ onset, ypos + x->w.height - 2 + 2*BORDER,
+ onset + IOWIDTH, ypos + x->w.height -1 + 2*BORDER);
+ }
+ n = nin;
+ nplus = (n == 1 ? 1 : n-1);
+ for (i = 0; i < n; i++)
+ {
+ int onset = xpos + (x->w.width - IOWIDTH + 3 * BORDER) * i / nplus - BORDER;
+ // INLETS
+ if (firsttime)
+ sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n",
+ glist_getcanvas(glist),
+ onset, ypos - BORDER + 1,
+ onset + IOWIDTH, ypos + 2 - BORDER,
+ x, i);
+ else
+ sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n",
+ glist_getcanvas(glist), x, i,
+ onset, ypos - BORDER + 1,
+ onset + IOWIDTH, ypos + 2 - BORDER);
+
+ }
+ }
+}
+
+
+
+static int breakpoints_next_doodle(t_breakpoints *x, struct _glist *glist,
+ int xpos,int ypos)
+{
+ int ret = -1;
+ float xscale,yscale;
+ int dxpos,dypos;
+ float minval = 100000.0;
+ float tval;
+ int i;
+ int insertpos = -1;
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+
+ if (xpos > text_xpix(&x->x_obj,glist) + x->w.width)
+ xpos = text_xpix(&x->x_obj,glist) + x->w.width;
+
+ xscale = x->w.width/x->duration[x->last_state];
+ yscale = x->w.height;
+
+ dxpos = text_xpix(&x->x_obj,glist);/* + BORDER */;
+ dypos = text_ypix(&x->x_obj,glist) + BORDER;
+
+ for (i=0;i<=x->last_state;i++) {
+ float dx2 = (dxpos + (x->duration[i] * xscale)) - xpos;
+ float dy2 = (dypos + yscale - ( (x->finalvalues[i] - yBase) / ySize * yscale)) - ypos;
+
+ dx2*=dx2;
+ dy2*=dy2;
+ tval = sqrt(dx2+dy2);
+
+ if (tval <= minval) {
+ minval = tval;
+ insertpos = i;
+ }
+ }
+
+ /* decide if we want to make a new one */
+ if (minval > /*5*/ 8 && insertpos >= 0 && !x->x_freeze) {
+
+ while (((dxpos + (x->duration[insertpos] * xscale)) - xpos) < 0)
+ insertpos++;
+ while (((dxpos + (x->duration[insertpos-1] * xscale)) - xpos) > 0)
+ insertpos--;
+
+ if (x->last_state+1 >= x->args)
+ breakpoints_resize(x,x->args+1);
+
+ for (i=x->last_state;i>=insertpos;i--) {
+ x->duration[i+1] = x->duration[i];
+ x->finalvalues[i+1] = x->finalvalues[i];
+ }
+ x->duration[insertpos] = (float)(xpos-dxpos)/x->w.width*x->duration[x->last_state++];
+ x->w.pointerx = xpos;
+ x->w.pointery = ypos;
+ }
+ else {
+ x->w.pointerx = text_xpix(&x->x_obj,glist) + x->duration[insertpos]*x->w.width/x->duration[x->last_state];
+
+
+ x->w.pointery = ypos;
+ //x->w.pointery = text_ypix(&x->x_obj,glist) + (1.f - (x->finalvalues[i] - yBase) / ySize) * yscale;
+ }
+ #ifdef DEBUG
+ post("pointery =%f",x->w.pointery);
+ post("insertpos =%f",insertpos);
+ #endif
+ x->w.grabbed = insertpos;
+ return insertpos;
+}
+
+static void breakpoints_create_doodles(t_breakpoints *x, t_glist *glist)
+{
+ float xscale,yscale;
+ int xpos,ypos;
+ int i;
+ char guistr[255];
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+ float yvalue;
+
+ xscale = x->w.width/x->duration[x->last_state];
+ yscale = x->w.height;
+
+ xpos = text_xpix(&x->x_obj,glist);
+ ypos = (int) (text_ypix(&x->x_obj,glist) + x->w.height);
+ for (i=0;i<=x->last_state;i++) {
+ yvalue = (x->finalvalues[i] - yBase) / ySize * yscale;
+ sprintf(guistr,".x%x.c create oval %d %d %d %d -tags %xD%d",(unsigned int)glist_getcanvas(glist),
+ (int) (xpos+(x->duration[i] * xscale) - 2),
+ (int) (ypos - yvalue - 2),
+ (int) (xpos+(x->duration[i] * xscale)+2),
+ (int) (ypos - yvalue + 2),
+ (unsigned int)x,i);
+
+ if (i == x->w.grabbed) {
+ strcat(guistr," -fill red\n");
+ } else {
+ strcat(guistr," -fill "LINECOLOR"\n");
+ }
+ sys_vgui("%s",guistr);
+ }
+ x->w.numdoodles = i;
+}
+
+
+static void breakpoints_delete_doodles(t_breakpoints *x, t_glist *glist)
+{
+ int i;
+ for (i=0;i<=x->w.numdoodles;i++) {
+ sys_vgui(".x%x.c delete %xD%d\n",glist_getcanvas(glist),x,i);
+ }
+}
+
+static void breakpoints_update_doodles(t_breakpoints *x, t_glist *glist)
+{
+
+ breakpoints_delete_doodles(x,glist);
+/* LATER only create new doodles if necessary */
+ breakpoints_create_doodles(x, glist);
+}
+
+
+static void breakpoints_delnum(t_breakpoints *x)
+{
+ sys_vgui(".x%x.c delete %xT\n",glist_getcanvas(x->w.glist),x);
+
+}
+
+
+static void breakpoints_shownum(t_breakpoints *x,t_glist* glist)
+{
+ float xscale,yscale;
+ int xpos,ypos;
+ int i= x->w.grabbed;
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+
+ xscale = x->w.width/x->duration[x->last_state];
+ yscale = x->w.height;
+
+ xpos = text_xpix(&x->x_obj,glist);
+ ypos = (int) (text_ypix(&x->x_obj,glist) + x->w.height);
+
+ breakpoints_delnum(x);
+
+ sys_vgui(".x%x.c create text %d %d -text %.2fx%.2f -tags %xT\n",
+ (unsigned int)glist_getcanvas(x->w.glist),
+
+ (int) (xpos+(x->duration[i] * xscale) +3),
+ (int) (ypos - (x->finalvalues[i]-yBase)/ySize*yscale - 10),
+
+ x->finalvalues[i],
+ x->duration[i],
+ (unsigned int)x);
+ clock_delay(x->w.numclock,700);
+}
+
+
+
+static void breakpoints_create(t_breakpoints *x, t_glist *glist)
+{
+ int i;
+ static char buf[1024];
+ float xscale,yscale;
+ int xpos,ypos;
+ char num[40];
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+
+ xpos = text_xpix(&x->x_obj,glist);
+ ypos = (int) text_ypix(&x->x_obj,glist);
+ x->w.numclock = clock_new(x, (t_method) breakpoints_delnum);
+ sys_vgui(".x%x.c create rectangle \
+%d %d %d %d -tags %xS -fill "BACKGROUNDCOLOR" -width "BACKGROUNDWIDTH"\n",
+ glist_getcanvas(glist),
+ xpos-BORDER, ypos-BORDER,
+ xpos + x->w.width+2*BORDER, ypos + x->w.height+2*BORDER,
+ x);
+
+ xscale = x->w.width/x->duration[x->last_state];
+ yscale = x->w.height;
+
+ sprintf(buf,".x%x.c create line",(unsigned int)glist_getcanvas(glist));
+ for (i=0;i<=x->last_state;i++) {
+ sprintf(num," %d %d ",(int)(xpos + x->duration[i]*xscale),
+ (int)(ypos + x->w.height- (x->finalvalues[i]-yBase)/ySize*yscale));
+ strcat(buf,num);
+ }
+
+ sprintf(num,"-tags %pP -fill "LINECOLOR"\n",x);
+ strcat(buf,num);
+ sys_vgui("%s",buf);
+ breakpoints_create_doodles(x,glist);
+}
+
+
+static void breakpoints_update(t_breakpoints *x, t_glist *glist)
+{
+int i;
+ static char buf[1024];
+ float xscale,yscale;
+ char num[40];
+ int xpos = text_xpix(&x->x_obj,glist);
+ int ypos = text_ypix(&x->x_obj,glist);
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+
+ sys_vgui(".x%x.c coords %xS \
+%d %d %d %d\n",
+ glist_getcanvas(glist), x,
+ xpos - BORDER, ypos -BORDER,
+ xpos + x->w.width+2*BORDER, ypos + x->w.height+2*BORDER);
+
+
+ xscale = x->w.width/x->duration[x->last_state];
+ yscale = x->w.height;
+
+ sprintf(buf,".x%x.c coords %pP",(unsigned int)glist_getcanvas(glist),x);
+
+ for (i=0;i<=x->last_state;i++) {
+ sprintf(num," %d %d ",(int)(xpos + x->duration[i]*xscale),
+ (int) (ypos + x->w.height - (x->finalvalues[i]-yBase)/ySize*yscale));
+ strcat(buf,num);
+ }
+ strcat(buf,"\n");
+ sys_vgui("%s",buf);
+ breakpoints_update_doodles(x,glist);
+ draw_inlets(x, glist, 0,1,3);
+}
+
+
+
+void breakpoints_drawme(t_breakpoints *x, t_glist *glist, int firsttime)
+{
+
+ if (firsttime) breakpoints_create(x,glist);
+ else breakpoints_update(x,glist);
+
+ draw_inlets(x, glist, firsttime, 1,3);
+}
+
+
+
+
+void breakpoints_erase(t_breakpoints* x,t_glist* glist)
+{
+ int n;
+ sys_vgui(".x%x.c delete %xS\n",
+ glist_getcanvas(glist), x);
+
+ sys_vgui(".x%x.c delete %pP\n",
+ glist_getcanvas(glist), x);
+
+ if (x->r_sym == &s_) {
+ sys_vgui(".x%x.c delete %xi0\n",glist_getcanvas(glist),x);
+ sys_vgui(".x%x.c delete %xo0\n",glist_getcanvas(glist),x);
+ sys_vgui(".x%x.c delete %xo1\n",glist_getcanvas(glist),x);
+ sys_vgui(".x%x.c delete %xo2\n",glist_getcanvas(glist),x);
+ }
+ breakpoints_delete_doodles(x,glist);
+}
+
+
+
+/* ------------------------ breakpoints widgetbehaviour----------------------------- */
+
+
+static void breakpoints_getrect(t_gobj *z, t_glist *owner,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ int width, height;
+ t_breakpoints* s = (t_breakpoints*)z;
+
+ width = s->w.width + 2*BORDER;
+ height = s->w.height + 2*BORDER;
+ *xp1 = text_xpix(&s->x_obj,owner)-BORDER;
+ *yp1 = text_ypix(&s->x_obj,owner)-BORDER;
+ *xp2 = text_xpix(&s->x_obj,owner) + width ; //+ 4
+ *yp2 = text_ypix(&s->x_obj,owner) + height ; //+ 4
+}
+
+static void breakpoints_displace(t_gobj *z, t_glist *glist,
+ int dx, int dy)
+{
+ t_breakpoints *x = (t_breakpoints *)z;
+ x->x_obj.te_xpix += dx;
+ x->x_obj.te_ypix += dy;
+
+ breakpoints_drawme(x, glist, 0);
+ canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x);
+}
+
+static void breakpoints_select(t_gobj *z, t_glist *glist, int state)
+{
+ t_breakpoints *x = (t_breakpoints *)z;
+ sys_vgui(".x%x.c itemconfigure %xS -fill %s\n", glist,
+ x, (state? "blue" : BACKGROUNDCOLOR));
+}
+
+
+static void breakpoints_activate(t_gobj *z, t_glist *glist, int state)
+{
+/* t_text *x = (t_text *)z;
+ t_rtext *y = glist_findrtext(glist, x);
+ if (z->g_pd != gatom_class) rtext_activate(y, state);*/
+}
+
+static void breakpoints_delete(t_gobj *z, t_glist *glist)
+{
+ t_text *x = (t_text *)z;
+ canvas_deletelinesfor(glist_getcanvas(glist), x);
+}
+
+
+static void breakpoints_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_breakpoints* s = (t_breakpoints*)z;
+ if (vis)
+ breakpoints_drawme(s, glist, 1);
+ else
+ breakpoints_erase(s,glist);
+}
+
+/*
+
+static void breakpoints_save(t_gobj *z, t_binbuf *b)
+{
+ t_breakpoints *x = (t_breakpoints *)z;
+ binbuf_addv(b, "ssiisiiffss", gensym("#X"), gensym("obj"),
+ (t_int)x->x_obj.te_xpix, (t_int)x->x_obj.te_ypix,
+ atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)),
+ x->w.width,x->w.height,x->max,x->min,x->r_sym,x->s_sym);
+ binbuf_addv(b, ";");
+}
+
+*/
+
+static void breakpoints_followpointer(t_breakpoints* x,t_glist* glist)
+{
+ float dur;
+ float xscale = x->duration[x->last_state]/x->w.width;
+ float ySize = x->max - x->min;
+ float yBase = x->min;
+
+ if ((x->w.grabbed > 0) && (x->w.grabbed < x->last_state)) {
+
+ dur = (x->w.pointerx - text_xpix(&x->x_obj,glist))*xscale;
+ if (dur < x->duration[x->w.grabbed-1])
+ dur = x->duration[x->w.grabbed-1];
+ if (dur > x->duration[x->w.grabbed+1])
+ dur = x->duration[x->w.grabbed+1];
+
+ x->duration[x->w.grabbed] = dur;
+ }
+
+ float grabbed = (1.0f - (x->w.pointery - (float)text_ypix(&x->x_obj,glist))/(float)x->w.height);
+ #ifdef DEBUG
+ post("grabbed =%f",grabbed);
+ #endif
+
+ if (grabbed < 0.0)
+ grabbed= 0.0;
+ else if (grabbed > 1.0)
+ grabbed= 1.0;
+
+ x->finalvalues[x->w.grabbed] = grabbed * ySize + yBase;
+
+
+ outlet_bang(x->out3);
+ if (x->c_sym != &s_) pd_bang(x->c_sym->s_thing);
+
+}
+
+
+void breakpoints_motion(t_breakpoints *x, t_floatarg dx, t_floatarg dy)
+{
+ if (x->w.shift) {
+ x->w.pointerx+=dx/1000.f;
+ x->w.pointery+=dy/1000.f;
+ }
+ else
+ {
+ x->w.pointerx+=dx;
+ x->w.pointery+=dy;
+ }
+ if (!x->resizing)
+ breakpoints_followpointer(x,x->w.glist);
+ else {
+ x->w.width+=dx;
+ x->w.height+=dy;
+ }
+ breakpoints_shownum(x,x->w.glist);
+ breakpoints_update(x,x->w.glist);
+}
+
+void breakpoints_key(t_breakpoints *x, t_floatarg f)
+{
+ if (f == 8.0 && x->w.grabbed < x->last_state && x->w.grabbed > 0) {
+ int i;
+
+ for (i=x->w.grabbed;i<=x->last_state;i++) {
+ x->duration[i] = x->duration[i+1];
+ x->finalvalues[i] = x->finalvalues[i+1];
+ }
+
+ x->last_state--;
+ x->w.grabbed--;
+ breakpoints_update(x,x->w.glist);
+ outlet_bang(x->out3);
+ if (x->c_sym != &s_) pd_bang(x->c_sym->s_thing);
+ }
+}
+
+
+/*
+static int bng_newclick(t_gobj *z, struct _glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit)
+{
+ if(doit)
+ bng_click((t_bng *)z, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, 0, (t_floatarg)alt);
+ return (1);
+}
+*/
+
+static int breakpoints_newclick(t_breakpoints *x, struct _glist *glist,
+ int xpos, int ypos, int shift, int alt, int dbl, int doit)
+{
+ // check if user wants to resize
+ float wxpos = text_xpix(&x->x_obj,glist);
+ float wypos = (text_ypix(&x->x_obj,glist));
+
+ if (doit){
+
+ #ifdef DEBUG
+
+ post("clicked");
+ #endif
+
+
+ /*
+
+ if ( (xpos >= wxpos + BORDER) && (xpos <= wxpos + x->w.width - BORDER) \
+ && (ypos >= wypos + BORDER) && (ypos <= wypos + x->w.height - BORDER) ) {
+ */
+
+
+ if ( (xpos >= wxpos ) && (xpos <= wxpos + x->w.width ) \
+ && (ypos >= wypos ) && (ypos <= wypos + x->w.height ) ) {
+ #ifdef DEBUG
+ post("inside");
+ #endif
+
+ breakpoints_next_doodle(x,glist,xpos,ypos);
+
+ glist_grab(x->w.glist, &x->x_obj.te_g, (t_glistmotionfn) breakpoints_motion,
+ (t_glistkeyfn) breakpoints_key, xpos, ypos);
+
+ x->w.shift = shift;
+ breakpoints_followpointer(x,glist);
+ breakpoints_shownum(x,glist);
+ breakpoints_update(x,glist);
+
+
+ }
+
+ }
+ return (1);
+}
+
+/*
+static int breakpoints_newclick(t_breakpoints *x, struct _glist *glist,
+ int xpos, int ypos, int shift, int alt, int dbl, int doit)
+{
+ //check if user wants to resize
+ float wxpos = text_xpix(&x->x_obj,glist);
+ float wypos = (int) (text_ypix(&x->x_obj,glist) + x->w.height);
+
+ if (doit){
+ breakpoints_next_doodle(x,glist,xpos,ypos);
+
+ glist_grab(x->w.glist, &x->x_obj.te_g, (t_glistmotionfn) breakpoints_motion,
+ (t_glistkeyfn) breakpoints_key, xpos, ypos);
+
+ x->resizing = 0;
+ if (x->resizeable && (xpos > wxpos + x->w.width) &&
+ (ypos > wypos)) {
+ x->resizing = 1;
+
+ }
+
+ if (xpos > wxpos + BORDER && (xpos < wxpos + x->w.width - BORDER) \
+ ypos > wypos + BORDER && (ypos < wypos + x->w.height - BORDER) ) {
+ x->w.shift = shift;
+ breakpoints_followpointer(x,glist);
+ breakpoints_shownum(x,glist);
+ breakpoints_update(x,glist);
+ }
+ }
+ return (1);
+}
+
+*/
+