From bbde9edb23856238349150fd1038d3a540a2bd15 Mon Sep 17 00:00:00 2001 From: Thomas O Fredericks Date: Mon, 31 Mar 2008 15:41:33 +0000 Subject: Added breakpoint and breakpoints to tof externals svn path=/trunk/externals/tof/; revision=9639 --- help/breakpoints-help.pd | 86 +++++++ help/breakpoints~-help.pd | 54 ++++ src/Makefile | 61 +++++ src/breakpoints.c | 449 +++++++++++++++++++++++++++++++++ src/breakpoints~.c | 479 ++++++++++++++++++++++++++++++++++++ src/breakpoints~.h | 63 +++++ src/g_canvas.h | 615 ++++++++++++++++++++++++++++++++++++++++++++++ src/w_breakpoints.h | 569 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 2376 insertions(+) create mode 100755 help/breakpoints-help.pd create mode 100755 help/breakpoints~-help.pd create mode 100755 src/Makefile create mode 100755 src/breakpoints.c create mode 100755 src/breakpoints~.c create mode 100755 src/breakpoints~.h create mode 100755 src/g_canvas.h create mode 100755 src/w_breakpoints.h 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 */ + +#include + +//#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 + +/* + 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 */ + +#include + +//#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 + +/* + 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 +#include +#include +#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); +} + +*/ + -- cgit v1.2.1