From 5285f098b0e14c73c1d451be6eadd9acab3adccd Mon Sep 17 00:00:00 2001 From: Thomas O Fredericks Date: Fri, 4 Jun 2010 17:38:55 +0000 Subject: Added a list accumulator svn path=/trunk/externals/tof/; revision=13598 --- src/list_accum-help.pd | 27 ++++++++++ src/list_accum.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 src/list_accum-help.pd create mode 100644 src/list_accum.c diff --git a/src/list_accum-help.pd b/src/list_accum-help.pd new file mode 100644 index 0000000..e7795ba --- /dev/null +++ b/src/list_accum-help.pd @@ -0,0 +1,27 @@ +#N canvas 1298 133 478 349 10; +#X obj 56 223 tof/list_accum; +#X msg 77 158 1 2 3 4 5 6; +#X obj 55 86 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X obj 54 288 print; +#X floatatom 69 131 5 0 0 0 - - -; +#X msg 159 158 a b c d; +#X obj 171 194 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 140 256 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X text 35 36 Tags: lists; +#X text 36 5 Description: Accumulates incomming atoms into one big +list; +#X text 113 135 Inlet 1 \, anything: Accumulate atoms; +#X text 192 194 Inlet 2 \, bang: Clear accumulated atoms; +#X text 76 85 Inlet 1 \, bang: Output and clear accumulated atoms; +#X text 160 254 Outlet 2 \, bang: Nothing accumulated (empty); +#X text 93 288 Outlet 1 \, list: Accumulated atoms; +#X connect 0 0 3 0; +#X connect 0 1 7 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 1; diff --git a/src/list_accum.c b/src/list_accum.c new file mode 100644 index 0000000..48e3e7a --- /dev/null +++ b/src/list_accum.c @@ -0,0 +1,139 @@ +#include "m_pd.h" +//#include +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) + +// The maxsize should match the maximum value of an int (2147483647) +#define MAXSIZE 2147483647 +//#define MAXSIZE 20 + + + + +static t_class *list_accum_class; + +typedef struct _list_accum { + t_object x_obj; + int got_data; + t_outlet* outlet1; + t_outlet* outlet2; + int mem_size; + int ac; + t_atom* av; +} t_list_accum; + + + + +// Bang: output accumulated list +static void list_accum_bang(t_list_accum *x) +{ + + if ( x->got_data) { + x->got_data = 0; + outlet_list(x->outlet1,&s_list,x->ac,x->av); + } else { + outlet_bang(x->outlet2); + } + + +} + +void list_accum_clear(t_list_accum *x) { + x->got_data = 0; + +} + + +void list_accum_anything(t_list_accum *x, t_symbol* s, int ac, t_atom* av) +{ + // COPY + + if ( !x->got_data ) x->ac =0; + x->got_data = 1; + + + int do_selector = ( s != &s_list && s != &s_float && s != &s_symbol ); + int ac_prev = x->ac; + unsigned int ac_new = x->ac + ac + do_selector; //One more for the selector + + + if ( ac_new < MAXSIZE ) { + + + x->ac = ac_new; + + // Resize memory if required and add 10 atoms just in case + if(x->ac > x->mem_size) { + x->av = resizebytes(x->av, x->mem_size * sizeof(*(x->av)), + (10 + x->ac) * sizeof(*(x->av))); + x->mem_size = 10 + x->ac; + } + + t_atom* dst = x->av + ac_prev; //Offset destination by current size + + // Copy selector + if ( do_selector ) { + SETSYMBOL(dst, s); + dst++; + } + // Copy atoms + while(ac--) *dst++ = *av++; + + } else { + pd_error(x, "[list_accum]: Input was ignored because maximum size(%d) would be exceeded.", MAXSIZE); + } + +} + + +static void list_accum_free(t_list_accum *x) +{ + freebytes(x->av, x->mem_size * sizeof(*(x->av))); +} + +void *list_accum_new(t_symbol *s, int argc, t_atom *argv) +{ + t_list_accum *x = (t_list_accum *)pd_new(list_accum_class); + + //x->iterating = 0; + /* + x->mode = 0; + + + if (argc && IS_A_SYMBOL(argv,0) ) { + t_symbol* type = atom_getsymbol(argv); + if (type->s_name == gensym("prepend") ) { + x->mode = 1; + } + } + */ + + // Initialize memory + x->mem_size = 10; + x->ac = 0; + x->av = getbytes(x->mem_size * sizeof(*(x->av))); + + x->outlet1 = outlet_new(&x->x_obj, &s_list); + x->outlet2 = outlet_new(&x->x_obj, &s_bang); + + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("clear")); + + return (void *)x; +} + +void list_accum_setup(void) { + list_accum_class = class_new(gensym("list_accum"), + (t_newmethod)list_accum_new, + (t_method)list_accum_free, sizeof(t_list_accum), + CLASS_DEFAULT, + A_GIMME, 0); + + class_addbang (list_accum_class, list_accum_bang); + class_addmethod(list_accum_class, (t_method)list_accum_clear, gensym("clear"),0); + class_addanything (list_accum_class, list_accum_anything); + + //class_addlist (list_accum_class, list_accum_list); + +} -- cgit v1.2.1