[PD-dev] 0.48.0 release status

Christof Ressi christof.ressi at gmx.at
Sat Jul 22 14:21:50 CEST 2017


Yeah, let's save this for later. In the meantime I'll try to hunt down the pointer bugs...

> Gesendet: Freitag, 21. Juli 2017 um 19:58 Uhr
> Von: "Miller Puckette" <msp at ucsd.edu>
> An: "Christof Ressi" <christof.ressi at gmx.at>
> Cc: "Dan Wilcox" <danomatika at gmail.com>, pd-dev at iem.at
> Betreff: Re: [PD-dev] 0.48.0 release status
>
> OK... for now, I renamed "range" to "get" (did it right away to avoid the
> necessity of keeping the other name for compatibility).  We can mess with the
> other stuff later.
> 
> Not sure about the pointer issues, will just hope that doesn't bite us before
> I can look closer at it.
> 
> Meanwhile, yeah, I can think of losts of cool things to try (e.g., "sort")
> 
> cheers
> Miller
> 
> On Fri, Jul 21, 2017 at 06:20:49PM +0200, Christof Ressi wrote:
> > Thanks for your answer! I guess it doesn't have high priority but anyway, the thing is this:
> > 
> > I'm really happy about [list store] but I think it can be way more expressive. My idea was to take the interface of [text] and [array] to add more methods. 
> > 
> > First, I renamed [range( to [get( (but kept the old method around as an alias) because it's structurally very similar to [text get] and [array get].
> > 
> > Then I added a method [set <f> ...( which lets you overwrite atoms, just like [text set] and [array set]. the first float is the index, followed by the atoms you want to copy.
> > 
> > Then I added a general [insert <f> ...( method which lets you insert atoms, where the first float is the index, followed by the atoms you want to insert *before* that index. A large index lets you append atoms. I kept [prepend ...( and [append ...( as shortcuts for those two special cases.
> > 
> > Finally I added a [delete <f> <f>( method where the first float is the index to start deleting and the second float is the number of floats to delete.
> > 
> > ---
> > 
> > These methods would turn [list store] into a powerful dynamically sized type-agnostic array - which we don't have in Pd yet! [text] comes closest, but it doesn't handle pointers and it bashes everything to binbufs which sometimes leads to unexpected or undesired behaviour.
> > 
> > Please find my version of x_list.c(which also includes the bug fix that you've already applied) and a messy test patch attached. I didn't have much time...
> > 
> > The methods works well with floats and symbols but there are mysterious bugs with pointers. Not only with my new method but also with your [range( method (which I didn't change). For example, sequencing a list of pointers creates 'consistency check failed' errors with [print] and sometimes there are crashes with segmentation faults. 
> > 
> > Also, I'm wondering if memmove() and realloc() is really safe with arrays of t_listelem because a gpointer atom l_a inside t_listelem points to l_a. when the array changes location in memory, won't the pointer point to the wrong location?
> > 
> > I know there are more important things to do right now. Just have look when you have time. 
> > 
> > Thanks!
> > 
> > Christof
> > 
> > 
> > 
> > 
> > 
> > 
> > > Gesendet: Freitag, 21. Juli 2017 um 17:26 Uhr
> > > Von: "Miller Puckette" <msp at ucsd.edu>
> > > An: "Christof Ressi" <christof.ressi at gmx.at>
> > > Cc: "Dan Wilcox" <danomatika at gmail.com>, pd-dev at iem.at
> > > Betreff: Re: [PD-dev] 0.48.0 release status
> > >
> > > Always open to bug reports (although swamped right now I'm afraid, will only
> > > get to things that are either urgent or easy :)
> > > 
> > > I've already fixed "list_store_range" following your earlier report, thanks.
> > > 
> > > Miller
> > > 
> > > On Fri, Jul 21, 2017 at 01:05:15PM +0200, Christof Ressi wrote:
> > > > I got some more feedback/code for [list store], apart from the list_store_range bug I've already reported on the list. Is there some time left for you guys to review it? I can send it in a couple of hours. I'm travelling right now. 
> > > > 
> > > > Christof
> > > > 
> > > > > Gesendet: Freitag, 21. Juli 2017 um 11:54 Uhr
> > > > > Von: "Dan Wilcox" <danomatika at gmail.com>
> > > > > An: pd-dev at iem.at
> > > > > Cc: "Miller Puckette" <msp at ucsd.edu>
> > > > > Betreff: [PD-dev] 0.48.0 release status
> > > > >
> > > > > Ok all, at this point we've nailed most of the bugs and feedback so far. The latest PR is https://github.com/pure-data/pure-data/pull/123 <https://github.com/pure-data/pure-data/pull/123>
> > > > > 
> > > > > As far as I can tell, the only remaining things which could be done/included for the release are:
> > > > > 
> > > > > Small Stuff
> > > > > 
> > > > > * Remove midiin & sysexin Windows warnings in x_midi.c (& update help file)
> > > > > 
> > > > > (Optional) Big Stuff
> > > > > 
> > > > > * Adopt DejaVu Sans Mono a the default font -> this is in the dejavu branch https://github.com/pure-data/pure-data/pull/42 <https://github.com/pure-data/pure-data/pull/42>
> > > > >   This is mainly for mac & Linux, Windows support will need to be added later as mentioned in the discussion. It also fixes the bad Monaco rendering on
> > > > >   retina screens at small font sizes.
> > > > > * Update the icon -> see my pd-icon repo https://github.com/pure-data/pd-icon <https://github.com/pure-data/pd-icon> & the recent thread on the pd-list
> > > > > 
> > > > > There may be more things, but I think I'm done on my end for now. We could do one final test release after this, but hopefully the feedback bugs will all have been fixed.
> > > > > 
> > > > > --------
> > > > > Dan Wilcox
> > > > > @danomatika <http://twitter.com/danomatika>
> > > > > danomatika.com <http://danomatika.com/>
> > > > > robotcowboy.com <http://robotcowboy.com/>
> > > > > 
> > > > > 
> > > > > 
> > > > > _______________________________________________
> > > > > Pd-dev mailing list
> > > > > Pd-dev at lists.iem.at
> > > > > https://lists.puredata.info/listinfo/pd-dev
> > > > >
> > > > 
> > > > _______________________________________________
> > > > Pd-dev mailing list
> > > > Pd-dev at lists.iem.at
> > > > https://lists.puredata.info/listinfo/pd-dev
> > > 
> 
> 
> > /* Copyright (c) 1997- Miller Puckette and others.
> > * For information on usage and redistribution, and for a DISCLAIMER OF ALL
> > * WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
> > 
> > #include "m_pd.h"
> > #include <string.h>
> > 
> > #ifdef _WIN32
> > # include <malloc.h> /* MSVC or mingw on windows */
> > #elif defined(__linux__) || defined(__APPLE__)
> > # include <alloca.h> /* linux, mac, mingw, cygwin */
> > #else
> > # include <stdlib.h> /* BSDs for example */
> > #endif
> > 
> > #ifndef HAVE_ALLOCA     /* can work without alloca() but we never need it */
> > #define HAVE_ALLOCA 1
> > #endif
> > 
> > #define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */
> > 
> > /* the "list" object family.
> > 
> >     list append - append a list to another
> >     list prepend - prepend a list to another
> >     list split - first n elements to first outlet, rest to second outlet
> >     list trim - trim off "list" selector
> >     list length - output number of items in list
> >     list fromsymbol - "explode" a symbol into a list of character codes
> > 
> > Need to think more about:
> >     list foreach - spit out elements of a list one by one (also in reverse?)
> >     list reverse - permute elements of a list back to front
> >     list cat - build a list by accumulating elements
> > 
> > Probably don't need:
> >     list first - output first n elements.
> >     list last - output last n elements
> >     list nth - nth item in list, counting from zero
> >     list array - get items from a named array as a list
> >     list pack - synonym for 'pack'
> >     list unpack - synonym for 'unpack'
> > */
> > 
> > /* -------------- utility functions: storage, copying  -------------- */
> >     /* List element for storage.  Keep an atom and, in case it's a pointer,
> >         an associated 'gpointer' to protect against stale pointers. */
> > typedef struct _listelem
> > {
> >     t_atom l_a;
> >     t_gpointer l_p;
> > } t_listelem;
> > 
> > typedef struct _alist
> > {
> >     t_pd l_pd;          /* object to point inlets to */
> >     int l_n;            /* number of items */
> >     int l_npointer;     /* number of pointers */
> >     t_listelem *l_vec;  /* pointer to items */
> > } t_alist;
> > 
> > #if HAVE_ALLOCA
> > #define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ?  \
> >         alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom))))
> > #define ATOMS_FREEA(x, n) ( \
> >     ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0)))
> > #else
> > #define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom)))
> > #define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom)))
> > #endif
> > 
> > static void atoms_copy(int argc, t_atom *from, t_atom *to)
> > {
> >     int i;
> >     for (i = 0; i < argc; i++)
> >         to[i] = from[i];
> > }
> > 
> > /* ------------- fake class to divert inlets to ----------------- */
> > 
> > t_class *alist_class;
> > 
> > static void alist_init(t_alist *x)
> > {
> >     x->l_pd = alist_class;
> >     x->l_n = x->l_npointer = 0;
> >     x->l_vec = 0;
> > }
> > 
> > static void alist_clear(t_alist *x)
> > {
> >     int i;
> >     for (i = 0; i < x->l_n; i++)
> >     {
> >         if (x->l_vec[i].l_a.a_type == A_POINTER)
> >             gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer);
> >     }
> >     if (x->l_vec)
> >         freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec));
> > }
> > 
> > static void alist_copyin(t_alist *x, t_symbol *s, int argc, t_atom *argv,
> >     int where)
> > {
> >     int i, j;
> >     for (i = 0, j = where; i < argc; i++, j++)
> >     {
> >         x->l_vec[j].l_a = argv[i];
> >         if (x->l_vec[j].l_a.a_type == A_POINTER)
> >         {
> >             x->l_npointer++;
> >             gpointer_copy(x->l_vec[j].l_a.a_w.w_gpointer, &x->l_vec[j].l_p);
> >             x->l_vec[j].l_a.a_w.w_gpointer = &x->l_vec[j].l_p;
> >         }
> >     }
> > }
> > 
> >     /* set contents to a list */
> > static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
> > {
> >     alist_clear(x);
> >     if (!(x->l_vec = (t_listelem *)getbytes(argc * sizeof(*x->l_vec))))
> >     {
> >         x->l_n = 0;
> >         error("list: out of memory");
> >         return;
> >     }
> >     x->l_n = argc;
> >     x->l_npointer = 0;
> >     alist_copyin(x, s, argc, argv, 0);
> > }
> > 
> >     /* set contents to an arbitrary non-list message */
> > static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
> > {
> >     int i;
> >     alist_clear(x);
> >     if (!(x->l_vec = (t_listelem *)getbytes((argc+1) * sizeof(*x->l_vec))))
> >     {
> >         x->l_n = 0;
> >         error("list_alloc: out of memory");
> >         return;
> >     }
> >     x->l_n = argc+1;
> >     x->l_npointer = 0;
> >     SETSYMBOL(&x->l_vec[0].l_a, s);
> >     for (i = 0; i < argc; i++)
> >     {
> >         x->l_vec[i+1].l_a = argv[i];
> >         if (x->l_vec[i+1].l_a.a_type == A_POINTER)
> >         {
> >             x->l_npointer++;
> >             gpointer_copy(x->l_vec[i+1].l_a.a_w.w_gpointer, &x->l_vec[i+1].l_p);
> >             x->l_vec[i+1].l_a.a_w.w_gpointer = &x->l_vec[i+1].l_p;
> >         }
> >     }
> > }
> > 
> > static void alist_toatoms(t_alist *x, t_atom *to, int onset, int count)
> > {
> >     int i;
> >     for (i = 0; i < count; i++)
> >         to[i] = x->l_vec[onset + i].l_a;
> > }
> > 
> > 
> > static void alist_clone(t_alist *x, t_alist *y, int onset, int count)
> > {
> >     int i;
> >     y->l_pd = alist_class;
> >     y->l_n = count;
> >     y->l_npointer = 0;
> >     if (!(y->l_vec = (t_listelem *)getbytes(y->l_n * sizeof(*y->l_vec))))
> >     {
> >         y->l_n = 0;
> >         error("list_alloc: out of memory");
> >     }
> >     else for (i = 0; i < count; i++)
> >     {
> >         y->l_vec[i].l_a = x->l_vec[onset + i].l_a;
> >         if (y->l_vec[i].l_a.a_type == A_POINTER)
> >         {
> >             gpointer_copy(y->l_vec[i].l_a.a_w.w_gpointer, &y->l_vec[i].l_p);
> >             y->l_vec[i].l_a.a_w.w_gpointer = &y->l_vec[i].l_p;
> >             y->l_npointer++;
> >         }
> >     }
> > }
> > 
> > static void alist_setup(void)
> > {
> >     alist_class = class_new(gensym("list inlet"),
> >         0, 0, sizeof(t_alist), 0, 0);
> >     class_addlist(alist_class, alist_list);
> >     class_addanything(alist_class, alist_anything);
> > }
> > 
> > /* ------------- list append --------------------- */
> > 
> > t_class *list_append_class;
> > 
> > typedef struct _list_append
> > {
> >     t_object x_obj;
> >     t_alist x_alist;
> > } t_list_append;
> > 
> > static void *list_append_new(t_symbol *s, int argc, t_atom *argv)
> > {
> >     t_list_append *x = (t_list_append *)pd_new(list_append_class);
> >     alist_init(&x->x_alist);
> >     alist_list(&x->x_alist, 0, argc, argv);
> >     outlet_new(&x->x_obj, &s_list);
> >     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
> >     return (x);
> > }
> > 
> > static void list_append_list(t_list_append *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     int n, outc = x->x_alist.l_n + argc;
> >     ATOMS_ALLOCA(outv, outc);
> >     atoms_copy(argc, argv, outv);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
> >         alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_append_anything(t_list_append *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     int n, outc = x->x_alist.l_n + argc + 1;
> >     ATOMS_ALLOCA(outv, outc);
> >     SETSYMBOL(outv, s);
> >     atoms_copy(argc, argv, outv + 1);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
> >         alist_toatoms(&y, outv + 1 + argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv + 1 + argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_append_append(t_list_append *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
> >         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
> >         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
> >     {
> >         x->x_alist.l_n = 0;
> >         error("list: out of memory");
> >         return;
> >     }
> >     alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n);
> >     x->x_alist.l_n += argc;
> > }
> > 
> > static void list_append_prepend(t_list_append *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
> >         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
> >         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
> >     {
> >         x->x_alist.l_n = 0;
> >         error("list: out of memory");
> >         return;
> >     }
> >     memmove(x->x_alist.l_vec + argc, x->x_alist.l_vec,
> >         x->x_alist.l_n * sizeof(*x->x_alist.l_vec));
> >     alist_copyin(&x->x_alist, s, argc, argv, 0);
> >     x->x_alist.l_n += argc;
> > }
> > 
> > static void list_append_free(t_list_append *x)
> > {
> >     alist_clear(&x->x_alist);
> > }
> > 
> > static void list_append_setup(void)
> > {
> >     list_append_class = class_new(gensym("list append"),
> >         (t_newmethod)list_append_new, (t_method)list_append_free,
> >         sizeof(t_list_append), 0, A_GIMME, 0);
> >     class_addlist(list_append_class, list_append_list);
> >     class_addanything(list_append_class, list_append_anything);
> >     class_sethelpsymbol(list_append_class, &s_list);
> > }
> > 
> > /* ------------- list prepend --------------------- */
> > 
> > t_class *list_prepend_class;
> > 
> > typedef t_list_append t_list_prepend;
> > 
> > static void *list_prepend_new(t_symbol *s, int argc, t_atom *argv)
> > {
> >     t_list_prepend *x = (t_list_prepend *)pd_new(list_prepend_class);
> >     alist_init(&x->x_alist);
> >     alist_list(&x->x_alist, 0, argc, argv);
> >     outlet_new(&x->x_obj, &s_list);
> >     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
> >     return (x);
> > }
> > 
> > static void list_prepend_list(t_list_prepend *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     int n, outc = x->x_alist.l_n + argc;
> >     ATOMS_ALLOCA(outv, outc);
> >     atoms_copy(argc, argv, outv + x->x_alist.l_n);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
> >         alist_toatoms(&y, outv, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_prepend_anything(t_list_prepend *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     int n, outc = x->x_alist.l_n + argc + 1;
> >     ATOMS_ALLOCA(outv, outc);
> >     SETSYMBOL(outv + x->x_alist.l_n, s);
> >     atoms_copy(argc, argv, outv + x->x_alist.l_n + 1);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
> >         alist_toatoms(&y, outv, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n);
> >         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_prepend_free(t_list_prepend *x)
> > {
> >     alist_clear(&x->x_alist);
> > }
> > 
> > static void list_prepend_setup(void)
> > {
> >     list_prepend_class = class_new(gensym("list prepend"),
> >         (t_newmethod)list_prepend_new, (t_method)list_prepend_free,
> >         sizeof(t_list_prepend), 0, A_GIMME, 0);
> >     class_addlist(list_prepend_class, list_prepend_list);
> >     class_addanything(list_prepend_class, list_prepend_anything);
> >     class_sethelpsymbol(list_prepend_class, &s_list);
> > }
> > 
> > /* ------------- list store --------------------- */
> > 
> > t_class *list_store_class;
> > 
> > typedef struct _list_store
> > {
> >     t_object x_obj;
> >     t_alist x_alist;
> >     t_outlet *x_out1;
> >     t_outlet *x_out2;
> > } t_list_store;
> > 
> > static void *list_store_new(t_symbol *s, int argc, t_atom *argv)
> > {
> >     t_list_store *x = (t_list_store *)pd_new(list_store_class);
> >     alist_init(&x->x_alist);
> >     alist_list(&x->x_alist, 0, argc, argv);
> >     x->x_out1 = outlet_new(&x->x_obj, &s_list);
> >     x->x_out2 = outlet_new(&x->x_obj, &s_bang);
> >     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
> >     return (x);
> > }
> > 
> > static void list_store_list(t_list_store *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     int n, outc = x->x_alist.l_n + argc;
> >     ATOMS_ALLOCA(outv, outc);
> >     atoms_copy(argc, argv, outv);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
> >         alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_out1, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n);
> >         outlet_list(x->x_out1, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > /* insert atoms before a given index */
> > static void list_store_doinsert(t_list_store *x, int index, t_symbol *s, 
> >     int argc, t_atom *argv)
> > {
> > 	if (index < 0) index = 0; /* index = 0 -> prepend */
> > 	if (index > x->x_alist.l_n) index = x->x_alist.l_n; /* index >= length -> append */
> > 	
> > 	if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
> >         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
> >         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
> >     {
> >         x->x_alist.l_n = 0;
> >         error("list: out of memory");
> >         return;
> >     }
> > 	/* we don't need memmove for appending */
> > 	if (index < x->x_alist.l_n){
> >         memmove(x->x_alist.l_vec + index + argc, x->x_alist.l_vec + index, (x->x_alist.l_n - index) * sizeof(*x->x_alist.l_vec));
> > 	}
> >     alist_copyin(&x->x_alist, s, argc, argv, index);
> >     x->x_alist.l_n += argc;
> > }	
> > 
> > static void list_store_insert(t_list_store *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     if (argc < 2) return;
> > 	
> > 	/* first atom is the index where to start inserting atoms. */
> > 	int index = atom_getfloat(argv);
> > 	argc--; argv++;
> > 	/* insert remaining atoms */
> > 	list_store_doinsert(x, index, s, argc, argv);
> > }
> > 
> > static void list_store_append(t_list_store *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     list_store_doinsert(x, 1e+009, s, argc, argv);
> > }
> > 
> > static void list_store_prepend(t_list_store *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> > 	list_store_doinsert(x, 0, s, argc, argv);
> > }
> > 
> > static void list_store_delete(t_list_store *x, float f1, float f2)
> > {
> >     int index = f1;
> > 	int ndelete = f2;
> > 	
> > 	if (index < 0) index = 0; 
> > 	if (index >= x->x_alist.l_n) return; /* out of range: nothing to delete */
> > 	
> > 	int maxlength = x->x_alist.l_n - index;
> > 	if (ndelete > maxlength) ndelete = maxlength;
> > 	
> > 	/* first unset pointers */
> > 	if (x->x_alist.l_npointer)
> >     {
> > 	    t_listelem *vec = x->x_alist.l_vec;
> > 		for (int i = 0; i < ndelete; i++)
> >         {
> >             if (vec[index + i].l_a.a_type == A_POINTER)
> >             {
> >         	    gpointer_unset(vec[i].l_a.a_w.w_gpointer);
> > 				x->x_alist.l_npointer--;
> > 				post("remaining number of pointers: %d", x->x_alist.l_npointer);
> > 			}
> >         }
> > 	}
> > 	
> > 	/* then move atoms */
> >     memmove(x->x_alist.l_vec + index, x->x_alist.l_vec + index + ndelete, 
> >         (x->x_alist.l_n - index - ndelete) * sizeof(*x->x_alist.l_vec));
> > 	
> > 	x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
> >         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
> >         (x->x_alist.l_n - ndelete) * sizeof(*x->x_alist.l_vec));
> > 	
> >     x->x_alist.l_n -= ndelete;
> > }
> > 
> > static void list_store_set(t_list_store *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     if (argc < 2) return;
> > 	
> > 	/* first atom is the index where to start copying the atoms */
> > 	int index = atom_getfloat(argv);
> > 	if (index < 0) index = 0;
> > 	if (index > x->x_alist.l_n - 1) index = x->x_alist.l_n - 1;
> > 	argc--; argv++;
> > 	
> > 	/* copy remaining atoms */
> > 	int maxlength = x->x_alist.l_n - index;
> > 	/* for now we truncate. we could also append remaining atoms... */
> > 	if (argc > maxlength) argc = maxlength;
> > 	
> > 	/* first unset pointers */
> > 	if (x->x_alist.l_npointer)
> >     {
> >         t_listelem *vec = x->x_alist.l_vec;
> > 		for (int i = 0; i < argc; i++)
> >         {
> >             if (vec[index + i].l_a.a_type == A_POINTER)
> > 			{
> > 				gpointer_unset(vec[i+index].l_a.a_w.w_gpointer);
> > 				x->x_alist.l_npointer--;
> > 			}
> >         }			
> >     }
> > 	/* then copy */
> >     alist_copyin(&x->x_alist, s, argc, argv, index);
> > }
> > 
> > static void list_store_get(t_list_store *x, float f1, float f2)
> > {
> >     t_atom *outv;
> >     int onset = f1, outc = f2;
> >     if (onset < 0 || outc < 0)
> >     {
> >         pd_error(x, "list_store_range: negative range (%d %d)", onset, outc);
> >         return;
> >     }
> >     if (onset + outc > x->x_alist.l_n)
> >     {
> >         outlet_bang(x->x_out2);
> >         return;
> >     }
> >     ATOMS_ALLOCA(outv, outc);
> >     if (x->x_alist.l_npointer)
> >     {
> >         t_alist y;
> >         alist_clone(&x->x_alist, &y, onset, outc);
> >         alist_toatoms(&y, outv, onset, outc);
> >         outlet_list(x->x_out1, &s_list, outc, outv);
> >         alist_clear(&y);
> >     }
> >     else
> >     {
> >         alist_toatoms(&x->x_alist, outv, onset, outc);
> >         outlet_list(x->x_out1, &s_list, outc, outv);
> >     }
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_store_range(t_list_store *x, float f1, float f2)
> > {
> >     list_store_get(x, f1, f2);    
> > }
> > 
> > static void list_store_free(t_list_store *x)
> > {
> >     alist_clear(&x->x_alist);
> > }
> > 
> > static void list_store_setup(void)
> > {
> >     list_store_class = class_new(gensym("list store"),
> >         (t_newmethod)list_store_new, (t_method)list_store_free,
> >         sizeof(t_list_store), 0, A_GIMME, 0);
> >     class_addlist(list_store_class, list_store_list);
> > 	class_addmethod(list_store_class, (t_method)list_store_set,
> >         gensym("set"), A_GIMME, 0);
> >     class_addmethod(list_store_class, (t_method)list_store_get,
> >         gensym("get"), A_FLOAT, A_FLOAT, 0);
> > 	class_addmethod(list_store_class, (t_method)list_store_range,
> >         gensym("range"), A_FLOAT, A_FLOAT, 0); /* alias for "get" */
> > 	class_addmethod(list_store_class, (t_method)list_store_insert,
> >         gensym("insert"), A_GIMME, 0);
> >     class_addmethod(list_store_class, (t_method)list_store_append,
> >         gensym("append"), A_GIMME, 0);
> >     class_addmethod(list_store_class, (t_method)list_store_prepend,
> >         gensym("prepend"), A_GIMME, 0);
> > 	class_addmethod(list_store_class, (t_method)list_store_delete,
> >         gensym("delete"), A_FLOAT, A_FLOAT, 0);
> > 	
> >     class_sethelpsymbol(list_store_class, &s_list);
> > }
> > 
> > /* ------------- list split --------------------- */
> > 
> > t_class *list_split_class;
> > 
> > typedef struct _list_split
> > {
> >     t_object x_obj;
> >     t_float x_f;
> >     t_outlet *x_out1;
> >     t_outlet *x_out2;
> >     t_outlet *x_out3;
> > } t_list_split;
> > 
> > static void *list_split_new(t_floatarg f)
> > {
> >     t_list_split *x = (t_list_split *)pd_new(list_split_class);
> >     x->x_out1 = outlet_new(&x->x_obj, &s_list);
> >     x->x_out2 = outlet_new(&x->x_obj, &s_list);
> >     x->x_out3 = outlet_new(&x->x_obj, &s_list);
> >     floatinlet_new(&x->x_obj, &x->x_f);
> >     x->x_f = f;
> >     return (x);
> > }
> > 
> > static void list_split_list(t_list_split *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     int n = x->x_f;
> >     if (n < 0)
> >         n = 0;
> >     if (argc >= n)
> >     {
> >         outlet_list(x->x_out2, &s_list, argc-n, argv+n);
> >         outlet_list(x->x_out1, &s_list, n, argv);
> >     }
> >     else outlet_list(x->x_out3, &s_list, argc, argv);
> > }
> > 
> > static void list_split_anything(t_list_split *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     t_atom *outv;
> >     ATOMS_ALLOCA(outv, argc+1);
> >     SETSYMBOL(outv, s);
> >     atoms_copy(argc, argv, outv + 1);
> >     list_split_list(x, &s_list, argc+1, outv);
> >     ATOMS_FREEA(outv, argc+1);
> > }
> > 
> > static void list_split_setup(void)
> > {
> >     list_split_class = class_new(gensym("list split"),
> >         (t_newmethod)list_split_new, 0,
> >         sizeof(t_list_split), 0, A_DEFFLOAT, 0);
> >     class_addlist(list_split_class, list_split_list);
> >     class_addanything(list_split_class, list_split_anything);
> >     class_sethelpsymbol(list_split_class, &s_list);
> > }
> > 
> > /* ------------- list trim --------------------- */
> > 
> > t_class *list_trim_class;
> > 
> > typedef struct _list_trim
> > {
> >     t_object x_obj;
> > } t_list_trim;
> > 
> > static void *list_trim_new( void)
> > {
> >     t_list_trim *x = (t_list_trim *)pd_new(list_trim_class);
> >     outlet_new(&x->x_obj, &s_list);
> >     return (x);
> > }
> > 
> > static void list_trim_list(t_list_trim *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     if (argc < 1 || argv[0].a_type != A_SYMBOL)
> >         outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv);
> >     else outlet_anything(x->x_obj.ob_outlet, argv[0].a_w.w_symbol,
> >         argc-1, argv+1);
> > }
> > 
> > static void list_trim_anything(t_list_trim *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
> > }
> > 
> > static void list_trim_setup(void)
> > {
> >     list_trim_class = class_new(gensym("list trim"),
> >         (t_newmethod)list_trim_new, 0,
> >         sizeof(t_list_trim), 0, 0);
> >     class_addlist(list_trim_class, list_trim_list);
> >     class_addanything(list_trim_class, list_trim_anything);
> >     class_sethelpsymbol(list_trim_class, &s_list);
> > }
> > 
> > /* ------------- list length --------------------- */
> > 
> > t_class *list_length_class;
> > 
> > typedef struct _list_length
> > {
> >     t_object x_obj;
> > } t_list_length;
> > 
> > static void *list_length_new( void)
> > {
> >     t_list_length *x = (t_list_length *)pd_new(list_length_class);
> >     outlet_new(&x->x_obj, &s_float);
> >     return (x);
> > }
> > 
> > static void list_length_list(t_list_length *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     outlet_float(x->x_obj.ob_outlet, (t_float)argc);
> > }
> > 
> > static void list_length_anything(t_list_length *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     outlet_float(x->x_obj.ob_outlet, (t_float)argc+1);
> > }
> > 
> > static void list_length_setup(void)
> > {
> >     list_length_class = class_new(gensym("list length"),
> >         (t_newmethod)list_length_new, 0,
> >         sizeof(t_list_length), 0, 0);
> >     class_addlist(list_length_class, list_length_list);
> >     class_addanything(list_length_class, list_length_anything);
> >     class_sethelpsymbol(list_length_class, &s_list);
> > }
> > 
> > /* ------------- list fromsymbol --------------------- */
> > 
> > t_class *list_fromsymbol_class;
> > 
> > typedef struct _list_fromsymbol
> > {
> >     t_object x_obj;
> > } t_list_fromsymbol;
> > 
> > static void *list_fromsymbol_new( void)
> > {
> >     t_list_fromsymbol *x = (t_list_fromsymbol *)pd_new(list_fromsymbol_class);
> >     outlet_new(&x->x_obj, &s_list);
> >     return (x);
> > }
> > 
> > static void list_fromsymbol_symbol(t_list_fromsymbol *x, t_symbol *s)
> > {
> >     t_atom *outv;
> >     int n, outc = strlen(s->s_name);
> >     ATOMS_ALLOCA(outv, outc);
> >     for (n = 0; n < outc; n++)
> >         SETFLOAT(outv + n, (unsigned char)s->s_name[n]);
> >     outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
> >     ATOMS_FREEA(outv, outc);
> > }
> > 
> > static void list_fromsymbol_setup(void)
> > {
> >     list_fromsymbol_class = class_new(gensym("list fromsymbol"),
> >         (t_newmethod)list_fromsymbol_new, 0, sizeof(t_list_fromsymbol), 0, 0);
> >     class_addsymbol(list_fromsymbol_class, list_fromsymbol_symbol);
> >     class_sethelpsymbol(list_fromsymbol_class, &s_list);
> > }
> > 
> > /* ------------- list tosymbol --------------------- */
> > 
> > t_class *list_tosymbol_class;
> > 
> > typedef struct _list_tosymbol
> > {
> >     t_object x_obj;
> > } t_list_tosymbol;
> > 
> > static void *list_tosymbol_new( void)
> > {
> >     t_list_tosymbol *x = (t_list_tosymbol *)pd_new(list_tosymbol_class);
> >     outlet_new(&x->x_obj, &s_symbol);
> >     return (x);
> > }
> > 
> > static void list_tosymbol_list(t_list_tosymbol *x, t_symbol *s,
> >     int argc, t_atom *argv)
> > {
> >     int i;
> > #if HAVE_ALLOCA
> >     char *str = alloca(argc + 1);
> > #else
> >     char *str = getbytes(argc + 1);
> > #endif
> >     for (i = 0; i < argc; i++)
> >         str[i] = (char)atom_getfloatarg(i, argc, argv);
> >     str[argc] = 0;
> >     outlet_symbol(x->x_obj.ob_outlet, gensym(str));
> > #if HAVE_ALLOCA
> > #else
> >     freebytes(str, argc+1);
> > #endif
> > }
> > 
> > static void list_tosymbol_setup(void)
> > {
> >     list_tosymbol_class = class_new(gensym("list tosymbol"),
> >         (t_newmethod)list_tosymbol_new, 0, sizeof(t_list_tosymbol), 0, 0);
> >     class_addlist(list_tosymbol_class, list_tosymbol_list);
> >     class_sethelpsymbol(list_tosymbol_class, &s_list);
> > }
> > 
> > /* ------------- list ------------------- */
> > 
> > static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
> > {
> >     if (!argc || argv[0].a_type != A_SYMBOL)
> >         pd_this->pd_newest = list_append_new(s, argc, argv);
> >     else
> >     {
> >         t_symbol *s2 = argv[0].a_w.w_symbol;
> >         if (s2 == gensym("append"))
> >             pd_this->pd_newest = list_append_new(s, argc-1, argv+1);
> >         else if (s2 == gensym("prepend"))
> >             pd_this->pd_newest = list_prepend_new(s, argc-1, argv+1);
> >         else if (s2 == gensym("split"))
> >             pd_this->pd_newest =
> >                 list_split_new(atom_getfloatarg(1, argc, argv));
> >         else if (s2 == gensym("trim"))
> >             pd_this->pd_newest = list_trim_new();
> >         else if (s2 == gensym("length"))
> >             pd_this->pd_newest = list_length_new();
> >         else if (s2 == gensym("fromsymbol"))
> >             pd_this->pd_newest = list_fromsymbol_new();
> >         else if (s2 == gensym("tosymbol"))
> >             pd_this->pd_newest = list_tosymbol_new();
> >         else if (s2 == gensym("store"))
> >             pd_this->pd_newest = list_store_new(s, argc-1, argv+1);
> >         else
> >         {
> >             error("list %s: unknown function", s2->s_name);
> >             pd_this->pd_newest = 0;
> >         }
> >     }
> >     return (pd_this->pd_newest);
> > }
> > 
> > void x_list_setup(void)
> > {
> >     alist_setup();
> >     list_append_setup();
> >     list_prepend_setup();
> >     list_store_setup();
> >     list_split_setup();
> >     list_trim_setup();
> >     list_length_setup();
> >     list_fromsymbol_setup();
> >     list_tosymbol_setup();
> >     class_addcreator((t_newmethod)list_new, &s_list, A_GIMME, 0);
> > }
> 
> > _______________________________________________
> > Pd-dev mailing list
> > Pd-dev at lists.iem.at
> > https://lists.puredata.info/listinfo/pd-dev
> 
>



More information about the Pd-dev mailing list