aboutsummaryrefslogtreecommitdiff
path: root/pd
diff options
context:
space:
mode:
authorMiller Puckette <millerpuckette@users.sourceforge.net>2005-07-24 19:41:15 +0000
committerMiller Puckette <millerpuckette@users.sourceforge.net>2005-07-24 19:41:15 +0000
commit2b5318216ea6804a84920979fd77f759e35889fd (patch)
treed720fd0990a3abaa465e39101e2fa0e918bb8244 /pd
parent9474b99117836c2b76485ab3f44035cfc933c1ab (diff)
New "list" object.
Added "addcomma", "addsemi", "adddollar", "adddollsym" messages to message object. worked on Mac compilation problems. svn path=/trunk/; revision=3371
Diffstat (limited to 'pd')
-rw-r--r--pd/doc/5.reference/list-help.pd364
-rw-r--r--pd/src/configure.in4
-rw-r--r--pd/src/g_text.c40
-rw-r--r--pd/src/g_traversal.c31
-rw-r--r--pd/src/m_conf.c2
-rw-r--r--pd/src/makefile2
-rw-r--r--pd/src/makefile.dependencies8
-rw-r--r--pd/src/makefile.in2
-rw-r--r--pd/src/makefile.nt2
-rw-r--r--pd/src/notes.txt10
-rw-r--r--pd/src/s_inter.c1
-rw-r--r--pd/src/s_midi_alsa.c20
-rw-r--r--pd/src/u_main.tk4
-rw-r--r--pd/src/x_connective.c16
-rw-r--r--pd/src/x_list.c415
15 files changed, 873 insertions, 48 deletions
diff --git a/pd/doc/5.reference/list-help.pd b/pd/doc/5.reference/list-help.pd
new file mode 100644
index 00000000..ea6355bb
--- /dev/null
+++ b/pd/doc/5.reference/list-help.pd
@@ -0,0 +1,364 @@
+#N canvas 105 298 629 492 12;
+#X obj 29 11 list;
+#X text 352 455 updated for Pd version 0.39;
+#X text 76 12 - building and using variable-length messages;
+#N canvas 92 130 654 658 about-lists 0;
+#X obj 50 625 print message;
+#X msg 50 438 list x.wav 44100;
+#X msg 50 596 read \$1 \$2;
+#X msg 50 467 set x.wav 44100;
+#X msg 67 567 set \, add2 read \, adddollar 1 \, adddollar 2;
+#X msg 50 497 x.wav 44100;
+#X obj 67 541 loadbang;
+#X text 155 544 reset message as it was;
+#X text 207 438 good;
+#X text 196 469 bad;
+#X text 46 25 Messages in Pd are simewhat artificially divided into
+two classes. First are data-holding messages (bang \, float \, symbol
+\, list) which are the primary way of communicating between objects.
+Second is "everything else" (you could call them out-of-band messages
+or metamessages) that describe changes in configuration \, read and
+write files \, quit Pd \, etc. These are provided so that complex objects
+don't need to have 100 separate inlets for every possible functionality.
+It's not clear whether this was a good design choice \, but it's entrenched.
+;
+#X text 162 497 ugly;
+#X text 48 183 The distinction becomes visible \, and ugly \, when
+the leading item in a data-holding message is a symbol. In this case
+\, to disambiguate it from the other sort \, the printed form of the
+message has a selector \, "list" or "symbol" prepended to it. Underneath
+\, there is always a selector in fromt of data messages \, but it is
+implied if the first data item is a number.;
+#X msg 411 461 list 44100 x.wav;
+#X msg 424 486 44100 x.wav;
+#X obj 411 512 print number-first;
+#X text 405 433 these two are equivalent:;
+#X text 50 294 In the example below \, the top message sets \$1 to
+"x.wav" and \$2 to 44100 in the "read" message. The lower message box
+outputs the message "read x.wav 44100". The "set" message changes the
+content of the message box itself (click on the longer message box
+below to repair the damage.) The "ugly" message \, since it is neither
+"list" nor "set" \, gets interpreted in an arbitrary (and probably
+inappropriate!) way.;
+#X connect 1 0 2 0;
+#X connect 2 0 0 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 2 0;
+#X connect 6 0 4 0;
+#X connect 13 0 15 0;
+#X connect 14 0 15 0;
+#X restore 42 311 pd about-lists;
+#X text 33 52 There are four list classes:;
+#X obj 22 82 list append;
+#X obj 22 107 list prepend;
+#X obj 22 157 list trim;
+#X obj 22 132 list split;
+#X text 140 81 - append the second list to the first;
+#X text 141 108 - prepend the second list to the first;
+#X text 141 133 - split a list in two;
+#X text 141 160 - trim the "list" selector off;
+#N canvas 186 284 602 409 trim 0;
+#X msg 159 239 1 2 3;
+#X msg 159 190 list cis boom bah;
+#X msg 160 265 bang;
+#X msg 159 163 walk the dog;
+#X obj 134 341 list trim;
+#X obj 134 363 print trim;
+#X msg 160 287 1 x y;
+#X msg 159 313 x 1 y;
+#X text 29 19 trim - convert list to message \, using first item as
+selector;
+#X msg 159 213 55;
+#X text 27 55 The "list trim" object inputs lists (or makes lists out
+of incoming non-list messages) and outputs a message whose selector
+is the first item of the list \, and whose arguments \, if any \, are
+the remainder of the list. If the list has no items \, or if its first
+item is numeric \, the selector is "list" (which might print out as
+list \, float \, or bang.);
+#X connect 0 0 4 0;
+#X connect 1 0 4 0;
+#X connect 2 0 4 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 6 0 4 0;
+#X connect 7 0 4 0;
+#X connect 9 0 4 0;
+#X restore 506 160 pd trim;
+#X text 501 53 details:;
+#X text 499 36 click for;
+#N canvas 322 170 608 420 append 0;
+#X obj 17 324 list append 1 2;
+#X floatatom 17 154 5 0 0 0 - - -;
+#X msg 17 129 1 2 3;
+#X msg 17 82 list cis boom bah;
+#X msg 17 179 bang;
+#X msg 176 294 bang;
+#X obj 17 353 print append;
+#X msg 17 39 walk the dog;
+#X msg 176 244 list x y z;
+#X msg 175 218 go dog go;
+#X msg 174 268 4 5 6 and 7;
+#X text 138 37 non-list message converted to list;
+#X text 182 77 list starting with symbol;
+#X text 181 96 (needs explicit "list" selector);
+#X text 69 152 number is one-element list;
+#X text 72 129 numeric list;
+#X text 67 181 bang is zero-element list;
+#X text 270 215 same for right inlet...;
+#X text 286 267 (note: only the first item;
+#X text 289 286 need be a number to make this;
+#X text 289 304 a list.);
+#X text 170 325 <- creation args initialize the list to append;
+#X text 20 6 Append - append (concatenate) the second list to the first
+;
+#X connect 0 0 6 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 1;
+#X connect 7 0 0 0;
+#X connect 8 0 0 1;
+#X connect 9 0 0 1;
+#X connect 10 0 0 1;
+#X restore 506 84 pd append;
+#N canvas 391 326 667 561 split 0;
+#X msg 103 328 1 2 3;
+#X msg 79 231 list cis boom bah;
+#X msg 99 263 bang;
+#X obj 79 421 list split 2;
+#X floatatom 182 396 3 0 5 0 - - -;
+#X obj 79 469 print split1;
+#X obj 198 470 print split2;
+#X msg 79 204 walk the dog;
+#X msg 102 306 1 2;
+#X msg 100 285 1;
+#X msg 103 349 1 2 3 4;
+#X msg 103 372 1 2 so are you;
+#X obj 320 470 print split3;
+#X text 76 488 first n;
+#X text 195 489 rest of list;
+#X text 317 489 shorter than n;
+#X text 218 394 new split point;
+#X text 49 25 Split - cut a list into smaller ones;
+#X text 210 419 <-- creation arg inits split point;
+#X text 201 202 non-list message converted to list;
+#X text 245 231 list with three symbols;
+#X text 139 288 list with one number;
+#X text 177 310 ... etc;
+#X text 241 370 <- if the first item is a number \, it's a list.;
+#X text 142 262 list with no items;
+#X text 48 61 The "list split" object takes lists and outputs the first
+"n" items (left outlet) and the remaining ones (middle outlet). The
+two outputs appear in the usual right-to-left order. In case there
+are fewer than "n" items in the list \, it is output (in its entirety)
+from the third outlet instead. The creation argument or the inlet sets
+the split point.;
+#X connect 0 0 3 0;
+#X connect 1 0 3 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 3 1 6 0;
+#X connect 3 2 12 0;
+#X connect 4 0 3 1;
+#X connect 7 0 3 0;
+#X connect 8 0 3 0;
+#X connect 9 0 3 0;
+#X connect 10 0 3 0;
+#X connect 11 0 3 0;
+#X restore 506 134 pd split;
+#N canvas 0 0 640 478 prepend 0;
+#X obj 17 324 list append 1 2;
+#X floatatom 17 154 5 0 0 0 - - -;
+#X msg 17 129 1 2 3;
+#X msg 17 82 list cis boom bah;
+#X msg 17 179 bang;
+#X msg 176 294 bang;
+#X obj 17 353 print append;
+#X msg 17 39 walk the dog;
+#X msg 176 244 list x y z;
+#X msg 175 218 go dog go;
+#X msg 174 268 4 5 6 and 7;
+#X text 138 37 non-list message converted to list;
+#X text 182 77 list starting with symbol;
+#X text 181 96 (needs explicit "list" selector);
+#X text 69 152 number is one-element list;
+#X text 72 129 numeric list;
+#X text 67 181 bang is zero-element list;
+#X text 270 215 same for right inlet...;
+#X text 286 267 (note: only the first item;
+#X text 289 286 need be a number to make this;
+#X text 289 304 a list.);
+#X text 20 6 Prepend - prepend the second list to the first;
+#X text 167 324 <- creation args initialize the list to prepend;
+#X connect 0 0 6 0;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 1;
+#X connect 7 0 0 0;
+#X connect 8 0 0 1;
+#X connect 9 0 0 1;
+#X connect 10 0 0 1;
+#X restore 506 109 pd prepend;
+#X text 29 228 In general \, inlets that take lists (two each for append/prepend
+\, and one each for split and trim) will convert non-list messages
+(such as "set 5") to lists (such as "list set 5" automatically. Here's
+more about lists in Pd:;
+#X text 30 344 And here are some examples showing how to use these
+objects to compose and/or use variable length messages:;
+#N canvas 381 50 719 646 example1 0;
+#X obj 43 173 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 252 176 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 247 154 clear;
+#X text 40 153 send;
+#X msg 91 175 250;
+#X msg 123 175 500;
+#X msg 156 175 750;
+#X msg 189 175 1000;
+#X obj 43 258 list append;
+#X obj 208 220 t l;
+#X obj 91 214 list prepend;
+#X obj 43 426 t l l;
+#X obj 94 426 print start;
+#X obj 149 257 print stored;
+#X obj 43 451 list split 1;
+#X obj 43 575 del;
+#X obj 43 607 print bang;
+#X obj 75 542 list append;
+#X msg 55 403 0 250 250 500;
+#X text 118 150 -- add --;
+#X text 57 20 example 1: simple rhythmic sequencer;
+#X text 49 53 The top part of this patch demonstrates building up a
+message from a variable number of elements provided sequentially. The
+"list prepend" object stores the list and \, each time a number arrives
+\, prepends the previous list to it.;
+#X text 416 237 "list prepend" to its own inlet.;
+#X text 253 220 "trigger list" is needed only to connect outlet of
+;
+#X text 274 258 printout shows the growing message.;
+#X text 67 279 "list append" stores the growing message which is output
+by the "send" button above. "list prepend" would have been equivalent.
+;
+#X text 185 403 <-- test message;
+#X text 59 354 The bottom part of the patch takes numbers off the beginning
+of the list \, one by one \, to use as delays.;
+#X text 210 426 printout shows the sequence as it starts.;
+#X text 189 543 The rest of the list is stored for next time.;
+#X obj 161 505 print done;
+#X text 170 450 Split off the first item. If there is none \, nothing
+comes out the first or second outlet \, but instead we get a "bang"
+from the third one.;
+#X text 84 575 After delay \, output a bang and recall the rest of
+the list.;
+#X connect 0 0 8 0;
+#X connect 1 0 10 1;
+#X connect 4 0 10 0;
+#X connect 5 0 10 0;
+#X connect 6 0 10 0;
+#X connect 7 0 10 0;
+#X connect 8 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 9 0;
+#X connect 10 0 8 1;
+#X connect 10 0 13 0;
+#X connect 11 0 14 0;
+#X connect 11 1 12 0;
+#X connect 14 0 15 0;
+#X connect 14 1 17 1;
+#X connect 14 2 30 0;
+#X connect 15 0 16 0;
+#X connect 15 0 17 0;
+#X connect 17 0 14 0;
+#X connect 18 0 11 0;
+#X restore 221 397 pd example1;
+#X text 64 396 simple sequencer;
+#N canvas 126 39 568 569 example2 0;
+#X obj 66 263 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 292 266 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X text 287 244 clear;
+#X text 63 243 send;
+#X obj 66 342 list append;
+#X obj 213 317 t l;
+#X obj 94 303 list prepend;
+#X obj 66 410 t l l;
+#X obj 121 410 print start;
+#X obj 171 340 print stored;
+#X obj 66 486 del;
+#X obj 105 486 list append;
+#X msg 94 264 250 57;
+#X msg 154 264 500 52;
+#X msg 215 264 750 55;
+#X obj 66 461 unpack;
+#X obj 66 435 list split 2;
+#X text 80 38 example 2: sequencer with pitch;
+#X text 147 242 -- add --;
+#X obj 185 438 print done;
+#X obj 115 517 print pitch;
+#X text 13 69 This example is a slight modification of example 1 showing
+how to build up lists with more than one item per iteration. We regard
+pairs of numbers as specifying a delay time and a pitch. Unlike the
+previous example \, the delay here is interpreted as teh delay until
+the next event \, not the delay since the previous one. This is done
+by taking the "pitch" output before the delay object (previously the
+"output" was taken from the delay object's output.);
+#X connect 0 0 4 0;
+#X connect 1 0 6 1;
+#X connect 4 0 7 0;
+#X connect 5 0 6 1;
+#X connect 6 0 5 0;
+#X connect 6 0 4 1;
+#X connect 6 0 9 0;
+#X connect 7 0 16 0;
+#X connect 7 1 8 0;
+#X connect 10 0 11 0;
+#X connect 11 0 16 0;
+#X connect 12 0 6 0;
+#X connect 13 0 6 0;
+#X connect 14 0 6 0;
+#X connect 15 0 10 0;
+#X connect 15 1 20 0;
+#X connect 16 0 15 0;
+#X connect 16 1 11 1;
+#X connect 16 2 19 0;
+#X restore 221 423 pd example2;
+#X text 55 425 another sequencer;
+#X text 113 452 serializer;
+#N canvas 116 31 673 426 example3 0;
+#X obj 19 287 list split 1;
+#X obj 19 378 print;
+#X obj 19 204 until;
+#X obj 19 242 list append;
+#X obj 45 171 t b l;
+#X obj 149 287 bang;
+#X msg 45 148 1 2 3 4 a b c;
+#X text 34 21 example 3: serializing a message without delays;
+#X text 17 55 The "until" object can be used as shown to iterate through
+all the items of a list.;
+#X text 178 147 <- click to test;
+#X text 101 171 First store list \, then start the loop;
+#X text 118 199 "until" bangs its output until told to stop by a "bang"
+to its right inlet.;
+#X text 137 241 Store the remaining list.;
+#X text 194 286 third outlet of "split" tells us to stop.;
+#X text 67 318 Second outlet of "split" becomes the new list for "list
+append" above.;
+#X text 75 377 First outlet is the output.;
+#X connect 0 0 1 0;
+#X connect 0 1 3 1;
+#X connect 0 2 5 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X connect 4 0 2 0;
+#X connect 4 1 3 1;
+#X connect 5 0 2 1;
+#X connect 6 0 4 0;
+#X restore 220 450 pd example3;
+#X obj 22 194 list;
+#X text 70 195 - short for "list append";
diff --git a/pd/src/configure.in b/pd/src/configure.in
index 84ab18c4..70b83ba5 100644
--- a/pd/src/configure.in
+++ b/pd/src/configure.in
@@ -60,7 +60,7 @@ AC_PROG_GCC_TRADITIONAL
AC_TYPE_SIGNAL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(gettimeofday select socket strerror)
-
+AC_FUNC_ALLOCA
dnl Checks for libraries.
dnl Checking for `dlopen' function in -ldl:
@@ -349,5 +349,5 @@ then
MORECFLAGS=$MORECFLAGS" -g3 -D__COMPAQC__ -arch host"
fi
-AC_OUTPUT(makefile)
+AC_OUTPUT(makefile config.h)
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index 535d993b..54b7ac37 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -332,6 +332,38 @@ static void message_add(t_message *x, t_symbol *s, int argc, t_atom *argv)
glist_retext(x->m_glist, &x->m_text);
}
+static void message_addcomma(t_message *x)
+{
+ t_atom a;
+ SETCOMMA(&a);
+ binbuf_add(x->m_text.te_binbuf, 1, &a);
+ glist_retext(x->m_glist, &x->m_text);
+}
+
+static void message_addsemi(t_message *x)
+{
+ message_add(x, 0, 0, 0);
+}
+
+static void message_adddollar(t_message *x, t_floatarg f)
+{
+ int n = f;
+ if (n < 0)
+ n = 0;
+ t_atom a;
+ SETDOLLAR(&a, n);
+ binbuf_add(x->m_text.te_binbuf, 1, &a);
+ glist_retext(x->m_glist, &x->m_text);
+}
+
+static void message_adddollsym(t_message *x, t_symbol *s)
+{
+ t_atom a;
+ SETDOLLSYM(&a, s);
+ binbuf_add(x->m_text.te_binbuf, 1, &a);
+ glist_retext(x->m_glist, &x->m_text);
+}
+
static void message_click(t_message *x,
t_floatarg xpos, t_floatarg ypos, t_floatarg shift,
t_floatarg ctrl, t_floatarg alt)
@@ -1295,6 +1327,14 @@ void g_text_setup(void)
A_GIMME, 0);
class_addmethod(message_class, (t_method)message_add2, gensym("add2"),
A_GIMME, 0);
+ class_addmethod(message_class, (t_method)message_addcomma,
+ gensym("addcomma"), 0);
+ class_addmethod(message_class, (t_method)message_addsemi,
+ gensym("addsemi"), 0);
+ class_addmethod(message_class, (t_method)message_adddollar,
+ gensym("adddollar"), A_FLOAT, 0);
+ class_addmethod(message_class, (t_method)message_adddollsym,
+ gensym("adddollsym"), A_SYMBOL, 0);
messresponder_class = class_new(gensym("messresponder"), 0, 0,
sizeof(t_text), CLASS_PD, 0);
diff --git a/pd/src/g_traversal.c b/pd/src/g_traversal.c
index 4addeff3..a9165b8d 100644
--- a/pd/src/g_traversal.c
+++ b/pd/src/g_traversal.c
@@ -90,18 +90,6 @@ int gpointer_check(const t_gpointer *gp, int headok)
else return (0);
}
-/* call this if you know the pointer is fresh but don't know if we're pointing
-to the head of a list or to real data. Any pointer is known to be fresh
-when it appears as the argument of a message, but if your "pointer" method
-or inlet stores it and you use it later, call gpointer_check above. */
-
-/* LATER reconsider the above... I no longer think it's true! */
-
-static int gpointer_ishead(const t_gpointer *gp)
-{
- return ((gp->gp_stub->gs_which == GP_GLIST) && !gp->gp_un.gp_scalar);
-}
-
/* get the template for the object pointer to. Assumes we've already checked
freshness. Returns 0 if head of list. */
@@ -122,8 +110,9 @@ static t_symbol *gpointer_gettemplatesym(const t_gpointer *gp)
}
}
- /* copy a pointer to another, assuming the first one is fresh and
- the second one hasn't yet been initialized. */
+ /* copy a pointer to another, assuming the second one hasn't yet been
+ initialized. New gpointers should be initialized either by this
+ routine or by gpointer_init below. */
void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto)
{
*gpto = *gpfrom;
@@ -132,6 +121,8 @@ void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto)
else bug("gpointer_copy");
}
+ /* clear a gpointer that was previously set, releasing the associted
+ gstub if this was the last reference to it. */
void gpointer_unset(t_gpointer *gp)
{
t_gstub *gs;
@@ -416,9 +407,9 @@ static void get_pointer(t_get *x, t_gpointer *gp)
pd_error(x, "get: couldn't find template %s", templatesym->s_name);
return;
}
- if (gpointer_ishead(gp))
+ if (!gpointer_check(gp, 0))
{
- pd_error(x, "get: empty pointer");
+ pd_error(x, "get: stale or empty pointer");
return;
}
if (gs->gs_which == GP_ARRAY) vec = gp->gp_un.gp_w;
@@ -691,9 +682,9 @@ static void getsize_pointer(t_getsize *x, t_gpointer *gp)
pd_error(x, "getsize: field %s not of type array", fieldsym->s_name);
return;
}
- if (gpointer_ishead(gp))
+ if (!gpointer_check(gp, 0))
{
- pd_error(x, "getsize: empty pointer");
+ pd_error(x, "get: stale or empty pointer");
return;
}
if (gpointer_gettemplatesym(gp) != x->x_templatesym)
@@ -1033,9 +1024,9 @@ static void sublist_pointer(t_sublist *x, t_gpointer *gp)
pd_error(x, "sublist: couldn't find template %s", templatesym->s_name);
return;
}
- if (gpointer_ishead(gp))
+ if (!gpointer_check(gp, 0))
{
- pd_error(x, "sublist: empty pointer");
+ pd_error(x, "get: stale or empty pointer");
return;
}
if (!template_find_field(template, x->x_fieldsym,
diff --git a/pd/src/m_conf.c b/pd/src/m_conf.c
index d529ecd6..c7561920 100644
--- a/pd/src/m_conf.c
+++ b/pd/src/m_conf.c
@@ -37,6 +37,7 @@ void x_misc_setup(void);
void x_net_setup(void);
void x_qlist_setup(void);
void x_gui_setup(void);
+void x_list_setup(void);
void d_arithmetic_setup(void);
void d_array_setup(void);
void d_ctl_setup(void);
@@ -83,6 +84,7 @@ void conf_init(void)
x_net_setup();
x_qlist_setup();
x_gui_setup();
+ x_list_setup();
d_arithmetic_setup();
d_array_setup();
d_ctl_setup();
diff --git a/pd/src/makefile b/pd/src/makefile
index f69e9a00..9a560285 100644
--- a/pd/src/makefile
+++ b/pd/src/makefile
@@ -42,7 +42,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
d_math.c d_fft.c d_mayer_fft.c d_fftroutine.c d_array.c d_global.c \
d_delay.c d_resample.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
- x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c d_soundfile.c \
+ x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c d_soundfile.c \
$(SYSSRC)
diff --git a/pd/src/makefile.dependencies b/pd/src/makefile.dependencies
index 79c847aa..770c2ce3 100644
--- a/pd/src/makefile.dependencies
+++ b/pd/src/makefile.dependencies
@@ -890,6 +890,14 @@ x_gui.o: x_gui.c m_pd.h \
/usr/include/endian.h /usr/include/bits/endian.h /usr/include/stdlib.h \
/usr/include/unistd.h /usr/include/bits/posix_opt.h \
/usr/include/bits/confname.h /usr/include/getopt.h
+x_list.o: x_list.c m_pd.h \
+ /usr/lib/gcc-lib/i386-redhat-linux/3.3.3/include/stddef.h \
+ /usr/include/string.h /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/gnu/stubs.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/bits/types.h \
+ /usr/include/bits/wordsize.h /usr/include/bits/typesizes.h \
+ /usr/include/stdlib.h
d_soundfile.o: d_soundfile.c /usr/include/unistd.h \
/usr/include/features.h /usr/include/sys/cdefs.h \
/usr/include/gnu/stubs.h /usr/include/bits/posix_opt.h \
diff --git a/pd/src/makefile.in b/pd/src/makefile.in
index 2851e66a..c4a1987e 100644
--- a/pd/src/makefile.in
+++ b/pd/src/makefile.in
@@ -42,7 +42,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
d_math.c d_fft.c d_mayer_fft.c d_fftroutine.c d_array.c d_global.c \
d_delay.c d_resample.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
- x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c d_soundfile.c \
+ x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c d_soundfile.c \
$(SYSSRC)
diff --git a/pd/src/makefile.nt b/pd/src/makefile.nt
index a33296c1..22430d3c 100644
--- a/pd/src/makefile.nt
+++ b/pd/src/makefile.nt
@@ -34,7 +34,7 @@ SRC = g_canvas.c g_graph.c g_text.c g_rtext.c g_array.c g_template.c g_io.c \
d_math.c d_fft.c d_mayer_fft.c d_fftroutine.c d_array.c d_global.c \
d_delay.c d_resample.c \
x_arithmetic.c x_connective.c x_interface.c x_midi.c x_misc.c \
- x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c d_soundfile.c \
+ x_time.c x_acoustics.c x_net.c x_qlist.c x_gui.c x_list.c d_soundfile.c \
$(SYSSRC)
PADIR = ..\portaudio
diff --git a/pd/src/notes.txt b/pd/src/notes.txt
index 038c2a94..8fa53b39 100644
--- a/pd/src/notes.txt
+++ b/pd/src/notes.txt
@@ -16,11 +16,16 @@ GOP font depends on abstraction, not parent
------------ 0.39 ---------
problems:
+windows:
+ modal dialogs confuse watchdog
+mac:
+ .pd extension not added when saving?
TK commands to nonexistent windows? (maybe fixed)
array name changes don't show up on parent
arrays that don't fit in bounds don't update (same as red rectangle problem?)
what about upsampling inlet~s? ask Pd list...
+
flag for array to suppress printing name
check:
@@ -40,7 +45,6 @@ block resampling arguments
document tabwrite~_start
problems:
-modal dialogs confuse watchdog
patcher inlets don't deal with scalars (zbug.pd)
Macintosh .pd extension not added to filenames
need to optimize canvas_motion (get rid of box hit test??)
@@ -70,7 +74,6 @@ features:
flag to suppress printing array name above graph
rename windowname-pd instead of pd-windowname
fix copyright notices
-update portmusic to latest
IEM guis to use queued updates
pixel font sizes
pd to find running ones (pd -new to defeat)
@@ -85,7 +88,6 @@ tables:
queued graphics updates for IEMGUIs and scalars
think of a way to embed abstractions in a patch
make watchdog work for MACOSX
-GOP bounding box object
IEMGUIs better default font size
search path to include both calling patch and abstraction, if different
abstraction reload shouldn't have to vis everyone
@@ -96,7 +98,7 @@ put serial object in main dist (see rat@telecoma, Apr. 25; winfried May 22)
open/save panel to take messages to init directory, and to set extent list
flags to defeat pre-loading specified classes
expr to parse exponential notation
-
+pipe to handle symbols&pointers (just takes floats now???)
data:
data copy/paste doesn't check templates aren't changed
diff --git a/pd/src/s_inter.c b/pd/src/s_inter.c
index 5eb931ec..3e9ded5f 100644
--- a/pd/src/s_inter.c
+++ b/pd/src/s_inter.c
@@ -851,7 +851,6 @@ int sys_startgui(const char *guidir)
#ifdef UNISTD
int stdinpipe[2];
#endif
- fprintf(stderr, "gui; %s\n", guidir);
/* create an empty FD poll list */
sys_fdpoll = (t_fdpoll *)t_getbytes(0);
sys_nfdpoll = 0;
diff --git a/pd/src/s_midi_alsa.c b/pd/src/s_midi_alsa.c
index 437ac792..6e9143b3 100644
--- a/pd/src/s_midi_alsa.c
+++ b/pd/src/s_midi_alsa.c
@@ -48,6 +48,16 @@ void sys_alsa_do_open_midi(int nmidiin, int *midiinvec,
int i;
alsa_nmidiin = 0;
alsa_nmidiout = 0;
+ if(nmidiin>MAXMIDIINDEV )
+ {
+ post("midi input ports reduced to maximum %d", MAXMIDIINDEV);
+ nmidiin=MAXMIDIINDEV;
+ }
+ if(nmidiout>MAXMIDIOUTDEV)
+ {
+ post("midi output ports reduced to maximum %d", MAXMIDIOUTDEV);
+ nmidiout=MAXMIDIOUTDEV;
+ }
if (nmidiin>0 && nmidiout>0)
err = snd_seq_open(&midi_handle,"default",SND_SEQ_OPEN_DUPLEX,0);
@@ -200,8 +210,14 @@ void sys_alsa_poll_midi(void)
void sys_alsa_close_midi()
{
alsa_nmidiin = alsa_nmidiout = 0;
- snd_seq_close(midi_handle);
- snd_midi_event_free(midiev);
+ if(midi_handle)
+ {
+ snd_seq_close(midi_handle);
+ if(midiev)
+ {
+ snd_midi_event_free(midiev);
+ }
+ }
}
#define NSEARCH 10
diff --git a/pd/src/u_main.tk b/pd/src/u_main.tk
index 8da41f7a..401b37d6 100644
--- a/pd/src/u_main.tk
+++ b/pd/src/u_main.tk
@@ -4007,10 +4007,10 @@ proc pdtk_alsa_midi_dialog {id indevlist indev1 indev2 indev3 indev4 \
}
}
if {$alsa} {
- label $id.in1f.l1 -text "In Channels:"
+ label $id.in1f.l1 -text "In Ports:"
entry $id.in1f.x1 -textvariable midi_alsain -width 4
pack $id.in1f.l1 $id.in1f.x1 -side left
- label $id.in1f.l2 -text "Out Channels:"
+ label $id.in1f.l2 -text "Out Ports:"
entry $id.in1f.x2 -textvariable midi_alsaout -width 4
pack $id.in1f.l2 $id.in1f.x2 -side left
}
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
index ad6219cd..3d62b319 100644
--- a/pd/src/x_connective.c
+++ b/pd/src/x_connective.c
@@ -505,11 +505,7 @@ static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
if (x->x_type == A_FLOAT)
{
float f;
- if (!argc) /* empty lists go out reject outlet */
- {
- outlet_bang(x->x_rejectout);
- return;
- }
+ if (!argc) return;
f = atom_getfloat(argv);
for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
if (e->e_w.w_float == f)
@@ -584,8 +580,7 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv)
{
int n;
t_routeelement *e;
- t_route *x;
-
+ t_route *x = (t_route *)pd_new(route_class);
t_atom a;
if (argc == 0)
{
@@ -593,13 +588,6 @@ static void *route_new(t_symbol *s, int argc, t_atom *argv)
SETFLOAT(&a, 0);
argv = &a;
}
- for (n = 1; n < argc; n++)
- if (argv[n].a_type != argv[0].a_type)
- {
- error("route: creation with mixed argument types failed");
- return (0);
- }
- x = (t_route *)pd_new(route_class);
x->x_type = argv[0].a_type;
x->x_nelement = argc;
x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec));
diff --git a/pd/src/x_list.c b/pd/src/x_list.c
new file mode 100644
index 00000000..a867e293
--- /dev/null
+++ b/pd/src/x_list.c
@@ -0,0 +1,415 @@
+/* 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> */
+#include <alloca.h>
+extern t_pd *newest;
+
+#define HAVE_ALLOCA 1 /* LATER this should be set by configure script! */
+#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 strip - send message with leading symbol as selector
+ list length - output number of items in list
+ list nth - nth item in list, counting from zero
+
+Not sure we need these:
+ list cat - build a list by accumulating elements
+ list foreach - spit out elements of a list one by one
+ list array - get items from a named array as a list
+ list reverse - permute elements of a list back to front
+ list pack - synonym for 'pack'
+ list unpack - synonym for 'unpack'
+ list first - output first n elements.
+ list last - output last n elements
+*/
+
+/* -------------- 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 */
+ 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)
+{
+ 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 = 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_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int i;
+ alist_clear(x);
+ if (!(x->l_vec = (t_listelem *)getbytes(argc * sizeof(*x->l_vec))))
+ {
+ x->l_n = 0;
+ error("list_alloc: out of memory");
+ return;
+ }
+ x->l_n = argc;
+ for (i = 0; i < argc; i++)
+ {
+ x->l_vec[i].l_a = argv[i];
+ if (x->l_vec[i].l_a.a_type == A_POINTER)
+ gpointer_copy(x->l_vec[i].l_a.a_w.w_gpointer, &x->l_vec[i].l_p);
+ }
+}
+
+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;
+ 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)
+ gpointer_copy(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 i;
+ for (i = 0; i < x->l_n; i++)
+ to[i] = x->l_vec[i].l_a;
+}
+
+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);
+ alist_toatoms(&x->x_alist, outv+argc);
+ 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);
+ alist_toatoms(&x->x_alist, outv + 1 + argc);
+ outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
+ ATOMS_FREEA(outv, outc);
+}
+
+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 struct _list_prepend
+{
+ t_object x_obj;
+ t_alist x_alist;
+} 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);
+ alist_toatoms(&x->x_alist, outv);
+ atoms_copy(argc, argv, outv + 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);
+ alist_toatoms(&x->x_alist, outv);
+ SETSYMBOL(outv + x->x_alist.l_n, s);
+ atoms_copy(argc, argv, outv + x->x_alist.l_n + 1);
+ 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 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 ------------------- */
+
+static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
+{
+ if (!argc || argv[0].a_type != A_SYMBOL)
+ newest = list_append_new(s, argc, argv);
+ else
+ {
+ t_symbol *s2 = argv[0].a_w.w_symbol;
+ if (s2 == gensym("append"))
+ newest = list_append_new(s, argc-1, argv+1);
+ else if (s2 == gensym("prepend"))
+ newest = list_prepend_new(s, argc-1, argv+1);
+ else if (s2 == gensym("split"))
+ newest = list_split_new(atom_getfloatarg(1, argc, argv));
+ else if (s2 == gensym("trim"))
+ newest = list_trim_new();
+ else
+ {
+ error("list %s: unknown function", s2->s_name);
+ newest = 0;
+ }
+ }
+ return (newest);
+}
+
+void x_list_setup(void)
+{
+ alist_setup();
+ list_append_setup();
+ list_prepend_setup();
+ list_split_setup();
+ list_trim_setup();
+ class_addcreator((t_newmethod)list_new, &s_list, A_GIMME, 0);
+}