From df82a00f735b5cd727e561f97f4d27ae3e8e974f Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@vt.edu>
Date: Mon, 23 Jul 2012 23:57:50 -0400
Subject: [PATCH] Overhauled preset_node and preset_hub to support any kind of
 data, including symbols, floats, and lists. Removed unnecessary global class
 declarations and object filtering for node and hub.

---
 src/g_bang.c       |   1 +
 src/g_canvas.h     |  21 +-------
 src/g_editor.c     |   7 +--
 src/g_hdial.c      |   1 +
 src/g_hslider.c    |   1 +
 src/g_mycanvas.c   |   1 +
 src/g_numbox.c     |   1 +
 src/g_text.c       |   2 +
 src/g_toggle.c     |   1 +
 src/g_vdial.c      |   1 +
 src/g_vslider.c    |   1 +
 src/g_vumeter.c    |   1 +
 src/s_stuff.h      |  63 ++++++++++++++++++++++
 src/x_connective.c |   6 +--
 src/x_list.c       | 100 +++++++++++------------------------
 src/x_preset.c     | 128 +++++++++++++++++++++++++--------------------
 src/x_preset.h     |   6 ++-
 17 files changed, 190 insertions(+), 152 deletions(-)

diff --git a/src/g_bang.c b/src/g_bang.c
index f259c6b93..018ae116d 100644
--- a/src/g_bang.c
+++ b/src/g_bang.c
@@ -31,6 +31,7 @@ void bng_draw_select(t_bng* x, t_glist* glist);
 /* --------------- bng     gui-bang ------------------------- */
 
 t_widgetbehavior bng_widgetbehavior;
+static t_class *bng_class;
 
 /*  widget helper functions  */
 
diff --git a/src/g_canvas.h b/src/g_canvas.h
index fb096e7de..e62578a9b 100644
--- a/src/g_canvas.h
+++ b/src/g_canvas.h
@@ -235,26 +235,9 @@ struct _glist
 t_class *preset_hub_class;
 t_class *preset_node_class;
 
-// core gui
-t_class *gatom_class;
-t_class *message_class;
-
-// core text
-extern t_class *pdint_class;
-extern t_class *pdfloat_class;
-extern t_class *pdsymbol_class;
+// special case objects
 extern t_class *print_class;
-
-// iemgui
-t_class *bng_class;
-t_class *hradio_class, *hradio_old_class;
-t_class *hslider_class;
-t_class *my_canvas_class;
-t_class *my_numbox_class;
-t_class *toggle_class;
-t_class *vradio_class, *vradio_old_class;
-t_class *vslider_class;
-t_class *vu_class;
+extern t_class *message_class;
 /*-----------------end universal preset stuff-------------------*/
 
 /* a data structure to describe a field in a pure datum */
diff --git a/src/g_editor.c b/src/g_editor.c
index 03ca44e03..b121bf671 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -3010,6 +3010,7 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
             {
 				// if the first object is preset_node, check if the object we are connecting to
 				// is supported. If not, disallow connection
+				/*
 				if (pd_class(&y1->g_pd) == preset_node_class) {
 					if (pd_class(&y2->g_pd) != gatom_class &&
 						pd_class(&y2->g_pd) != bng_class &&
@@ -3031,7 +3032,7 @@ void canvas_doconnect(t_canvas *x, int xpos, int ypos, int which, int doit)
 						error("preset node currently works only with gui objects, ints, floats, and symbols, plus a print object for node monitoring...\n");
 						return;
 					}
-				}
+				}*/
 
 				// now check if explicit user-made connection into preset_node if kind other than message
 				// messages may be used to change node's operation
@@ -4604,7 +4605,7 @@ void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
 		goto bad;
     }
 		/* now check for illegal connections between preset_node object and other non-supported objects */
-	if (pd_class(&src->g_pd) == preset_node_class) {
+	/*if (pd_class(&src->g_pd) == preset_node_class) {
 		if (pd_class(&sink->g_pd) != gatom_class &&
 			pd_class(&sink->g_pd) != bng_class &&
 			pd_class(&sink->g_pd) != hradio_class &&
@@ -4625,7 +4626,7 @@ void canvas_connect(t_canvas *x, t_floatarg fwhoout, t_floatarg foutno,
 				error("preset node currently works only with gui objects, ints, floats, and symbols, plus a print object for node monitoring...\n");
 				goto bad;
 		}
-	}
+	}*/
 
         /* if object creation failed, make dummy inlets or outlets
         as needed */ 
diff --git a/src/g_hdial.c b/src/g_hdial.c
index f0d747d5f..6b9870708 100644
--- a/src/g_hdial.c
+++ b/src/g_hdial.c
@@ -34,6 +34,7 @@ void hradio_draw_select(t_hradio* x, t_glist* glist);
 /* ------------- hdl     gui-horicontal dial ---------------------- */
 
 t_widgetbehavior hradio_widgetbehavior;
+static t_class *hradio_class, *hradio_old_class;
 
 /* widget helper functions */
 
diff --git a/src/g_hslider.c b/src/g_hslider.c
index 320a2e3f5..37561b1ad 100644
--- a/src/g_hslider.c
+++ b/src/g_hslider.c
@@ -31,6 +31,7 @@ static void hslider_draw_select(t_hslider* x,t_glist* glist);
 /* ------------ hsl    gui-horicontal  slider ----------------------- */
 
 t_widgetbehavior hslider_widgetbehavior;
+static t_class *hslider_class;
 
 static double last;
 static int is_last_float = 0;
diff --git a/src/g_mycanvas.c b/src/g_mycanvas.c
index fe47c6abc..5f3b8f53c 100644
--- a/src/g_mycanvas.c
+++ b/src/g_mycanvas.c
@@ -31,6 +31,7 @@ void my_canvas_draw_select(t_my_canvas* x, t_glist* glist);
 /* ---------- cnv  my gui-canvas for a window ---------------- */
 
 t_widgetbehavior my_canvas_widgetbehavior;
+static t_class *my_canvas_class;
 
 /* widget helper functions */
 
diff --git a/src/g_numbox.c b/src/g_numbox.c
index 7eddc8211..dbba9b6d8 100644
--- a/src/g_numbox.c
+++ b/src/g_numbox.c
@@ -38,6 +38,7 @@ static void my_numbox_draw_update(t_gobj *client, t_glist *glist);
 /* ------------ nmx gui-my number box ----------------------- */
 
 t_widgetbehavior my_numbox_widgetbehavior;
+static t_class *my_numbox_class;
 
 /* widget helper functions */
 
diff --git a/src/g_text.c b/src/g_text.c
index 4cf7b97e8..d275020dc 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -19,6 +19,8 @@
 #include "x_preset.h"
 
 t_class *text_class;
+t_class *message_class;
+static t_class *gatom_class;
 static void text_vis(t_gobj *z, t_glist *glist, int vis);
 static void text_displace(t_gobj *z, t_glist *glist,
     int dx, int dy);
diff --git a/src/g_toggle.c b/src/g_toggle.c
index bf430bf8e..3db86241a 100644
--- a/src/g_toggle.c
+++ b/src/g_toggle.c
@@ -32,6 +32,7 @@ void toggle_draw_select(t_toggle* x, t_glist* glist);
 /* --------------- tgl     gui-toggle ------------------------- */
 
 t_widgetbehavior toggle_widgetbehavior;
+static t_class *toggle_class;
 
 /* widget helper functions */
 
diff --git a/src/g_vdial.c b/src/g_vdial.c
index c947a9863..f460c8e13 100644
--- a/src/g_vdial.c
+++ b/src/g_vdial.c
@@ -31,6 +31,7 @@ void vradio_draw_select(t_vradio* x, t_glist* glist);
 /* ------------- vdl     gui-vertical radio button ---------------------- */
 
 t_widgetbehavior vradio_widgetbehavior;
+static t_class *vradio_class, *vradio_old_class;
 
 /* widget helper functions */
 
diff --git a/src/g_vslider.c b/src/g_vslider.c
index b4e2c77c1..8e9265cb1 100644
--- a/src/g_vslider.c
+++ b/src/g_vslider.c
@@ -31,6 +31,7 @@ static void vslider_draw_select(t_vslider* x, t_glist* glist);
 /* ------------ vsl gui-vertical  slider ----------------------- */
 
 t_widgetbehavior vslider_widgetbehavior;
+static t_class *vslider_class;
 
 static double last;
 static int is_last_float = 0;
diff --git a/src/g_vumeter.c b/src/g_vumeter.c
index 688012c03..8e76135ee 100644
--- a/src/g_vumeter.c
+++ b/src/g_vumeter.c
@@ -32,6 +32,7 @@ void vu_check_height(t_vu *x, int h);
 /* ----- vu  gui-peak- & rms- vu-meter-display ---------- */
 
 t_widgetbehavior vu_widgetbehavior;
+static t_class *vu_class;
 
 /* widget helper functions */
 
diff --git a/src/s_stuff.h b/src/s_stuff.h
index d07454639..ceec125ff 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -7,6 +7,9 @@
 /* NOTE: this file describes Pd implementation details which may change
 in future releases.  The public (stable) API is in m_pd.h. */  
 
+#ifndef __s_stuff_h_
+#define __s_stuff_h_
+
 /* in s_path.c */
 
 typedef struct _namelist    /* element in a linked list of stored strings */
@@ -336,3 +339,63 @@ EXTERN void inmidi_polyaftertouch(int portno,
                                   int value);
 /* } jsarlo */
 extern t_widgetbehavior text_widgetbehavior;
+
+/* in x_list.c */
+    /* 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;
+
+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 */
+};
+
+#ifndef t_alist
+#define t_alist struct _alist
+#endif
+
+#if 0 /* probably won't use this version... */
+#ifdef HAVE_ALLOCA
+#define LIST_ALLOCA(x, n) ( \
+    (x).l_n = (n), \
+    (x).l_vec = (t_listelem *)((n) < LIST_NGETBYTE ?  \
+        alloca((n) * sizeof(t_listelem)) : getbytes((n) * sizeof(t_listelem))))     \
+#define LIST_FREEA(x) ( \
+    ((x).l_n < LIST_NGETBYTE ||
+        (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem)), 0)))
+
+#else
+#define LIST_ALLOCA(x, n) ( \
+    (x).l_n = (n), \
+    (x).l_vec = (t_listelem *)getbytes((n) * sizeof(t_listelem))) 
+#define LIST_FREEA(x) (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem)))
+#endif
+#endif
+
+#if HAVE_ALLOCA
+#define XL_ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ?  \
+        alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom))))
+#define XL_ATOMS_FREEA(x, n) ( \
+    ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0)))
+#else
+#define XL_ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom)))
+#define XL_ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom)))
+#endif
+
+EXTERN void atoms_copy(int argc, t_atom *from, t_atom *to);
+EXTERN t_class *alist_class;
+EXTERN void alist_init(t_alist *x);
+EXTERN void alist_clear(t_alist *x);
+EXTERN void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN void alist_toatoms(t_alist *x, t_atom *to);
+EXTERN void alist_clone(t_alist *x, t_alist *y);
+
+#endif /* __s_stuff_h_ */
diff --git a/src/x_connective.c b/src/x_connective.c
index 6221997c9..aeed72d01 100644
--- a/src/x_connective.c
+++ b/src/x_connective.c
@@ -11,7 +11,7 @@
 extern t_pd *newest;
 
 /* -------------------------- int ------------------------------ */
-t_class *pdint_class;
+static t_class *pdint_class;
 
 typedef struct _pdint
 {
@@ -48,7 +48,7 @@ void pdint_setup(void)
 }
 
 /* -------------------------- float ------------------------------ */
-t_class *pdfloat_class;
+static t_class *pdfloat_class;
 
 typedef struct _pdfloat
 {
@@ -95,7 +95,7 @@ void pdfloat_setup(void)
 }
 
 /* -------------------------- symbol ------------------------------ */
-t_class *pdsymbol_class;
+static t_class *pdsymbol_class;
 
 typedef struct _pdsymbol
 {
diff --git a/src/x_list.c b/src/x_list.c
index be6df2a66..9f9c739f3 100644
--- a/src/x_list.c
+++ b/src/x_list.c
@@ -5,6 +5,7 @@
 #include "config.h"
 
 #include "m_pd.h"
+#include "s_stuff.h"
 /* #include <string.h> */
 
 #ifdef HAVE_MALLOC_H
@@ -42,51 +43,8 @@ Probably don't need:
 */
 
 /* -------------- 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 0 /* probably won't use this version... */
-#ifdef HAVE_ALLOCA
-#define LIST_ALLOCA(x, n) ( \
-    (x).l_n = (n), \
-    (x).l_vec = (t_listelem *)((n) < LIST_NGETBYTE ?  \
-        alloca((n) * sizeof(t_listelem)) : getbytes((n) * sizeof(t_listelem))))     \
-#define LIST_FREEA(x) ( \
-    ((x).l_n < LIST_NGETBYTE ||
-        (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem)), 0)))
-
-#else
-#define LIST_ALLOCA(x, n) ( \
-    (x).l_n = (n), \
-    (x).l_vec = (t_listelem *)getbytes((n) * sizeof(t_listelem))) 
-#define LIST_FREEA(x) (freebytes((x).l_vec, (x).l_n * sizeof(t_listelem)))
-#endif
-#endif
 
-#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)
+void atoms_copy(int argc, t_atom *from, t_atom *to)
 {
     int i;
     for (i = 0; i < argc; i++)
@@ -97,26 +55,30 @@ static void atoms_copy(int argc, t_atom *from, t_atom *to)
 
 t_class *alist_class;
 
-static void alist_init(t_alist *x)
+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)
+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));
+	if (x->l_n) {
+    	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));
+	}
+	x->l_n = 0;
+	x->l_npointer = 0;
 }
 
-static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
+void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
     alist_clear(x);
@@ -140,7 +102,7 @@ static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
     }
 }
 
-static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
+void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
     alist_clear(x);
@@ -165,7 +127,7 @@ static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
     }
 }
 
-static void alist_toatoms(t_alist *x, t_atom *to)
+void alist_toatoms(t_alist *x, t_atom *to)
 {
     int i;
     for (i = 0; i < x->l_n; i++)
@@ -173,7 +135,7 @@ static void alist_toatoms(t_alist *x, t_atom *to)
 }
 
 
-static void alist_clone(t_alist *x, t_alist *y)
+void alist_clone(t_alist *x, t_alist *y)
 {
     int i;
     y->l_pd = alist_class;
@@ -195,7 +157,7 @@ static void alist_clone(t_alist *x, t_alist *y)
     }
 }
 
-static void alist_setup(void)
+void alist_setup(void)
 {
     alist_class = class_new(gensym("list inlet"),
         0, 0, sizeof(t_alist), 0, 0);
@@ -228,7 +190,7 @@ static void list_append_list(t_list_append *x, t_symbol *s,
 {
     t_atom *outv;
     int n, outc = x->x_alist.l_n + argc;
-    ATOMS_ALLOCA(outv, outc);
+    XL_ATOMS_ALLOCA(outv, outc);
     atoms_copy(argc, argv, outv);
     if (x->x_alist.l_npointer)
     {
@@ -243,7 +205,7 @@ static void list_append_list(t_list_append *x, t_symbol *s,
         alist_toatoms(&x->x_alist, outv+argc);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
-    ATOMS_FREEA(outv, outc);
+    XL_ATOMS_FREEA(outv, outc);
 }
 
 static void list_append_anything(t_list_append *x, t_symbol *s,
@@ -251,7 +213,7 @@ static void list_append_anything(t_list_append *x, t_symbol *s,
 {
     t_atom *outv;
     int n, outc = x->x_alist.l_n + argc + 1;
-    ATOMS_ALLOCA(outv, outc);
+    XL_ATOMS_ALLOCA(outv, outc);
     SETSYMBOL(outv, s);
     atoms_copy(argc, argv, outv + 1);
     if (x->x_alist.l_npointer)
@@ -267,7 +229,7 @@ static void list_append_anything(t_list_append *x, t_symbol *s,
         alist_toatoms(&x->x_alist, outv + 1 + argc);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
-    ATOMS_FREEA(outv, outc);
+    XL_ATOMS_FREEA(outv, outc);
 }
 
 static void list_append_free(t_list_append *x)
@@ -310,7 +272,7 @@ static void list_prepend_list(t_list_prepend *x, t_symbol *s,
 {
     t_atom *outv;
     int n, outc = x->x_alist.l_n + argc;
-    ATOMS_ALLOCA(outv, outc);
+    XL_ATOMS_ALLOCA(outv, outc);
     atoms_copy(argc, argv, outv + x->x_alist.l_n);
     if (x->x_alist.l_npointer)
     {
@@ -325,7 +287,7 @@ static void list_prepend_list(t_list_prepend *x, t_symbol *s,
         alist_toatoms(&x->x_alist, outv);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
-    ATOMS_FREEA(outv, outc);
+    XL_ATOMS_FREEA(outv, outc);
 }
 
 
@@ -335,7 +297,7 @@ static void list_prepend_anything(t_list_prepend *x, t_symbol *s,
 {
     t_atom *outv;
     int n, outc = x->x_alist.l_n + argc + 1;
-    ATOMS_ALLOCA(outv, outc);
+    XL_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)
@@ -351,7 +313,7 @@ static void list_prepend_anything(t_list_prepend *x, t_symbol *s,
         alist_toatoms(&x->x_alist, outv);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
-    ATOMS_FREEA(outv, outc);
+    XL_ATOMS_FREEA(outv, outc);
 }
 
 static void list_prepend_free(t_list_prepend *x)
@@ -411,11 +373,11 @@ 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);
+    XL_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);
+    XL_ATOMS_FREEA(outv, argc+1);
 }
 
 static void list_split_setup(void)
diff --git a/src/x_preset.c b/src/x_preset.c
index 73f4f4531..51a9019af 100644
--- a/src/x_preset.c
+++ b/src/x_preset.c
@@ -398,19 +398,21 @@ static int preset_node_location_changed(t_preset_node *x)
 	return(0);
 }
 
-static void preset_node_bang(t_preset_node *x)
+static void preset_node_anything(t_preset_node *x, t_symbol *s, int argc, t_atom *argv)
 {
-	SETSYMBOL(&x->pn_val, gensym("bang"));
-}
-
-static void preset_node_float(t_preset_node *x, t_float f)
-{
-	SETFLOAT(&x->pn_val, f);
-}
-
-static void preset_node_symbol(t_preset_node *x, t_symbol *s)
-{
-	SETSYMBOL(&x->pn_val, s);
+	if (PH_DEBUG) fprintf(stderr,"preset_node_anything\n");
+	int i;
+	alist_list(&x->pn_val, 0, argc, argv);
+	// check for pointers and warn user presetting them has not been tested
+    for (i = 0; i < x->pn_val.l_n; i++)
+    {
+        if (x->pn_val.l_vec[i].l_a.a_type == A_POINTER)
+        {
+			pd_error(x, "preset_node preset received a pointer as part of a list--this has not been tested, use at your own risk and please report any successes/failures. thank you!");
+			break;
+        }
+    }
+	
 }
 
 	//=============== following functions are for interaction with the hub/pd =================//
@@ -437,21 +439,15 @@ void preset_node_request_hub_store(t_preset_node *x, t_float f)
 		preset_hub_store(x->pn_hub, f);
 }
 
-t_atom preset_node_request_value(t_preset_node *x)
-{
-    return(x->pn_val);
-}
-
-void preset_node_set_and_output_value(t_preset_node *x, t_atom *val)
+void preset_node_set_and_output_value(t_preset_node *x, t_alist val)
 {
-	if (val->a_type == A_FLOAT) {
-		preset_node_float(x, val->a_w.w_float);
-		outlet_float(x->pn_outlet, x->pn_val.a_w.w_float);
-	} else if (val->a_type == A_SYMBOL) {
-		preset_node_symbol(x, val->a_w.w_symbol);
-		outlet_symbol(x->pn_outlet, x->pn_val.a_w.w_symbol);
-	} else
-		pd_error(x, "error: preset_node currently supports only floats and symbols");
+	t_atom *outv;
+	alist_clear(&x->pn_val);
+	alist_clone(&val, &x->pn_val);
+	XL_ATOMS_ALLOCA(outv, x->pn_val.l_n);
+	alist_toatoms(&x->pn_val, outv);
+	outlet_list(x->pn_outlet, &s_list, x->pn_val.l_n, outv);
+	XL_ATOMS_FREEA(outv, x->pn_val.l_n);
 }
 
 void preset_node_clear(t_preset_node *x, t_float f)
@@ -477,6 +473,8 @@ void preset_node_clear(t_preset_node *x, t_float f)
 				// if it is first one
 				if (np1->np_preset == (int)f) {
 					hd2->phd_npreset = np1->np_next;
+					if (np1->np_val.l_n)
+						alist_clear(&np1->np_val);
 					freebytes(np1, sizeof(*np1));
 					changed = 1;
 					if(PH_DEBUG) fprintf(stderr,"	found preset to delete (first)\n");
@@ -485,6 +483,8 @@ void preset_node_clear(t_preset_node *x, t_float f)
 						np2 = np1->np_next;
 						if (np2 && np2->np_preset == (int)f) {
 							np1->np_next = np2->np_next;
+							if (np2->np_val.l_n)
+								alist_clear(&np2->np_val);
 							freebytes(np2, sizeof(*np2));
 							changed = 1;
 							if(PH_DEBUG) fprintf(stderr,"	found preset to delete\n");
@@ -540,7 +540,8 @@ static void *preset_node_new(t_symbol *s, int argc, t_atom *argv)
 
 	x->pn_canvas = canvas;
 	t_canvas *y = x->pn_canvas;
-	t_preset_hub *h;
+	//t_preset_hub *h;
+	alist_init(&x->pn_val);
 
 	x->pn_hub = NULL;
 	x->pn_gl_loc_length = 0;
@@ -566,6 +567,8 @@ static void preset_node_free(t_preset_node* x)
 		preset_hub_delete_a_node(x->pn_hub, x);
 	glob_preset_node_list_delete(x);
 
+	alist_clear(&x->pn_val);
+
 	// the two arrays can point to same locations so here we prevent double free
 	// (this is only possible initially when the object is first instantiated)
 	if (x->pn_gl_loc != x->pn_old_gl_loc) {
@@ -603,12 +606,8 @@ void preset_node_setup(void)
     class_addmethod(preset_node_class, (t_method)preset_node_purge,
         gensym("purge"), A_NULL, 0);
 
-    class_addbang(preset_node_class, preset_node_bang);
-    class_addfloat(preset_node_class, preset_node_float);
-    class_addsymbol(preset_node_class, preset_node_symbol);
-
-	// TODO: we may add this later if necessary
-    //class_addlist(preset_node_class, preset_node_list);
+	// we use anything to cover virtually all presetable types of data
+	class_addanything(preset_node_class, preset_node_anything);
 }
 
 //====================== end preset_node ===========================//
@@ -630,12 +629,12 @@ typedef enum
 	separated for legibility sakes):
 	#X obj X Y preset_hub NAME %hidden%
 	%node% LOCATION_ARRAY_LENGTH LOCATION_ARRAY_(INT) 1 2 3 etc.
-	%preset% 1 %float%/%symbol% (e.g. number or symbol, later also possibly a list)
+	%preset% 1 data
 	%preset% 2 4
 	etc
 	%node% 2 0
 	%preset% 1 5.561
-	%preset% 3 7.00001
+	%preset% 3 7.00001 anything including lists
 	%preset% 5 some_text
 	;
 
@@ -646,6 +645,7 @@ typedef enum
 void preset_hub_save(t_gobj *z, t_binbuf *b)
 {
 	if(PH_DEBUG) fprintf(stderr,"preset_hub_save\n");
+	t_atom *outv;
 	int i;
 	t_preset_hub_data *phd;
 	t_node_preset *np;
@@ -678,10 +678,12 @@ void preset_hub_save(t_gobj *z, t_binbuf *b)
 		np = phd->phd_npreset;
 		while (np) {
 			binbuf_addv(b, "si", gensym("%preset%"), (int)np->np_preset);
-			if (np->np_val.a_type == A_FLOAT)
-				binbuf_addv(b, "f", np->np_val.a_w.w_float);
-			else if (np->np_val.a_type == A_SYMBOL)
-				binbuf_addv(b, "s", np->np_val.a_w.w_symbol);
+			for (i = 0; i < np->np_val.l_n; i++) {
+				if (np->np_val.l_vec[i].l_a.a_type == A_FLOAT)
+					binbuf_addv(b, "f", np->np_val.l_vec[i].l_a.a_w.w_float);
+				else if (np->np_val.l_vec[i].l_a.a_type == A_SYMBOL)
+					binbuf_addv(b, "s", np->np_val.l_vec[i].l_a.a_w.w_symbol);
+			}
 			np = np->np_next;
 		}
 
@@ -722,8 +724,8 @@ void preset_hub_recall(t_preset_hub *x, t_float f)
 							if(PH_DEBUG) fprintf(stderr,"	searching presets\n");
 							if (np->np_preset == (int)f) {
 								valid = 1;
-								if(PH_DEBUG) fprintf(stderr,"	valid %d %g\n", (hd->phd_node ? 1:0), np->np_val.a_w.w_float);
-								preset_node_set_and_output_value(hd->phd_node, &np->np_val);
+								if(PH_DEBUG) fprintf(stderr,"	valid %d\n", (hd->phd_node ? 1:0));
+								preset_node_set_and_output_value(hd->phd_node, np->np_val);
 								break;
 							}
 							np = np->np_next;
@@ -772,6 +774,7 @@ void preset_hub_store(t_preset_hub *h, t_float f)
 						np2 = hd1->phd_npreset;
 						while (np2) {
 							if (np2->np_preset == (int)f) {
+								if(PH_DEBUG) fprintf(stderr,"	overwriting\n");
 								overwrite = 1;
 								break;
 							}
@@ -782,6 +785,7 @@ void preset_hub_store(t_preset_hub *h, t_float f)
 
 					if (!overwrite) {
 						// we need to create a new preset (this is also true if hd1->phd_npreset is NULL)
+						if(PH_DEBUG) fprintf(stderr,"	creating new preset\n");
 						np2 = (t_node_preset *)t_getbytes(sizeof(*np2));
 						if (np1)
 							np1->np_next = np2;
@@ -789,11 +793,10 @@ void preset_hub_store(t_preset_hub *h, t_float f)
 						np2->np_preset = (int)f;
 					}
 
-					val = preset_node_request_value(hd1->phd_node);
-					if (val.a_type == A_FLOAT)
-						SETFLOAT(&np2->np_val, atom_getfloat(&val));
-					else if (val.a_type == A_SYMBOL)
-						SETSYMBOL(&np2->np_val, atom_getsymbol(&val));
+					alist_clear(&np2->np_val);
+					if(PH_DEBUG) fprintf(stderr,"	node data len = %d, old hub data len = %d\n", hd1->phd_node->pn_val.l_n, np2->np_val.l_n);
+					alist_clone(&hd1->phd_node->pn_val, &np2->np_val);
+					if(PH_DEBUG) fprintf(stderr,"	node data len = %d, NEW hub data len = %d\n", hd1->phd_node->pn_val.l_n, np2->np_val.l_n);
 
 					// finally if this is the first preset, hd1->phd_npreset will be NULL so,
 					// let's have it point to the newly created n2
@@ -935,6 +938,8 @@ void preset_hub_reset(t_preset_hub *h)
 				np1 = hd1->phd_npreset;
 				while (np1) {
 					np2 = np1->np_next;
+					if (np1->np_val.l_n)
+						alist_clear(&np1->np_val);
 					freebytes(np1, sizeof(*np1));
 					changed = 1;
 					if(PH_DEBUG) fprintf(stderr,"	deleting preset\n");
@@ -982,6 +987,8 @@ void preset_hub_clear(t_preset_hub *h, t_float f)
 				// if it is first one
 				if (np1->np_preset == (int)f) {
 					hd2->phd_npreset = np1->np_next;
+					if (np1->np_val.l_n)
+						alist_clear(&np1->np_val);
 					freebytes(np1, sizeof(*np1));
 					changed = 1;
 					if(PH_DEBUG) fprintf(stderr,"	found preset to delete (first)\n");
@@ -990,6 +997,8 @@ void preset_hub_clear(t_preset_hub *h, t_float f)
 						np2 = np1->np_next;
 						if (np2 && np2->np_preset == (int)f) {
 							np1->np_next = np2->np_next;
+							if (np1->np_val.l_n)
+								alist_clear(&np1->np_val);
 							freebytes(np2, sizeof(*np2));
 							changed = 1;
 							if(PH_DEBUG) fprintf(stderr,"	found preset to delete\n");
@@ -1031,6 +1040,8 @@ void preset_hub_purge(t_preset_hub *h)
 					np1 = hd2->phd_npreset;
 					while (np1) {
 						np2 = np1->np_next;
+						if (np1->np_val.l_n)
+							alist_clear(&np1->np_val);
 						freebytes(np1, sizeof(*np1));
 						changed = 1;
 						if(PH_DEBUG) fprintf(stderr,"	deleting preset\n");
@@ -1071,6 +1082,7 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
 	t_preset_hub *x, *check;
 	t_symbol *name;
 	int i, pos, loc_pos;
+	int j, data_count; //for lists
 	t_glist *glist=(t_glist *)canvas_getcurrent();
 	t_canvas *canvas = (t_canvas *)glist_getcanvas(glist);
 
@@ -1181,11 +1193,6 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
 					np1 = np2;
 					h_cur = H_PRESET;
 				}
-				// SYMBOL DATA
-				else if (h_cur == H_PRESET_DATA) {
-					if(PH_DEBUG) fprintf(stderr,"	sym data %s\n", atom_getsymbol(&argv[i])->s_name);
-					SETSYMBOL(&np2->np_val, atom_getsymbol(&argv[i]));
-				}
 			}
 			// FLOAT ANALYSIS
 			else if (argv[i].a_type == A_FLOAT) {
@@ -1204,19 +1211,26 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
 				else if (h_cur == H_LOCATION) {
 					// node location data
 					hd2->phd_pn_gl_loc[loc_pos] = (int)atom_getfloat(&argv[i]);
+					if(PH_DEBUG) fprintf(stderr,"	loc = %d\n", hd2->phd_pn_gl_loc[loc_pos]);
 					loc_pos++;
-					if(PH_DEBUG) fprintf(stderr,"	loc = %d\n", hd2->phd_pn_gl_loc_length);
 				}
 				else if (h_cur == H_PRESET) {
 					// preset number
 					if(PH_DEBUG) fprintf(stderr,"	preset %g\n", atom_getfloat(&argv[i]));
 					np2->np_preset = (int)atom_getfloat(&argv[i]);
+					data_count = i+1;
+					// figure out how long of variable data list follows the preset descriptor
+					while (data_count < argc && strcmp(atom_getsymbol(&argv[data_count])->s_name, "%preset%") && strcmp(atom_getsymbol(&argv[data_count])->s_name, "%node%")) {
+						data_count++;
+					}
+					if(PH_DEBUG) fprintf(stderr,"	found preset? %d found node? %d\n", strcmp(atom_getsymbol(&argv[data_count])->s_name, "%preset%"), strcmp(atom_getsymbol(&argv[data_count])->s_name, "%node%"));
+					data_count = data_count - (i+1);
+					if(PH_DEBUG) fprintf(stderr,"	data_count = %d staring @ %d out of %d\n", data_count, i+1, argc);
+					alist_init(&np2->np_val);
+					alist_list(&np2->np_val, 0, data_count, argv+(i+1));
+					i = i + data_count;
 					h_cur = H_PRESET_DATA;
 				}
-				else if (h_cur == H_PRESET_DATA) {
-					if(PH_DEBUG) fprintf(stderr,"	preset data %g\n", atom_getfloat(&argv[i]));
-					SETFLOAT(&np2->np_val, atom_getfloat(&argv[i]));
-				}
 			}
 		}
 	}
@@ -1290,6 +1304,8 @@ static void preset_hub_free(t_preset_hub* x)
 				np1 = hd1->phd_npreset;
 				while (np1) {
 					np2 = np1->np_next;
+					if (np1->np_val.l_n)
+						alist_clear(&np1->np_val);
 					freebytes(np1, sizeof(*np1));
 					np1 = np2;
 				}
diff --git a/src/x_preset.h b/src/x_preset.h
index fbade30f2..277b1ecbb 100644
--- a/src/x_preset.h
+++ b/src/x_preset.h
@@ -6,11 +6,13 @@
 Global preset system by Ivica Ico Bukvic <ico@vt.edu> July, 2012
 */
 
+#include "s_stuff.h"
+
 // each node in the patch
 typedef struct _preset_node
 {
     t_object pn_obj;
-    t_atom pn_val;			// last known value (null if not initialized)
+    t_alist pn_val;	// last known value (null if not initialized)
 
 	t_symbol *pn_hub_name;	// hub name this node is associated with
 	t_preset_hub *pn_hub;	// pointer to the hub (null if none, equiv. to active/disabled)
@@ -31,7 +33,7 @@ typedef struct _preset_node
 typedef struct _node_preset
 {
 	int np_preset;
-	t_atom np_val;
+	t_alist np_val;
 	struct _node_preset *np_next;
 } t_node_preset;
 
-- 
GitLab