[PD-cvs] SF.net SVN: pure-data:[10469] trunk/pd

millerpuckette at users.sourceforge.net millerpuckette at users.sourceforge.net
Tue Dec 30 02:51:32 CET 2008


Revision: 10469
          http://pure-data.svn.sourceforge.net/pure-data/?rev=10469&view=rev
Author:   millerpuckette
Date:     2008-12-30 01:51:31 +0000 (Tue, 30 Dec 2008)

Log Message:
-----------
0.42-0test08

Modified Paths:
--------------
    trunk/pd/extra/bonk~/bonk~-help.pd
    trunk/pd/extra/bonk~/bonk~.c
    trunk/pd/extra/pd~/pd~.c
    trunk/pd/src/CHANGELOG.txt
    trunk/pd/src/g_canvas.c
    trunk/pd/src/g_canvas.h
    trunk/pd/src/g_editor.c
    trunk/pd/src/g_rtext.c
    trunk/pd/src/g_text.c
    trunk/pd/src/m_glob.c
    trunk/pd/src/m_pd.h
    trunk/pd/src/makefile.in
    trunk/pd/src/notes.txt
    trunk/pd/src/s_audio.c
    trunk/pd/src/s_audio_oss.c
    trunk/pd/src/s_audio_pa.c
    trunk/pd/src/s_loader.c
    trunk/pd/src/s_main.c
    trunk/pd/src/s_stuff.h

Added Paths:
-----------
    trunk/pd/extra/lrshift~/lrshift~-help.pd

Removed Paths:
-------------
    trunk/pd/extra/lrshift~/rlshift~-help.pd

Modified: trunk/pd/extra/bonk~/bonk~-help.pd
===================================================================
--- trunk/pd/extra/bonk~/bonk~-help.pd	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/extra/bonk~/bonk~-help.pd	2008-12-30 01:51:31 UTC (rev 10469)
@@ -1,13 +1,13 @@
-#N canvas 304 143 967 599 10;
-#X obj 370 524 spigot;
+#N canvas 304 143 967 599 12;
+#X obj 358 544 spigot;
 #X msg 442 397 bang;
-#X obj 429 488 bonk~;
+#X obj 428 508 bonk~;
 #X msg 442 214 learn 1;
 #X msg 442 274 learn 0;
-#X msg 437 456 print;
+#X msg 446 451 print;
 #X obj 390 437 adc~;
-#X msg 614 538 \; pd dsp 1;
-#X obj 277 524 spigot;
+#X msg 613 558 \; pd dsp 1;
+#X obj 276 544 spigot;
 #N canvas 366 126 604 404 synth 0;
 #X obj 112 24 r bonk-cooked;
 #X obj 112 49 unpack;
@@ -59,14 +59,14 @@
 #X connect 21 0 1 0;
 #X connect 22 0 6 0;
 #X connect 23 0 9 0;
-#X restore 846 555 pd synth;
-#X floatatom 846 532 0 0 0 0 - - -;
-#X msg 846 502 0;
+#X restore 845 575 pd synth;
+#X floatatom 845 552 0 0 0 0 - - -;
+#X msg 845 522 0;
 #X msg 442 244 learn 10;
 #X msg 442 304 forget;
 #X msg 442 334 write templates.txt;
 #X msg 442 364 read templates.txt;
-#X msg 877 502 90;
+#X msg 876 522 90;
 #X msg 442 81 thresh 6 50;
 #X text 8 56 The Bonk object takes an audio signal input and looks
 for "attacks" defined as sharp changes in the spectral envelope of
@@ -75,13 +75,13 @@
 to guess which of two or more instruments was hit. Bonk is described
 theoretically in the 1998 ICMC proceedings \, reprinted on http://man104nfs.ucsd.edu/~mpuckett.
 ;
-#X text 602 504 click here;
-#X text 603 517 to start DSP;
+#X text 601 524 click here;
+#X text 602 537 to start DSP;
 #X text 8 377 In this patch \, after starting DSP \, you can print
 out the raw or cooked output using the two "spigots" or listen to a
 synthesizer output by raising its volume.;
-#X text 747 501 output volume;
-#X text 761 519 (0-100);
+#X text 746 521 output volume;
+#X text 760 539 (0-100);
 #X msg 442 150 mask 4 0.7;
 #X msg 442 184 debounce 0;
 #X text 8 309 Bonk's analysis is carried out on a 256-point window
@@ -89,7 +89,7 @@
 The analysis period can be specified as Bonk's creation argument but
 must be a multiple of 64;
 #X text 532 185 Minimum time (msec) between attacks;
-#X text 532 140 Describes how energy in each frequency band masks later
+#X text 526 136 Describes how energy in each frequency band masks later
 energy in the band. Here the masking is total for 4 analysis periods
 and then drops by 0.7 each period.;
 #X text 530 214 Forget all templates and start learning new ones. The
@@ -101,22 +101,22 @@
 #X text 595 334 Write templates to a file in text-editable format.
 ;
 #X text 596 364 Read templates from a file.;
-#X text 538 453 Print out all settings and templates.;
+#X text 514 450 Print out all settings and templates.;
 #X msg 442 120 minvel 10;
-#X text 538 392 Poll the current spectrum via "raw" outlet \, You can
+#X text 514 392 Poll the current spectrum via "raw" outlet \, You can
 set a very high threshold if you don't want attacks mixed in.;
 #X msg 437 426 debug 0;
-#X text 538 426 turn debugging on or off.;
-#X obj 326 525 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+#X text 514 426 turn debugging on or off.;
+#X obj 325 545 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
 1;
-#X obj 419 525 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+#X obj 407 545 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
 1;
-#X obj 370 554 print cooked;
-#X obj 277 554 print raw;
-#X text 253 490 enable printout:;
-#X text 533 121 Minimum "velocity" to output (quieter notes are ignored.)
+#X obj 358 574 print cooked;
+#X obj 276 574 print raw;
+#X text 158 545 enable printout:;
+#X text 530 121 Minimum "velocity" to output (quieter notes are ignored.)
 ;
-#X obj 462 513 s bonk-cooked;
+#X obj 461 533 s bonk-cooked;
 #X text 218 12 BONK~ - an attack detector for small percussion instruments
 ;
 #X text 8 174 Bonk's two outputs are the raw spectrum of the attack
@@ -127,12 +127,14 @@
 bands \, normalized so that 100 is an attack of amplitude of about
 1 The instrument number is significant only if Bonk has a "template
 set" in memory.;
-#X text 532 52 Set low and high thresholds. Signal growth must exceed
+#X text 531 47 Set low and high thresholds. Signal growth must exceed
 the high one and then fall to the low one to make an attack. The unit
 is the sum of the proportional growth in the 11 filter bands. Proportional
 growth is essentially the logarithmic time derivative.;
 #X text 238 27 (NOTE: this documentation does not yet describe new
 features for Pd 0.42).;
+#X msg 446 479 print 1;
+#X text 514 481 print out filterbank settings;
 #X connect 0 0 40 0;
 #X connect 1 0 2 0;
 #X connect 2 0 8 0;
@@ -157,3 +159,4 @@
 #X connect 36 0 2 0;
 #X connect 38 0 8 1;
 #X connect 39 0 0 1;
+#X connect 49 0 2 0;

Modified: trunk/pd/extra/bonk~/bonk~.c
===================================================================
--- trunk/pd/extra/bonk~/bonk~.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/extra/bonk~/bonk~.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -95,6 +95,7 @@
 #define DEFHALFTONES 6
 #define DEFOVERLAP 1
 #define DEFFIRSTBIN 1
+#define DEFMINBANDWIDTH 1.5
 #define DEFHITHRESH 5
 #define DEFLOTHRESH 2.5
 #define DEFMASKTIME 4
@@ -122,6 +123,7 @@
     float b_halftones;          /* filter bandwidth in halftones */
     float b_overlap;            /* overlap; default 1 for 1/2-power pts */
     float b_firstbin;           /* freq of first filter in bins, default 1 */
+    float b_minbandwidth;       /* minimum bandwidth, default 1.5 */
     t_filterkernel *b_vec;      /* filter kernels */
     int b_refcount;             /* number of bonk~ objects using this */
     struct _filterbank *b_next; /* next in linked list */
@@ -206,7 +208,7 @@
     float x_halftones;      /* nominal halftones between filters */
     float x_overlap;
     float x_firstbin;
-
+    float x_minbandwidth;
     float x_hithresh;       /* threshold for total growth to trigger */
     float x_lothresh;       /* threshold for total growth to re-arm */
     float x_minvel;         /* minimum velocity we output */
@@ -275,10 +277,11 @@
 
 static void bonk_tick(t_bonk *x);
 
-#define HALFWIDTH 0.75 /* half peak bandwidth at half power point in bins */
+#define HALFWIDTH 0.75  /* half peak bandwidth at half power point in bins */
+#define SLIDE 0.25    /* relative slide between filter subwindows */
 
 static t_filterbank *bonk_newfilterbank(int npoints, int nfilters,
-    float halftones, float overlap, float firstbin)
+    float halftones, float overlap, float firstbin, float minbandwidth)
 {
     int i, j;
     float cf, bw, h, relspace;
@@ -288,6 +291,7 @@
     b->b_halftones = halftones;
     b->b_overlap = overlap;
     b->b_firstbin = firstbin;
+    b->b_minbandwidth = minbandwidth;
     b->b_refcount = 0;
     b->b_next = bonk_filterbanklist;
     bonk_filterbanklist = b;
@@ -296,17 +300,21 @@
     h = exp((log(2.)/12.)*halftones);  /* specced interval between filters */
     relspace = (h - 1)/(h + 1);        /* nominal spacing-per-f for fbank */
     
+    if (minbandwidth < 2*HALFWIDTH)
+        minbandwidth = 2*HALFWIDTH;
+    if (firstbin < minbandwidth/(2*HALFWIDTH))
+        firstbin = minbandwidth/(2*HALFWIDTH);
     cf = firstbin;
     bw = cf * relspace * overlap;
-    if (bw < HALFWIDTH)
-        bw = HALFWIDTH;
+    if (bw < (0.5*minbandwidth))
+        bw = (0.5*minbandwidth);
     for (i = 0; i < nfilters; i++)
     {
         float *fp, newcf, newbw;
         float normalizer = 0;
         int filterpoints, skippoints, hoppoints, nhops;
         
-        filterpoints = 0.5 + npoints * HALFWIDTH/bw;
+        filterpoints = npoints * HALFWIDTH/bw;
         if (cf > npoints/2)
         {
             post("bonk~: only using %d filters (ran past Nyquist)", i+1);
@@ -320,7 +328,7 @@
         else if (filterpoints > npoints)
             filterpoints = npoints;
         
-        hoppoints = 0.5 + 0.5 * npoints * HALFWIDTH/bw;
+        hoppoints = SLIDE * npoints * HALFWIDTH/bw;
         
         nhops = 1. + (npoints-filterpoints)/(float)hoppoints;
         skippoints = 0.5 * (npoints-filterpoints - (nhops-1) * hoppoints);
@@ -343,7 +351,7 @@
             fp[1] = window * sin(phase);
             normalizer += window;
         }
-        normalizer = 1/(normalizer * nhops);
+        normalizer = 1/(normalizer * sqrt(nhops));
         for (fp = b->b_vec[i].k_stuff, j = 0;
              j < filterpoints; j++, fp+= 2)
             fp[0] *= normalizer, fp[1] *= normalizer;
@@ -353,10 +361,10 @@
 #endif
         newcf = (cf + bw/overlap)/(1 - relspace);
         newbw = newcf * overlap * relspace;
-        if (newbw < HALFWIDTH)
+        if (newbw < 0.5*minbandwidth)
         {
-            newbw = HALFWIDTH;
-            newcf = cf + 2 * HALFWIDTH / overlap;
+            newbw = 0.5*minbandwidth;
+            newcf = cf + minbandwidth / overlap;
         }
         cf = newcf;
         bw = newbw;
@@ -387,7 +395,7 @@
 
 static void bonk_donew(t_bonk *x, int npoints, int period, int nsig, 
     int nfilters, float halftones, float overlap, float firstbin,
-    float samplerate)
+    float minbandwidth, float samplerate)
 {
     int i, j;
     t_hist *h;
@@ -440,7 +448,8 @@
             fb->b_halftones == x->x_halftones &&
             fb->b_firstbin == firstbin &&
             fb->b_overlap == overlap &&
-            fb->b_npoints == x->x_npoints)
+            fb->b_npoints == x->x_npoints &&
+            fb->b_minbandwidth == minbandwidth)
     {
         fb->b_refcount++;
         x->x_filterbank = fb;
@@ -448,7 +457,7 @@
     }
     if (!x->x_filterbank)
         x->x_filterbank = bonk_newfilterbank(npoints, nfilters, 
-            halftones, overlap, firstbin),
+            halftones, overlap, firstbin, minbandwidth),
                 x->x_filterbank->b_refcount++;
 }
 
@@ -1035,7 +1044,7 @@
     int nsig = 1, period = DEFPERIOD, npts = DEFNPOINTS,
         nfilters = DEFNFILTERS, j;
     float halftones = DEFHALFTONES, overlap = DEFOVERLAP,
-        firstbin = DEFFIRSTBIN;
+        firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH;
     t_insig *g;
 
     if (argc > 0 && argv[0].a_type == A_FLOAT)
@@ -1082,6 +1091,11 @@
             firstbin = atom_getfloatarg(1, argc, argv);
             argc -= 2; argv += 2;
         }
+        else if (!strcmp(firstarg->s_name, "-minbandwidth") && argc > 1)
+        {
+            minbandwidth = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
         else if (!strcmp(firstarg->s_name, "-spew") && argc > 1)
         {
             x->x_spew = (atom_getfloatarg(1, argc, argv) != 0);
@@ -1123,7 +1137,7 @@
     }
     x->x_cookedout = outlet_new(&x->x_obj, gensym("list"));
     bonk_donew(x, npts, period, nsig, nfilters, halftones, overlap,
-        firstbin, sys_getsr());
+        firstbin, minbandwidth, sys_getsr());
     return (x);
 }
 
@@ -1182,6 +1196,9 @@
         attr = attr_offset_new("firstbin", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_firstbin));
         class_addattr(c, attr);
         
+        attr = attr_offset_new("minbandwidth", sym_float32, attrflags, (method)0L, (method)0L, calcoffset(t_bonk, x_minbandwidth));
+        class_addattr(c, attr);
+        
         attr = attr_offset_new("minvel", sym_float32, attrflags, (method)0L, (method)bonk_minvel_set, calcoffset(t_bonk, x_minvel));
         class_addattr(c, attr);
         
@@ -1250,6 +1267,7 @@
         x->x_nfilters = DEFNFILTERS;
         x->x_halftones = DEFHALFTONES;
         x->x_firstbin = DEFFIRSTBIN;
+        x->x_minbandwidth = DEFMINBANDWIDTH;
         x->x_overlap = DEFOVERLAP;
         x->x_ninsig = 1;
 
@@ -1305,7 +1323,8 @@
         x->x_clock = clock_new(x, (method)bonk_tick);
 
         bonk_donew(x, x->x_npoints, x->x_period, x->x_ninsig, x->x_nfilters,
-            x->x_halftones, x->x_overlap, x->x_firstbin, sys_getsr());
+            x->x_halftones, x->x_overlap, x->x_firstbin, x->x_minbandwidth,
+                sys_getsr());
     }
     return (x);
 }

Added: trunk/pd/extra/lrshift~/lrshift~-help.pd
===================================================================
--- trunk/pd/extra/lrshift~/lrshift~-help.pd	                        (rev 0)
+++ trunk/pd/extra/lrshift~/lrshift~-help.pd	2008-12-30 01:51:31 UTC (rev 10469)
@@ -0,0 +1,29 @@
+#N canvas 143 0 673 325 12;
+#X msg 268 277 bang;
+#X obj 244 303 print~;
+#X msg 185 278 bang;
+#X obj 161 304 print~;
+#X text 53 117 click here first;
+#X msg 72 270 bang;
+#X obj 48 296 print~;
+#X text 162 222 shift left;
+#X text 243 224 shift right;
+#X obj 161 252 lrshift~ 1;
+#X obj 244 251 lrshift~ -1;
+#X text 39 37 Acting at whatever vector size the window is running at \, lrshift~ shifts samples to the left (toward the beginning sample) or to the right. The argument gives the direction and the amount of the shift. The rightmost (or leftmost) samples are set to zero.;
+#X graph graph2 0 0 63 1 448 258 648 118;
+#X array shiftin 64 float;
+#X pop;
+#X obj 47 11 rlshift~;
+#X text 115 11 -- shift signal vector elements left or right;
+#X msg 54 138 \; pd dsp 1 \; shiftin 1 1;
+#X obj 48 204 tabreceive~ shiftin;
+#X text 525 308 Updated for Pd 0.31.;
+#X connect 0 0 1 0;
+#X connect 2 0 3 0;
+#X connect 5 0 6 0;
+#X connect 9 0 3 0;
+#X connect 10 0 1 0;
+#X connect 16 0 6 0;
+#X connect 16 0 9 0;
+#X connect 16 0 10 0;

Deleted: trunk/pd/extra/lrshift~/rlshift~-help.pd
===================================================================
--- trunk/pd/extra/lrshift~/rlshift~-help.pd	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/extra/lrshift~/rlshift~-help.pd	2008-12-30 01:51:31 UTC (rev 10469)
@@ -1,29 +0,0 @@
-#N canvas 143 0 673 325 12;
-#X msg 268 277 bang;
-#X obj 244 303 print~;
-#X msg 185 278 bang;
-#X obj 161 304 print~;
-#X text 53 117 click here first;
-#X msg 72 270 bang;
-#X obj 48 296 print~;
-#X text 162 222 shift left;
-#X text 243 224 shift right;
-#X obj 161 252 lrshift~ 1;
-#X obj 244 251 lrshift~ -1;
-#X text 39 37 Acting at whatever vector size the window is running at \, lrshift~ shifts samples to the left (toward the beginning sample) or to the right. The argument gives the direction and the amount of the shift. The rightmost (or leftmost) samples are set to zero.;
-#X graph graph2 0 0 63 1 448 258 648 118;
-#X array shiftin 64 float;
-#X pop;
-#X obj 47 11 rlshift~;
-#X text 115 11 -- shift signal vector elements left or right;
-#X msg 54 138 \; pd dsp 1 \; shiftin 1 1;
-#X obj 48 204 tabreceive~ shiftin;
-#X text 525 308 Updated for Pd 0.31.;
-#X connect 0 0 1 0;
-#X connect 2 0 3 0;
-#X connect 5 0 6 0;
-#X connect 9 0 3 0;
-#X connect 10 0 1 0;
-#X connect 16 0 6 0;
-#X connect 16 0 9 0;
-#X connect 16 0 10 0;

Modified: trunk/pd/extra/pd~/pd~.c
===================================================================
--- trunk/pd/extra/pd~/pd~.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/extra/pd~/pd~.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -177,11 +177,15 @@
     snprintf(pdexecbuf, MAXPDSTRING, "%s/bin/pd", pddir);
     if (stat(pdexecbuf, &statbuf) < 0)
     {
-        snprintf(pdexecbuf, MAXPDSTRING, "%s/pd", pddir);
+        snprintf(pdexecbuf, MAXPDSTRING, "%s/../../../bin/pd", pddir);
         if (stat(pdexecbuf, &statbuf) < 0)
         {
-            ERROR "pd~: can't stat %s", pdexecbuf);
-            goto fail1;
+            snprintf(pdexecbuf, MAXPDSTRING, "%s/pd", pddir);
+            if (stat(pdexecbuf, &statbuf) < 0)
+            {
+                ERROR "pd~: can't stat %s", pdexecbuf);
+                goto fail1;
+            }
         }
     }
     snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, 

Modified: trunk/pd/src/CHANGELOG.txt
===================================================================
--- trunk/pd/src/CHANGELOG.txt	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/CHANGELOG.txt	2008-12-30 01:51:31 UTC (rev 10469)
@@ -1,6 +1,6 @@
 This file describes implementation and API changes; stuff more visible to the
 user appears in the "release notes" instead.  See the bottom of this file
-for original notes on source stype and organization.
+for original notes on source style and organization.
 
 0.42.0 
 

Modified: trunk/pd/src/g_canvas.c
===================================================================
--- trunk/pd/src/g_canvas.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/g_canvas.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -51,7 +51,6 @@
 static void canvas_addtolist(t_canvas *x);
 static void canvas_takeofflist(t_canvas *x);
 static void canvas_pop(t_canvas *x, t_floatarg fvis);
-void canvas_create_editor(t_glist *x, int createit);
 
 /* --------- functions to handle the canvas environment ----------- */
 
@@ -513,8 +512,6 @@
     if (!menu)
         pd_pushsym(&x->gl_pd);
     glist_add(g, &x->gl_gobj);
-    if (glist_isvisible(g))
-        canvas_create_editor(x, 1);
     return (x);
 }
 
@@ -605,7 +602,8 @@
             canvas_getdir(x)->s_name);
 }
 
-void canvas_dirty(t_canvas *x, t_int n)
+    /* mark a glist dirty or clean */
+void canvas_dirty(t_canvas *x, t_floatarg n)
 {
     t_canvas *x2 = canvas_getrootfor(x);
     if (glist_amreloadingabstractions)
@@ -613,7 +611,8 @@
     if ((unsigned)n != x2->gl_dirty)
     {
         x2->gl_dirty = n;
-        canvas_reflecttitle(x2);
+        if (glist_isvisible(x2))
+            canvas_reflecttitle(x2);
     }
 }
 
@@ -663,15 +662,8 @@
     {
         if (glist_isvisible(x))
         {
-                /* just clear out the whole canvas... */
+                /* just clear out the whole canvas */
             sys_vgui(".x%lx.c delete all\n", x);
-#if 0
-                /* alternatively, we could have erased them one by one...
-            for (y = x->gl_list; y; y = y->g_next)
-                gobj_vis(y, x, 0);
-                    ... but we should go through and erase the lines as well
-                    if we do it that way. */
-#endif
             x->gl_mapped = 0;
         }
     }
@@ -695,14 +687,14 @@
     {
         t_glist *gl2 = x->gl_owner;
         if (!gl2) 
-            bug("canvas_vis");  /* shouldn't happen but don't get too upset. */
+            bug("glist_menu_open");  /* shouldn't happen but not dangerous */
         else
         {
                 /* erase ourself in parent window */
             gobj_vis(&x->gl_gobj, gl2, 0);
                     /* get rid of our editor (and subeditors) */
             if (x->gl_editor)
-                canvas_create_editor(x, 0);
+                canvas_destroy_editor(x);
             x->gl_havewindow = 1;
                     /* redraw ourself in parent window (blanked out this time) */
             gobj_vis(&x->gl_gobj, gl2, 1);
@@ -744,7 +736,8 @@
     glist_noselect(x);
     while (y = x->gl_list)
         glist_delete(x, y);
-    canvas_vis(x, 0);
+    if (x == glist_getcanvas(x))
+        canvas_vis(x, 0);
 
     if (strcmp(x->gl_name->s_name, "Pd"))
         pd_unbind(&x->gl_pd, canvas_makebindsym(x->gl_name));
@@ -1558,6 +1551,8 @@
         gensym("menu-open"), A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_map,
         gensym("map"), A_FLOAT, A_NULL);
+    class_addmethod(canvas_class, (t_method)canvas_dirty,
+        gensym("dirty"), A_FLOAT, A_NULL);
     class_setpropertiesfn(canvas_class, (t_propertiesfn)canvas_properties);
 
 /* ---------------------- list handling ------------------------ */

Modified: trunk/pd/src/g_canvas.h
===================================================================
--- trunk/pd/src/g_canvas.h	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/g_canvas.h	2008-12-30 01:51:31 UTC (rev 10469)
@@ -401,7 +401,8 @@
 EXTERN void glist_drawiofor(t_glist *glist, t_object *ob, int firsttime,
     char *tag, int x1, int y1, int x2, int y2);
 EXTERN void glist_eraseiofor(t_glist *glist, t_object *ob, char *tag);
-EXTERN void canvas_create_editor(t_glist *x, int createit);
+EXTERN void canvas_create_editor(t_glist *x);
+EXTERN void canvas_destroy_editor(t_glist *x);
 void canvas_deletelinesforio(t_canvas *x, t_text *text,
     t_inlet *inp, t_outlet *outp);
 extern int glist_amreloadingabstractions; /* stop GUI changes while reloading */ 
@@ -466,7 +467,7 @@
 EXTERN void canvas_unsetcurrent(t_canvas *x);
 EXTERN t_symbol *canvas_realizedollar(t_canvas *x, t_symbol *s);
 EXTERN t_canvas *canvas_getrootfor(t_canvas *x);
-EXTERN void canvas_dirty(t_canvas *x, t_int n);
+EXTERN void canvas_dirty(t_canvas *x, t_floatarg n);
 EXTERN int canvas_getfont(t_canvas *x);
 typedef int (*t_canvasapply)(t_canvas *x, t_int x1, t_int x2, t_int x3);
 

Modified: trunk/pd/src/g_editor.c
===================================================================
--- trunk/pd/src/g_editor.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/g_editor.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -27,6 +27,7 @@
 static t_binbuf *copy_binbuf;
 static char *canvas_textcopybuf;
 static int canvas_textcopybufsize;
+static t_glist *glist_finddirty(t_glist *x);
 
 /* ---------------- generic widget behavior ------------------------- */
 
@@ -166,12 +167,26 @@
     }
 }
 
+    /* recursively deselect everything in a gobj "g", if it happens to be
+    a glist, in preparation for deselecting g itself in glist_dselect() */
+static void glist_checkanddeselectall(t_glist *gl, t_gobj *g)
+{
+    t_glist *gl2;
+    t_gobj *g2;
+    if (pd_class(&g->g_pd) != canvas_class)
+        return;
+    gl2 = (t_glist *)g;
+    for (g2 = gl2->gl_list; g2; g2 = g2->g_next)
+        glist_checkanddeselectall(gl2, g2);
+    glist_noselect(gl2);
+}
+
     /* call this for selected objects only */
 void glist_deselect(t_glist *x, t_gobj *y)
 {
     int fixdsp = 0;
     static int reenter = 0;
-    if (reenter) return;
+    /* if (reenter) return; */
     reenter = 1;
     if (x->gl_editor)
     {
@@ -187,6 +202,7 @@
                 {
                     z = fuddy;
                     canvas_stowconnections(glist_getcanvas(x));
+                    glist_checkanddeselectall(x, y);
                 }
                 gobj_activate(y, x, 0);
             }
@@ -862,39 +878,31 @@
 
     /* recursively create or destroy all editors of a glist and its 
     sub-glists, as long as they aren't toplevels. */
-void canvas_create_editor(t_glist *x, int createit)
+void canvas_create_editor(t_glist *x)
 {
     t_gobj *y;
     t_object *ob;
-    if (createit)
+    if (!x->gl_editor)
     {
-        if (x->gl_editor)
-            bug("canvas_create_editor");
-        else
-        {
-            x->gl_editor = editor_new(x);
-            for (y = x->gl_list; y; y = y->g_next)
-                if (ob = pd_checkobject(&y->g_pd))
-                    rtext_new(x, ob);
-        }
+        x->gl_editor = editor_new(x);
+        for (y = x->gl_list; y; y = y->g_next)
+            if (ob = pd_checkobject(&y->g_pd))
+                rtext_new(x, ob);
     }
-    else
+}
+
+void canvas_destroy_editor(t_glist *x)
+{
+    t_gobj *y;
+    t_object *ob;
+    if (x->gl_editor)
     {
-        if (!x->gl_editor)
-            bug("canvas_create_editor");
-        else
-        {
-            for (y = x->gl_list; y; y = y->g_next)
-                if (ob = pd_checkobject(&y->g_pd))
-                    rtext_free(glist_findrtext(x, ob));
-            editor_free(x->gl_editor, x);
-            x->gl_editor = 0;
-        }
+        for (y = x->gl_list; y; y = y->g_next)
+            if (ob = pd_checkobject(&y->g_pd))
+                rtext_free(glist_findrtext(x, ob));
+        editor_free(x->gl_editor, x);
+        x->gl_editor = 0;
     }
-    for (y = x->gl_list; y; y = y->g_next)
-        if (pd_class(&y->g_pd) == canvas_class &&
-            ((t_canvas *)y)->gl_isgraph && !((t_canvas *)y)->gl_havewindow)
-                canvas_create_editor((t_canvas *)y, createit);
 }
 
 void canvas_reflecttitle(t_canvas *x);
@@ -907,6 +915,8 @@
 {
     char buf[30];
     int flag = (f != 0);
+    if (x != glist_getcanvas(x))
+        bug("canvas_vis");
     if (flag)
     {
         /* post("havewindow %d, isgraph %d, isvisible %d  editor %d",
@@ -926,7 +936,7 @@
         }
         else
         {
-            canvas_create_editor(x, 1);
+            canvas_create_editor(x);
             sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x,
                 (int)(x->gl_screenx2 - x->gl_screenx1),
                 (int)(x->gl_screeny2 - x->gl_screeny1),
@@ -949,14 +959,14 @@
                 subpatches fall here too but don'd need the editor freed, so
                 we check if it exists. */
             if (x->gl_editor)
-                canvas_create_editor(x, 0);
+                canvas_destroy_editor(x);
             return;
         }
         sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
         glist_noselect(x);
         if (glist_isvisible(x))
             canvas_map(x, 0);
-        canvas_create_editor(x, 0);
+        canvas_destroy_editor(x);
         sys_vgui("destroy .x%lx\n", x);
         for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++)
             ;
@@ -966,8 +976,6 @@
         if (glist_isgraph(x) && x->gl_owner)
         {
             t_glist *gl2 = x->gl_owner;
-            if (!x->gl_owner->gl_isdeleting)
-                canvas_create_editor(x, 1);
             if (glist_isvisible(gl2))
                 gobj_vis(&x->gl_gobj, gl2, 0);
             x->gl_havewindow = 0;
@@ -987,7 +995,7 @@
     {
         int hadeditor = (x->gl_editor != 0);
         if (hadeditor)
-            canvas_create_editor(x, 0);
+            canvas_destroy_editor(x);
         if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
             gobj_vis(&x->gl_gobj, x->gl_owner, 0);
         x->gl_isgraph = 0;
@@ -996,8 +1004,6 @@
             gobj_vis(&x->gl_gobj, x->gl_owner, 1);
             canvas_fixlinesfor(x->gl_owner, &x->gl_obj);
         }
-        if (hadeditor)
-            canvas_create_editor(x, 1);
     }
     else if (flag)
     {
@@ -1023,8 +1029,6 @@
         }
         if (glist_isvisible(x) && x->gl_goprect)
             glist_redraw(x);
-        if (x->gl_loading && x->gl_owner && glist_isvisible(x->gl_owner))
-            canvas_create_editor(x, 1);
         if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
         {
             gobj_vis(&x->gl_gobj, x->gl_owner, 1);
@@ -1549,7 +1553,7 @@
         else hiy = x->gl_editor->e_ywas, loy = ypos;
         canvas_selectinrect(x, lox, loy, hix, hiy);
         sys_vgui(".x%lx.c delete x\n", x);
-        x->gl_editor->e_onmotion = 0;
+        x->gl_editor->e_onmotion = MA_NONE;
     }
     else sys_vgui(".x%lx.c coords x %d %d %d %d\n",
             x, x->gl_editor->e_xwas,
@@ -1580,8 +1584,25 @@
             /* after motion, if there's only one item selected, activate it */
         if (x->gl_editor->e_selection &&
             !(x->gl_editor->e_selection->sel_next))
-                gobj_activate(x->gl_editor->e_selection->sel_what,
-                    x, 1);
+        {
+            t_gobj *g = x->gl_editor->e_selection->sel_what;
+            t_glist *gl2;
+                /* first though, check we aren't an abstraction with a
+                dirty sub-patch that would be discarded if we edit this. */
+            if (pd_class(&g->g_pd) == canvas_class &&
+                canvas_isabstraction((t_glist *)g) &&
+                    (gl2 = glist_finddirty((t_glist *)g)))
+            {
+                vmess(&gl2->gl_pd, gensym("menu-open"), "");
+                x->gl_editor->e_onmotion = MA_NONE;
+                sys_vgui(
+"pdtk_check {Discard changes to '%s'?} {.x%lx dirty 0;\n} no\n",
+                    canvas_getrootfor(gl2)->gl_name->s_name, gl2);
+                return;
+            }
+                /* OK, activate it */
+            gobj_activate(x->gl_editor->e_selection->sel_what, x, 1);
+        }
     }
     if (x->gl_editor->e_onmotion != MA_NONE)
         sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
@@ -1609,7 +1630,8 @@
     }
     if (resortin) canvas_resortinlets(x);
     if (resortout) canvas_resortoutlets(x);
-    canvas_dirty(x, 1);
+    if (x->gl_editor->e_selection)
+        canvas_dirty(x, 1);
 }
 
     /* this routine is called whenever a key is pressed or released.  "x"
@@ -1686,6 +1708,10 @@
         return;
     if (x && down)
     {
+        t_object *ob;
+            /* cancel any dragging action */
+        if (x->gl_editor->e_onmotion == MA_MOVE)
+            x->gl_editor->e_onmotion = MA_NONE;
             /* if an object has "grabbed" keys just send them on */
         if (x->gl_editor->e_grab
             && x->gl_editor->e_keyfn && keynum)
@@ -1699,15 +1725,34 @@
             || !strcmp(gotkeysym->s_name, "Left")
             || !strcmp(gotkeysym->s_name, "Right")))
         {
-            if (!x->gl_editor->e_textdirty)
+                /* special case - carriage return to object "makes" it */
+            if (keynum == '\n' && (ob =
+                pd_checkobject(&x->gl_editor->e_selection->sel_what->g_pd)) &&
+                    ob->te_type == T_OBJECT)
             {
-                canvas_setundo(x, canvas_undo_cut,
-                    canvas_undo_set_cut(x, UCUT_TEXT), "typing");
+                t_gobj *g;
+                int nobj, indx =
+                    canvas_getindex(x, x->gl_editor->e_selection->sel_what);
+                glist_noselect(x);
+                    /* "ob" may have disappeared; just search to the last
+                    object and select it */
+                for (g = x->gl_list, nobj = 0; g; g = g->g_next, nobj++)
+                    if (nobj == indx)
+                        glist_select(x, g);
             }
-            rtext_key(x->gl_editor->e_textedfor,
-                (int)keynum, gotkeysym);
-            if (x->gl_editor->e_textdirty)
-                canvas_dirty(x, 1);
+            else
+            {
+                    /* otherwise send the key to the box's editor */
+                if (!x->gl_editor->e_textdirty)
+                {
+                    canvas_setundo(x, canvas_undo_cut,
+                        canvas_undo_set_cut(x, UCUT_TEXT), "typing");
+                }
+                rtext_key(x->gl_editor->e_textedfor,
+                    (int)keynum, gotkeysym);
+                if (x->gl_editor->e_textdirty)
+                    canvas_dirty(x, 1);
+            }
         }
             /* check for backspace or clear */
         else if (keynum == 8 || keynum == 127)
@@ -1795,6 +1840,7 @@
 }
 
 /* ----------------------------- window stuff ----------------------- */
+extern int sys_perf;
 
 void canvas_print(t_canvas *x, t_symbol *s)
 {
@@ -1827,11 +1873,11 @@
     {
         canvas_vis(g2, 1);
         sys_vgui(
-"pdtk_check {Discard changes to this window??} {.x%lx menuclose 3;\n} no\n",
-                g2);
+"pdtk_check {Discard changes to '%s'?} {.x%lx menuclose 3;\n} no\n",
+                canvas_getrootfor(g2)->gl_name->s_name, g2);
         return;
     }
-    if (f == 0)
+    if (f == 0 && sys_perf)
         sys_vgui("pdtk_check {really quit?} {pd quit;\n} yes\n");
     else glob_quit(0);
 }
@@ -1854,18 +1900,19 @@
         g = glist_finddirty(x);
         if (g)
         {
-            canvas_vis(g, 1);
+            vmess(&g->gl_pd, gensym("menu-open"), "");
             sys_vgui(
-"pdtk_check {Discard changes to this window??} {.x%lx menuclose 2;\n} no\n",
-                g);
+"pdtk_check {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
+                canvas_getrootfor(g)->gl_name->s_name, g);
             return;
         }
-        else
+        else if (sys_perf)
         {
             sys_vgui(
-"pdtk_check {Close this window??} {.x%lx menuclose 1;\n} yes\n",
-                x);
+"pdtk_check {Close '%s'?} {.x%lx menuclose 1;\n} yes\n",
+                canvas_getrootfor(x)->gl_name->s_name, x);
         }
+        else pd_free(&x->gl_pd);
     }
     else if (force == 1)
         pd_free(&x->gl_pd);
@@ -1877,10 +1924,10 @@
         g = glist_finddirty(x);
         if (g)
         {
-            canvas_vis(g, 1);
+            vmess(&g->gl_pd, gensym("menu-open"), "");
             sys_vgui(
-"pdtk_check {Discard changes to this window??} {.x%lx menuclose 2;\n} no\n",
-                g);
+"pdtk_check {Discard changes to '%s'?} {.x%lx menuclose 2;\n} no\n",
+                canvas_getrootfor(x)->gl_name->s_name, g);
             return;
         }
         else pd_free(&x->gl_pd);
@@ -2361,10 +2408,10 @@
         as needed */ 
     if (pd_class(&src->g_pd) == text_class && objsrc->te_type == T_OBJECT)
         while (outno >= obj_noutlets(objsrc))
-            outlet_new(objsrc, &s_);
+            outlet_new(objsrc, 0);
     if (pd_class(&sink->g_pd) == text_class && objsink->te_type == T_OBJECT)
         while (inno >= obj_ninlets(objsink))
-            inlet_new(objsink, &objsink->ob_pd, &s_, &s_);
+            inlet_new(objsink, &objsink->ob_pd, 0, 0);
 
     if (!(oc = obj_connect(objsrc, outno, objsink, inno))) goto bad;
     if (glist_isvisible(x))

Modified: trunk/pd/src/g_rtext.c
===================================================================
--- trunk/pd/src/g_rtext.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/g_rtext.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -342,8 +342,11 @@
 /* find the rtext that goes with a text item */
 t_rtext *glist_findrtext(t_glist *gl, t_text *who)
 {
-    t_rtext *x = gl->gl_editor->e_rtext;
-    while (x && x->x_text != who) x = x->x_next;
+    t_rtext *x;
+    if (!gl->gl_editor)
+        canvas_create_editor(gl);
+    for (x = gl->gl_editor->e_rtext; x && x->x_text != who; x = x->x_next)
+        ;
     if (!x) bug("glist_findrtext");
     return (x);
 }

Modified: trunk/pd/src/g_text.c
===================================================================
--- trunk/pd/src/g_text.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/g_text.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -131,9 +131,36 @@
     canvas_unsetcurrent((t_canvas *)gl);
 }
 
+    /* utility routine to figure out where to put a new text box from menu
+    and whether to connect to it automatically */
+static void canvas_howputnew(t_canvas *x, int *connectp, int *xpixp, int *ypixp,
+    int *indexp, int *totalp)
+{
+    int xpix, ypix, indx = 0, nobj = 0, x1, x2, y1, y2;
+    int connectme = (x->gl_editor->e_selection &&
+        !x->gl_editor->e_selection->sel_next);
+    if (connectme)
+    {
+        t_gobj *g;
+        for (g = x->gl_list, nobj = 0; g; g = g->g_next, nobj++)
+            if (g == x->gl_editor->e_selection->sel_what)
+        {
+            gobj_getrect(g, x, &x1, &y1, &x2, &y2);
+            indx = nobj;
+            *xpixp = x1;
+            *ypixp = y2 + 5;
+        }
+    }
+    else glist_getnextxy(x, xpixp, ypixp);
+    glist_noselect(x);
+    *connectp = connectme;
+    *indexp = indx;
+    *totalp = nobj;
+}
+
     /* object creation routine.  These are called without any arguments if
-    they're invoked from the
-    gui; when pasting or restoring from a file, we get at least x and y. */
+    they're invoked from the gui; when pasting or restoring from a file, we
+    get at least x and y. */
 
 void canvas_obj(t_glist *gl, t_symbol *s, int argc, t_atom *argv)
 {
@@ -145,18 +172,20 @@
         canvas_objtext(gl, atom_getintarg(0, argc, argv),
             atom_getintarg(1, argc, argv), 0, b);
     }
-    else if(!glist_isvisible(gl)){
-      /* JMZ: not a good idea to go into interactive mode in a closed canvas... */
-      post("unable to create stub object in closed canvas!");
-      return;
-    } else {
+        /* JMZ: don't go into interactive mode in a closed canvas */
+    else if (!glist_isvisible(gl))
+        post("unable to create stub object in closed canvas!");
+    else
+    {
+            /* interactively create new obect */
         t_binbuf *b = binbuf_new();
-        int xpix, ypix;
+        int connectme, xpix, ypix, indx, nobj;
+        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
         pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
-        glist_noselect(gl);
-        glist_getnextxy(gl, &xpix, &ypix);
         canvas_objtext(gl, xpix, ypix, 1, b);
-        canvas_startmotion(glist_getcanvas(gl));
+        if (connectme)
+            canvas_connect(gl, indx, 0, nobj, 0);
+        else canvas_startmotion(glist_getcanvas(gl));
     }
 }
 
@@ -417,24 +446,23 @@
         if (argc > 2) binbuf_restore(x->m_text.te_binbuf, argc-2, argv+2);
         glist_add(gl, &x->m_text.te_g);
     }
+    else if (!glist_isvisible(gl))
+        post("unable to create stub message in closed canvas!");
     else
     {
-        int xpix, ypix;
-        /* JMZ: not a good idea to go into interactive mode in a closed canvas... */
-        if(!glist_isvisible(gl)){
-          post("unable to create stub message in closed canvas!");
-          return;
-        }
+        int connectme, xpix, ypix, indx, nobj;
+        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
+        
         pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
-        glist_noselect(gl);
-        glist_getnextxy(gl, &xpix, &ypix);
-        x->m_text.te_xpix = xpix-3;
-        x->m_text.te_ypix = ypix-3;
+        x->m_text.te_xpix = xpix;
+        x->m_text.te_ypix = ypix;
         glist_add(gl, &x->m_text.te_g);
         glist_noselect(gl);
         glist_select(gl, &x->m_text.te_g);
         gobj_activate(&x->m_text.te_g, gl, 1);
-        canvas_startmotion(glist_getcanvas(gl));
+        if (connectme)
+            canvas_connect(gl, indx, 0, nobj, 0);
+        else canvas_startmotion(glist_getcanvas(gl));
     }
 }
 
@@ -876,19 +904,20 @@
     }
     else
     {
-        int xpix, ypix;
+        int connectme, xpix, ypix, indx, nobj;
+        canvas_howputnew(gl, &connectme, &xpix, &ypix, &indx, &nobj);
         outlet_new(&x->a_text,
             x->a_atom.a_type == A_FLOAT ? &s_float: &s_symbol);
         inlet_new(&x->a_text, &x->a_text.te_pd, 0, 0);
         pd_vmess(&gl->gl_pd, gensym("editmode"), "i", 1);
-        glist_noselect(gl);
-        glist_getnextxy(gl, &xpix, &ypix);
         x->a_text.te_xpix = xpix;
         x->a_text.te_ypix = ypix;
         glist_add(gl, &x->a_text.te_g);
         glist_noselect(gl);
         glist_select(gl, &x->a_text.te_g);
-        canvas_startmotion(glist_getcanvas(gl));
+        if (connectme)
+            canvas_connect(gl, indx, 0, nobj, 0);
+        else canvas_startmotion(glist_getcanvas(gl));
     }
 }
 
@@ -1321,10 +1350,18 @@
     else binbuf_text(x->te_binbuf, buf, bufsize);
 }
 
+    /* this gets called when amessage gets sent to an object whose creation
+    failed, presumably because of loading a patch with a missing extern or
+    abstraction */
+static void text_anything(t_text *x, t_symbol *s, int argc, t_atom *argv)
+{
+}
+
 void g_text_setup(void)
 {
     text_class = class_new(gensym("text"), 0, 0, sizeof(t_text),
         CLASS_NOINLET | CLASS_PATCHABLE, 0);
+    class_addanything(text_class, text_anything);
 
     message_class = class_new(gensym("message"), 0, (t_method)message_free,
         sizeof(t_message), CLASS_PATCHABLE, 0);

Modified: trunk/pd/src/m_glob.c
===================================================================
--- trunk/pd/src/m_glob.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/m_glob.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -8,6 +8,8 @@
 t_class *glob_pdobject;
 static t_class *maxclass;
 
+int sys_perf;   /* true if we should query user on close and quit */
+
 /* These "glob" routines, which implement messages to Pd, are from all
 over.  Some others are prototyped in m_imp.h as well. */
 
@@ -55,6 +57,11 @@
         error("file format newer than this version of Pd (trying anyway...)");
 }
 
+static void glob_perf(t_pd *dummy, float f)
+{
+    sys_perf = (f != 0);
+}
+
 void max_default(t_pd *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
@@ -121,6 +128,8 @@
         gensym("save-preferences"), 0);
     class_addmethod(glob_pdobject, (t_method)glob_version,
         gensym("version"), A_FLOAT, 0);
+    class_addmethod(glob_pdobject, (t_method)glob_perf,
+        gensym("perf"), A_FLOAT, 0);
 #ifdef UNIX
     class_addmethod(glob_pdobject, (t_method)glob_watchdog,
         gensym("watchdog"), 0);
@@ -128,3 +137,16 @@
     class_addanything(glob_pdobject, max_default);
     pd_bind(&glob_pdobject, gensym("pd"));
 }
+
+    /* function to return version number at run time.  Any of the
+    calling pointers may be zero in case you don't need all of them. */
+void sys_getversion(int *major, int *minor, int *bugfix)
+{
+    if (major)
+        *major = PD_MAJOR_VERSION;
+    if (minor)
+        *minor = PD_MINOR_VERSION;
+    if (bugfix)
+        *bugfix = PD_BUGFIX_VERSION;
+}
+

Modified: trunk/pd/src/m_pd.h
===================================================================
--- trunk/pd/src/m_pd.h	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/m_pd.h	2008-12-30 01:51:31 UTC (rev 10469)
@@ -11,7 +11,7 @@
 #define PD_MAJOR_VERSION 0
 #define PD_MINOR_VERSION 42
 #define PD_BUGFIX_VERSION 0
-#define PD_TEST_VERSION "test6"
+#define PD_TEST_VERSION "test8"
 
 /* old name for "MSW" flag -- we have to take it for the sake of many old
 "nmakefiles" for externs, which will define NT and not MSW */
@@ -642,6 +642,9 @@
 #define PD_BIGORSMALL(f) 0
 #endif
 
+    /* get version number at run time */
+EXTERN void sys_getversion(int *major, int *minor, int *bugfix);
+
 #if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
 }
 #endif

Modified: trunk/pd/src/makefile.in
===================================================================
--- trunk/pd/src/makefile.in	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/makefile.in	2008-12-30 01:51:31 UTC (rev 10469)
@@ -163,32 +163,33 @@
 
 BINARYMODE=@binarymode@
 
-ABOUT_FILE=$(pddocdir)/1.manual/1.introduction.txt
+ABOUT_FILE=$(DESTDIR)$(pddocdir)/1.manual/1.introduction.txt
 install:  all
-	install -d $(libpdbindir)
-	install $(BIN_DIR)/$(GUINAME) $(libpdbindir)/$(GUINAME)
-	install $(BIN_DIR)/pd-watchdog $(libpdbindir)/pd-watchdog
-	install -m644 $(BIN_DIR)/pd.tk $(libpdbindir)/pd.tk
+	install -d $(DESTDIR)$(libpdbindir)
+	install $(BIN_DIR)/$(GUINAME) $(DESTDIR)$(libpdbindir)/$(GUINAME)
+	install $(BIN_DIR)/pd-watchdog $(DESTDIR)$(libpdbindir)/pd-watchdog
+	install -m644 $(BIN_DIR)/pd.tk $(DESTDIR)$(libpdbindir)/pd.tk
 	install -d $(DESTDIR)$(bindir)
 	install $(BINARYMODE) $(PDEXEC) $(DESTDIR)$(bindir)/pd
 	install -m755 $(BIN_DIR)/pdsend $(DESTDIR)$(bindir)/pdsend
 	install -m755 $(BIN_DIR)/pdreceive $(DESTDIR)$(bindir)/pdreceive 
 	for dir in $(shell ls -1 ../doc | grep -v CVS); do \
 		echo "installing $$dir"; \
-		install -d $(pddocdir)/$$dir ; \
-		install -m644 -p ../doc/$$dir/*.* $(pddocdir)/$$dir ; \
+		install -d $(DESTDIR)$(pddocdir)/$$dir ; \
+		install -m644 -p ../doc/$$dir/*.* $(DESTDIR)$(pddocdir)/$$dir ; \
 	done
 	for dir in $(shell ls -1 ../doc/7.stuff | grep -v CVS); do \
 		echo "installing 7.stuff/$$dir"; \
-		install -d $(pddocdir)/7.stuff/$$dir ; \
-		install -m644 -p ../doc/7.stuff/$$dir/*.* $(pddocdir)/7.stuff/$$dir ; \
+		install -d $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
+		install -m644 -p ../doc/7.stuff/$$dir/*.* \
+                    $(DESTDIR)$(pddocdir)/7.stuff/$$dir ; \
 	done
 	mv $(ABOUT_FILE) $(ABOUT_FILE).tmp
 	cat $(ABOUT_FILE).tmp | sed 's|PD_VERSION|Pd version $(PD_VERSION)|' \
 		> $(ABOUT_FILE)
 	rm $(ABOUT_FILE).tmp
-	cp -pr ../extra $(libpddir)/
-	rm -f $(libpddir)/extra/*/*.o
+	cp -pr ../extra $(DESTDIR)$(libpddir)/
+	rm -f $(DESTDIR)$(libpddir)/extra/*/*.o
 	install -d $(DESTDIR)$(includedir)
 	install -m644 m_pd.h $(DESTDIR)$(includedir)/m_pd.h
 	install -d $(DESTDIR)$(mandir)/man1
@@ -230,7 +231,7 @@
 	$(CC) $(CPPFLAGS) -M $(SRC) > makefile.dependencies
 
 uninstall:
-	rm -f -r $(libpddir)
+	rm -f -r $(DESTDIR)$(libpddir)
 	rm -f $(DESTDIR)$(bindir)/pd
 	rm -f $(DESTDIR)$(bindir)/pdsend
 	rm -f $(DESTDIR)$(bindir)/pdreceive

Modified: trunk/pd/src/notes.txt
===================================================================
--- trunk/pd/src/notes.txt	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/notes.txt	2008-12-30 01:51:31 UTC (rev 10469)
@@ -1,5 +1,5 @@
 ---------------- dolist --------------------
-done: 
+close patch with dirty GOP abstraction can't vis the abstraction to query
 
 test:
 compile on various versions of linux
@@ -15,6 +15,7 @@
 Gnome: why don't windows pop up when clicked on?
 
 problems:
+saving as "x.pd" on mac writes to "x.pd.pd"
 if .pdsettings asks for an alsa device out of range, dialog
   comes up with empty list
 find asdf$1 (e.g.) doesn't work
@@ -29,7 +30,6 @@
 TK commands to nonexistent windows? (occasionally still happens)
 still can't detect when a window is moved or resized
 open_via_path call in d_soundfile.c isn't threadsafe
-crashed Pd putting vec and template in wrong order in array element of struct
 floor, ciel functions in expr misdeclared
 graph names don't appear until graph moved? (invis/vis on new array/rename)
 don't filter locked click() through getrect

Modified: trunk/pd/src/s_audio.c
===================================================================
--- trunk/pd/src/s_audio.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_audio.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -175,7 +175,7 @@
 
     /* set audio device settings (after cleaning up the specified device and
     channel vectors).  The audio devices are "zero based" (i.e. "0" means the
-    first one.)  We can later re-open audio and/or show the settings on a\
+    first one.)  We can later re-open audio and/or show the settings on a
     dialog window. */
 
 void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,

Modified: trunk/pd/src/s_audio_oss.c
===================================================================
--- trunk/pd/src/s_audio_oss.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_audio_oss.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -70,7 +70,6 @@
 
     /* OSS-specific private variables */
 static int oss_blockmode = 1;   /* flag to use "blockmode"  */
-static int oss_32bit = 0;       /* allow 23 bit transfers in OSS  */
 static char ossdsp[] = "/dev/dsp%d"; 
 
     /* don't assume we can turn all 31 bits when doing float-to-fix; 
@@ -109,12 +108,6 @@
     countedthem = 1;
 }
 
-void oss_set32bit( void)
-{
-    oss_32bit = 1;
-}
-
-
 typedef struct _multidev {
      int fd;
      int channels;
@@ -128,15 +121,6 @@
      return err;
 }
 
-    /* The AFMT_S32_BLOCKED format is not defined in standard linux kernels
-    but is proposed by Guenter Geiger to support extending OSS to handle
-    32 bit sample.  This is user in Geiger's OSS driver for RME Hammerfall.
-    I'm not clear why this isn't called AFMT_S32_[SLN]E... */
-
-#ifndef AFMT_S32_BLOCKED
-#define AFMT_S32_BLOCKED 0x0000400
-#endif
-
 void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
 {
     int orig, param, nblk, fd = dev->d_fd, wantformat;
@@ -145,22 +129,12 @@
 
     audio_buf_info ainfo;
 
-        /* set resolution - first try 4 byte samples */
-    if (oss_32bit && (ioctl(fd,SNDCTL_DSP_GETFMTS,&param) >= 0) &&
-        (param & AFMT_S32_BLOCKED))
-    {
-        wantformat = AFMT_S32_BLOCKED;
-        dev->d_bytespersamp = 4;
-    }
-    else
-    {
-        wantformat = AFMT_S16_NE;
-        dev->d_bytespersamp = 2;
-    }
+        /* we only know how to do 2 byte samples */
+    wantformat = AFMT_S16_NE;
+    dev->d_bytespersamp = 2;
+
     param = wantformat;
 
-    if (sys_verbose)
-        post("bytes per sample = %d", dev->d_bytespersamp);
     if (ioctl(fd, SNDCTL_DSP_SETFMT, &param) == -1)
         fprintf(stderr,"OSS: Could not set DSP format\n");
     else if (wantformat != param)
@@ -740,19 +714,8 @@
             linux_dacs[dev].d_dropcount--;
         else
         {
-            if (linux_dacs[dev].d_bytespersamp == 4)
+            if (linux_dacs[dev].d_bytespersamp == 2)
             {
-                for (i = DEFDACBLKSIZE * nchannels,  fp1 = sys_soundout +       
-                    DEFDACBLKSIZE*thischan,
-                    lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
-                {
-                    float f = *fp1 * 2147483648.;
-                    *lp = (f >= 2147483647. ? 2147483647. : 
-                        (f < -2147483648. ? -2147483648. : f));
-                }
-            }
-            else
-            {
                 for (i = DEFDACBLKSIZE,  fp1 = sys_soundout +   
                     DEFDACBLKSIZE*thischan,
                     sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
@@ -798,17 +761,8 @@
         }
         timeref = timenow;
 
-        if (linux_adcs[dev].d_bytespersamp == 4)
+        if (linux_adcs[dev].d_bytespersamp == 2)
         {
-            for (i = DEFDACBLKSIZE*nchannels,
-                fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
-                    lp = (t_oss_int32 *)buf; i--; fp1++, lp++)
-            {
-                *fp1 = ((float)(*lp))*(float)(1./2147483648.);
-            }
-        }
-        else
-        {
             for (i = DEFDACBLKSIZE,fp1 = sys_soundin + thischan*DEFDACBLKSIZE,
                 sp = (t_oss_int16 *)buf; i--; fp1++, sp += nchannels)
             {

Modified: trunk/pd/src/s_audio_pa.c
===================================================================
--- trunk/pd/src/s_audio_pa.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_audio_pa.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -11,7 +11,6 @@
 #include "s_stuff.h"
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
 #include <portaudio.h>
 #include "s_audio_pablio.h"
 
@@ -30,11 +29,15 @@
 
 int pa_foo;
 
+#ifndef MSW
+#include <unistd.h>
+#endif
 static void pa_init(void)
 {
     static int initialized;
     if (!initialized)
     {
+#ifndef MSW
         /* Initialize PortAudio  */
         /* for some reason Pa_Initialize(0 closes file descriptor 1.
         As a workaround, dup it to another number and dup2 it back
@@ -46,6 +49,9 @@
             dup2(newfd, 1);
             close(newfd);
         }
+#else
+        int err = Pa_Initialize();
+#endif
         if ( err != paNoError ) 
         {
             fprintf( stderr,

Modified: trunk/pd/src/s_loader.c
===================================================================
--- trunk/pd/src/s_loader.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_loader.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -203,8 +203,6 @@
     return (1);
 }
 
-/* callback type definition */
-typedef int (*loader_t)(t_canvas *canvas, char *classname);
 
 /* linked list of loaders */
 typedef struct loader_queue {

Modified: trunk/pd/src/s_main.c
===================================================================
--- trunk/pd/src/s_main.c	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_main.c	2008-12-30 01:51:31 UTC (rev 10469)
@@ -333,7 +333,6 @@
 
 #ifdef USEAPI_OSS
 "-oss             -- use OSS audio API\n",
-"-32bit           ----- allow 32 bit OSS audio (for RME Hammerfall)\n",
 #endif
 
 #ifdef USEAPI_ALSA
@@ -619,12 +618,6 @@
             sys_set_audio_api(API_OSS);
             argc--; argv++;
         }
-        else if (!strcmp(*argv, "-32bit"))
-        {
-            sys_set_audio_api(API_OSS);
-            oss_set32bit();
-            argc--; argv++;
-        }
 #endif
 #ifdef USEAPI_ALSA
         else if (!strcmp(*argv, "-alsa"))

Modified: trunk/pd/src/s_stuff.h
===================================================================
--- trunk/pd/src/s_stuff.h	2008-12-29 14:34:50 UTC (rev 10468)
+++ trunk/pd/src/s_stuff.h	2008-12-30 01:51:31 UTC (rev 10469)
@@ -49,11 +49,14 @@
 
 extern int sys_defaultfont;
 extern t_symbol *sys_libdir;    /* library directory for auxilliary files */
-extern t_symbol *sys_guidir;    /* directory holding pd_gui (also pd, u_pdsend, etc) */
+extern t_symbol *sys_guidir;    /* directory holding pd_gui, u_pdsend, etc */
 
 /* s_loader.c */
-int sys_load_lib(t_canvas *canvas, char *filename);
 
+typedef int (*loader_t)(t_canvas *canvas, char *classname); /* callback type */
+EXTERN int sys_load_lib(t_canvas *canvas, char *filename);
+EXTERN void sys_register_loader(loader_t loader);
+
 /* s_audio.c */
 
 #define SENDDACS_NO 0           /* return values for sys_send_dacs() */


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Pd-cvs mailing list