From 61aa1bbe16f53ee6abb499c1f0a6e3bf010d15fd Mon Sep 17 00:00:00 2001
From: Ivica Ico Bukvic <ico@vt.edu>
Date: Sun, 7 Oct 2012 21:10:59 -0400
Subject: [PATCH] backported audio driver support from 0.43 and the pd/extra
 folder with supporting fixes/merges where needed. Removed outdated expr-help
 file in favor of new documentation.

---
 extra/bonk~/bonk~-help.pd |   4 +-
 extra/bonk~/bonk~.c       | 179 ++++++++++-
 extra/bonk~/makefile      |   2 +-
 extra/choice/choice.c     |   2 +-
 extra/choice/makefile     |   2 +-
 extra/expr~/makefile      |  10 +-
 extra/expr~/vexp_if.c     |   4 +-
 extra/fiddle~/makefile    |   2 +-
 extra/loop~/loop~-help.pd |  22 +-
 extra/loop~/loop~.c       |  26 +-
 extra/loop~/makefile      |   2 +-
 extra/lrshift~/lrshift~.c |   8 +-
 extra/lrshift~/makefile   |   2 +-
 extra/pd~/makefile        |   3 +-
 extra/pd~/pdsched.c       |  25 +-
 extra/pd~/pd~.c           |  12 +-
 extra/pique/makefile      |   2 +-
 extra/pique/pique.c       |  42 +--
 extra/sigmund~/makefile   |   2 +-
 extra/sigmund~/sigmund~.c |  40 ++-
 extra/stdout/makefile     |   2 +-
 src/s_audio.c             | 219 +++++++++----
 src/s_audio_alsa.c        |  39 ++-
 src/s_audio_alsa.h        |   2 +-
 src/s_audio_alsamm.c      |   8 +-
 src/s_audio_jack.c        | 645 ++++++++++++++++++++++----------------
 src/s_audio_oss.c         |  21 +-
 src/s_file.c              |  15 +-
 src/s_main.c              |  12 +-
 src/s_stuff.h             |  55 +++-
 30 files changed, 934 insertions(+), 475 deletions(-)

diff --git a/extra/bonk~/bonk~-help.pd b/extra/bonk~/bonk~-help.pd
index e52b7c506..4666d6f55 100644
--- a/extra/bonk~/bonk~-help.pd
+++ b/extra/bonk~/bonk~-help.pd
@@ -1,4 +1,4 @@
-#N canvas 43 123 1054 583 12;
+#N canvas 0 0 1052 581 12;
 #X obj 382 492 spigot;
 #X msg 484 293 bang;
 #X obj 483 454 bonk~;
@@ -107,7 +107,7 @@ Bonk check the attack against a collection of stored templates to try
 to guess which of two or more instruments was hit. Bonk is described
 theoretically in the 1998 ICMC proceedings \, reprinted on crca.ucsd.edu/~msp
 .;
-#N canvas 723 241 701 719 creation-arguments 0;
+#N canvas 0 0 699 717 creation-arguments 1;
 #X text 228 14 creation arguments for bonk~;
 #X text 70 272 -npts 256;
 #X text 44 244 default value:;
diff --git a/extra/bonk~/bonk~.c b/extra/bonk~/bonk~.c
index d0f18de96..f1d49c9c1 100644
--- a/extra/bonk~/bonk~.c
+++ b/extra/bonk~/bonk~.c
@@ -82,7 +82,9 @@ void *bonk_class;
 static t_class *bonk_class;
 #endif
 
-#ifndef _MSC_VER
+#ifdef _WIN32
+#include <malloc.h>
+#elif ! defined(_MSC_VER)
 #include <alloca.h>
 #endif
 
@@ -195,6 +197,7 @@ typedef struct _bonk
     t_object x_obj;
     t_outlet *x_cookedout;
     t_clock *x_clock;
+    t_canvas *x_canvas;     /* ptr to current canvas --fbar */
 #endif /* PD */
 #ifdef MSP
     t_pxobject x_obj;
@@ -256,7 +259,12 @@ static void bonk_print(t_bonk *x, t_floatarg f);
 static void bonk_bang(t_bonk *x);
 
 static void bonk_write(t_bonk *x, t_symbol *s);
+static void bonk_dowrite(t_bonk *x, t_symbol *s);
+static void bonk_writefile(t_bonk *x, char *filename, short path);
+
 static void bonk_read(t_bonk *x, t_symbol *s);
+static void bonk_doread(t_bonk *x, t_symbol *s);
+static void bonk_openfile(t_bonk *x, char *filename, short path);
 
 void bonk_minvel_set(t_bonk *x, void *attr, long ac, t_atom *av);
 void bonk_lothresh_set(t_bonk *x, void *attr, long ac, t_atom *av);
@@ -960,13 +968,21 @@ static void bonk_bang(t_bonk *x)
     bonk_tick(x);
 }
 
+#ifdef PD
 static void bonk_read(t_bonk *x, t_symbol *s)
 {
-    FILE *fd = fopen(s->s_name, "r");
     float vec[MAXNFILTERS];
     int i, ntemplate = 0, remaining;
     float *fp, *fp2;
-    if (!fd)
+
+    /* fbar: canvas_open code taken from g_array.c */
+    FILE *fd;
+    char buf[MAXPDSTRING], *bufptr;
+    int filedesc;
+
+    if ((filedesc = canvas_open(x->x_canvas,
+            s->s_name, "", buf, &bufptr, MAXPDSTRING, 0)) < 0 
+                || !(fd = fdopen(filedesc, "r")))
     {
         post("%s: open failed", s->s_name);
         return;
@@ -998,14 +1014,103 @@ nomore:
     x->x_ntemplate = ntemplate;
     fclose(fd);
 }
+#endif
+
+#ifdef MSP
+static void bonk_read(t_bonk *x, t_symbol *s)
+{
+    defer(x, (method)bonk_doread, s, 0, NULL);
+}
+
+static void bonk_doread(t_bonk *x, t_symbol *s)
+{
+    long filetype = 'TEXT', outtype;
+    char filename[512];
+    short path;
+    
+    if (s == gensym("")) {
+        if (open_dialog(filename, &path, &outtype, &filetype, 1))
+            return;
+    } else {
+        strcpy(filename, s->s_name);
+        if (locatefile_extended(filename, &path, &outtype, &filetype, 1)) {
+            object_error((t_object *) x, "%s: not found", s->s_name);
+            return;
+        }
+    }
+    // we have a file
+    bonk_openfile(x, filename, path);
+}
+
+static void bonk_openfile(t_bonk *x, char *filename, short path) {
+    float vec[MAXNFILTERS];
+    int i, ntemplate = 0, remaining;
+    float *fp, *fp2;
+    
+    t_filehandle fh;
+    char **texthandle;
+    char *tokptr;
+    
+    if (path_opensysfile(filename, path, &fh, READ_PERM)) {
+        object_error((t_object *) x, "error opening %s", filename);
+        return;
+    }
+    
+    texthandle = sysmem_newhandle(0);
+    sysfile_readtextfile(fh, texthandle, 0, TEXT_LB_NATIVE);
+    sysfile_close(fh);
+    
+    x->x_template = (t_template *)t_resizebytes(x->x_template, 
+                                                x->x_ntemplate * sizeof(t_template), 0);
+    
+    tokptr = strtok(*texthandle, " \n");
+    
+    while(tokptr != NULL)
+    {
+        for (i = x->x_nfilters, fp = vec; i--; fp++) {
+            if (sscanf(tokptr, "%f", fp) < 1) 
+                goto nomore;
+            tokptr = strtok(NULL, " \n");
+        }
+        x->x_template = (t_template *)t_resizebytes(x->x_template,
+                                                    ntemplate * sizeof(t_template),
+                                                    (ntemplate + 1) * sizeof(t_template));
+        for (i = x->x_nfilters, fp = vec,
+             fp2 = x->x_template[ntemplate].t_amp; i--;)
+            *fp2++ = *fp++;
+        ntemplate++;
+    }
+nomore:
+    if (remaining = (ntemplate % x->x_ninsig))
+    {
+        post("bonk_read: %d templates not a multiple of %d; dropping extras");
+        x->x_template = (t_template *)t_resizebytes(x->x_template,
+                                                    ntemplate * sizeof(t_template),
+                                                    (ntemplate - remaining) * sizeof(t_template));
+        ntemplate = ntemplate - remaining;
+    }
+    
+    sysmem_freehandle(texthandle);
+    post("bonk: read %d templates\n", ntemplate);
+    x->x_ntemplate = ntemplate;
+}
+#endif
 
+#ifdef PD
 static void bonk_write(t_bonk *x, t_symbol *s)
 {
-    FILE *fd = fopen(s->s_name, "w");
+    FILE *fd;
+    char buf[MAXPDSTRING]; /* fbar */
     int i, ntemplate = x->x_ntemplate;
     t_template *tp = x->x_template;
     float *fp;
-    if (!fd)
+    
+    /* fbar: canvas-code as in g_array.c */
+    canvas_makefilename(x->x_canvas, s->s_name,
+        buf, MAXPDSTRING);
+    sys_bashfilename(buf, buf);
+
+    if (!(fd = fopen(buf, "w")))
     {
         post("%s: couldn't create", s->s_name);
         return;
@@ -1019,6 +1124,63 @@ static void bonk_write(t_bonk *x, t_symbol *s)
     post("bonk: wrote %d templates\n", x->x_ntemplate);
     fclose(fd);
 }
+#endif
+
+#ifdef MSP
+static void bonk_write(t_bonk *x, t_symbol *s)
+{
+    defer(x, (method)bonk_dowrite, s, 0, NULL);
+}
+
+static void bonk_dowrite(t_bonk *x, t_symbol *s)
+{
+    long filetype = 'TEXT', outtype;
+    char filename[MAX_FILENAME_CHARS];
+    short path;
+    
+    if (s == gensym("")) {
+        sprintf(filename, "bonk_template.txt");
+        saveas_promptset("Save template as...");   
+        if (saveasdialog_extended(filename, &path, &outtype, &filetype, 0))
+            return;
+    } else {
+        strcpy(filename, s->s_name);
+        path = path_getdefault();
+    }
+    bonk_writefile(x, filename, path);
+}
+
+void bonk_writefile(t_bonk *x, char *filename, short path)
+{
+    int i, ntemplate = x->x_ntemplate;
+    t_template *tp = x->x_template;
+    float *fp;
+    long err;
+    long buflen;
+    
+    t_filehandle fh;
+    
+    char buf[20];
+    
+    err = path_createsysfile(filename, path, 'TEXT', &fh); 
+    
+    if (err)
+        return;
+    
+    for (; ntemplate--; tp++)
+    {
+        for (i = x->x_nfilters, fp = tp->t_amp; i--; fp++) {
+            snprintf(buf, 20, "%6.2f ", *fp);
+            buflen = strlen(buf);
+            sysfile_write(fh, &buflen, buf);
+        }
+        buflen = 1;
+        sysfile_write(fh, &buflen, "\n");
+    }
+        
+    sysfile_close(fh);
+}
+#endif
 
 static void bonk_free(t_bonk *x)
 {
@@ -1048,6 +1210,7 @@ static void *bonk_new(t_symbol *s, int argc, t_atom *argv)
         firstbin = DEFFIRSTBIN, minbandwidth = DEFMINBANDWIDTH;
     t_insig *g;
 
+    x->x_canvas = canvas_getcurrent(); /* fbar: bind current canvas to x */
     if (argc > 0 && argv[0].a_type == A_FLOAT)
     {
             /* old style args for compatibility */
@@ -1176,7 +1339,7 @@ void bonk_tilde_setup(void)
         gensym("read"), A_SYMBOL, 0);
     class_addmethod(bonk_class, (t_method)bonk_write,
         gensym("write"), A_SYMBOL, 0);
-    post("bonk version 1.3");
+    post("bonk version 1.5");
 }
 #endif
 
@@ -1265,7 +1428,7 @@ int main()
         class_register(CLASS_BOX, c);
         bonk_class = c;
         
-        post("bonk~ v1.3");
+        post("bonk~ v1.5");
         return (0);
 }
 
@@ -1446,7 +1609,7 @@ void bonk_learn_set(t_bonk *x, void *attr, long ac, t_atom *av)
                 x->x_ntemplate * sizeof(x->x_template[0]), 0);
             x->x_ntemplate = 0;
         }
-        x->x_learn = (n != 0);
+        x->x_learn = n;
         x->x_learncount = 0;
     }
 }
diff --git a/extra/bonk~/makefile b/extra/bonk~/makefile
index af6399cca..7d56ed4d6 100644
--- a/extra/bonk~/makefile
+++ b/extra/bonk~/makefile
@@ -1,4 +1,4 @@
 NAME=bonk~
 CSYM=bonk_tilde
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/choice/choice.c b/extra/choice/choice.c
index b7bf23ab1..a50c66ac2 100644
--- a/extra/choice/choice.c
+++ b/extra/choice/choice.c
@@ -18,7 +18,7 @@ static t_class *choice_class;
 typedef struct _elem
 {
     float e_age;
-    float e_weight[DIMENSION];
+    t_float e_weight[DIMENSION];
 } t_elem;
 
 typedef struct _choice
diff --git a/extra/choice/makefile b/extra/choice/makefile
index 7fc711593..ee63e8fdf 100644
--- a/extra/choice/makefile
+++ b/extra/choice/makefile
@@ -1,4 +1,4 @@
 NAME=choice
 CSYM=choice
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/expr~/makefile b/extra/expr~/makefile
index 4c6481407..5dee147a7 100644
--- a/extra/expr~/makefile
+++ b/extra/expr~/makefile
@@ -6,7 +6,7 @@ install: install_linux
 
 clean: clean_linux
 
-PDEXTERN=/usr/local/lib/pd/externs
+PDEXTERN=/usr/local/lib/pd/extra
 
 # ----------------------- NT -----------------------
 
@@ -89,7 +89,6 @@ LINUXINCLUDE =  -I../../src
 
 expr.pd_linux: $(LINUXOBJ)
 	$(CC)  -shared -o expr.pd_linux $(LINUXOBJ) -lc -lm
-	strip --strip-unneeded expr.pd_linux
 
 expr~.pd_linux: expr.pd_linux
 	-ln -s expr.pd_linux expr~.pd_linux
@@ -110,12 +109,11 @@ install_linux:
 	install expr.pd_linux $(PDEXTERN)
 	rm -f $(PDEXTERN)/expr~.pd_linux
 	rm -f $(PDEXTERN)/fexpr~.pd_linux
-	cd $(PDEXTERN); \
-	-ln -s expr.pd_linux expr~.pd_linux
-	-ln -s expr.pd_linux fexpr~.pd_linux
+	cd $(PDEXTERN); ln -s expr.pd_linux expr~.pd_linux
+	cd $(PDEXTERN); ln -s expr.pd_linux fexpr~.pd_linux
 
 
-linux_clean:
+clean_linux:
 	rm -f *.pd_linux_o *.o
 
 # ----------------------- MAC OSX -----------------------
diff --git a/extra/expr~/vexp_if.c b/extra/expr~/vexp_if.c
index 648aba732..aaaf4ef3c 100644
--- a/extra/expr~/vexp_if.c
+++ b/extra/expr~/vexp_if.c
@@ -381,7 +381,7 @@ SDY the following coredumps why?
                                 post("expr: internal error expr_new");
                 default:
                         pd_error(x, "expr: bad type (%lx) inlet = %d\n",
-                                            eptr->ex_type, i + 1, 0, 0, 0);
+                                            eptr->ex_type, i + 1);
                         break;
                 }
         }
@@ -955,7 +955,7 @@ if (!sym || !(garray = (t_garray *)pd_findbyclass(sym, garray_class)) || \
                 !garray_getfloatwords(garray, &size, &vec))  {          \
         optr->ex_type = ET_FLT;                                         \
         optr->ex_int = 0;                                               \
-        error("no such table '%s'", sym->s_name);                       \
+        error("no such table '%s'", sym?(sym->s_name):"(null)");                       \
         return;                                                         \
 }
 
diff --git a/extra/fiddle~/makefile b/extra/fiddle~/makefile
index 247c905e6..0820a8382 100644
--- a/extra/fiddle~/makefile
+++ b/extra/fiddle~/makefile
@@ -1,4 +1,4 @@
 NAME=fiddle~
 CSYM=fiddle_tilde
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/loop~/loop~-help.pd b/extra/loop~/loop~-help.pd
index a445b805e..ff3d3a634 100644
--- a/extra/loop~/loop~-help.pd
+++ b/extra/loop~/loop~-help.pd
@@ -1,4 +1,4 @@
-#N canvas 33 0 647 662 12;
+#N canvas 234 90 647 662 12;
 #X floatatom 41 204 0 0 0 0 - - -;
 #X obj 254 382 print~;
 #X msg 254 347 bang;
@@ -7,7 +7,7 @@
 #X msg 55 252 bang;
 #X obj 183 382 print~;
 #X msg 183 347 bang;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
 #X array array2 150000 float 0;
 #X coords 0 1 150000 -1 200 150 1;
 #X restore 393 464 graph;
@@ -22,7 +22,6 @@
 #X floatatom 96 303 0 0 0 0 - - -;
 #X obj 96 326 *~ 1000;
 #X msg 43 568 read ../doc/sound/bell.aiff array2;
-#X msg 43 591 read ../doc/sound/vocal.aiff array2;
 #X msg 47 229 set 0.5;
 #X text 95 196 left signal input is transposition (1 is normal \, 2
 is up an octave \, etc);
@@ -46,6 +45,7 @@ that changing window size doesn't change the transposition.;
 to zero--you should mute the output before doing so. This may be desirable
 if you've set a large window size but then want to decrease it without
 waiting for the next phase crossing.;
+#X msg 43 591 read ../doc/sound/voice.wav array2;
 #X connect 0 0 3 0;
 #X connect 2 0 1 0;
 #X connect 3 0 6 0;
@@ -56,7 +56,7 @@ waiting for the next phase crossing.;
 #X connect 4 0 3 1;
 #X connect 5 0 3 0;
 #X connect 7 0 6 0;
-#X connect 11 0 28 0;
+#X connect 11 0 27 0;
 #X connect 12 0 16 0;
 #X connect 14 0 13 0;
 #X connect 14 0 13 1;
@@ -65,10 +65,10 @@ waiting for the next phase crossing.;
 #X connect 17 0 18 0;
 #X connect 18 0 15 0;
 #X connect 19 0 10 0;
-#X connect 20 0 10 0;
-#X connect 21 0 3 0;
-#X connect 28 0 14 0;
-#X connect 29 0 31 0;
-#X connect 30 0 28 1;
-#X connect 31 0 32 0;
-#X connect 32 0 30 0;
+#X connect 20 0 3 0;
+#X connect 27 0 14 0;
+#X connect 28 0 30 0;
+#X connect 29 0 27 1;
+#X connect 30 0 31 0;
+#X connect 31 0 29 0;
+#X connect 36 0 10 0;
diff --git a/extra/loop~/loop~.c b/extra/loop~/loop~.c
index 2f4400307..2fc3193e3 100644
--- a/extra/loop~/loop~.c
+++ b/extra/loop~/loop~.c
@@ -13,20 +13,24 @@ This file is downloadable from http://www.crca.ucsd.edu/~msp .
 
 #ifdef PD
 #include "m_pd.h"
+#else
+#define t_sample float
 #endif
 
+
+
 typedef struct _loopctl
 {
     double l_phase;
-    float l_invwindow;
-    float l_window;
+    t_sample l_invwindow;
+    t_sample l_window;
     int l_resync;
 } t_loopctl;
 
-static void loopctl_run(t_loopctl *x, float *transposein,
-        float *windowin, float *rawout, float *windowout, int n)
+static void loopctl_run(t_loopctl *x, t_sample *transposein,
+        t_sample *windowin, t_sample *rawout, t_sample *windowout, int n)
 {
-    float window, invwindow;
+    t_sample window, invwindow;
     double phase = x->l_phase;
     if (x->l_resync)
     {
@@ -55,7 +59,7 @@ static void loopctl_run(t_loopctl *x, float *transposein,
     {
         double phaseinc = invwindow * *transposein++;
         double newphase;
-        float nwind = *windowin++;
+        t_sample nwind = *windowin++;
         if (phaseinc >= 1 || phaseinc < 0)
             phaseinc = 0;
         newphase = phase + phaseinc;
@@ -77,7 +81,7 @@ static void loopctl_run(t_loopctl *x, float *transposein,
             newphase -= 1.;
         }
         phase = newphase;
-        *rawout++ = (float)phase;
+        *rawout++ = (t_sample)phase;
         *windowout++ = window;
     }
     x->l_invwindow = invwindow;
@@ -124,10 +128,10 @@ static void *loop_new(void)
 static t_int *loop_perform(t_int *w)
 {
     t_loopctl *ctl = (t_loopctl *)(w[1]);
-    t_float *in1 = (t_float *)(w[2]);
-    t_float *in2 = (t_float *)(w[3]);
-    t_float *out1 = (t_float *)(w[4]);
-    t_float *out2 = (t_float *)(w[5]);
+    t_sample *in1 = (t_sample *)(w[2]);
+    t_sample *in2 = (t_sample *)(w[3]);
+    t_sample *out1 = (t_sample *)(w[4]);
+    t_sample *out2 = (t_sample *)(w[5]);
     int n = (int)(w[6]);
     loopctl_run(ctl, in1, in2, out1, out2, n);
     return (w+7);
diff --git a/extra/loop~/makefile b/extra/loop~/makefile
index fd21f2b4c..dc367b20a 100644
--- a/extra/loop~/makefile
+++ b/extra/loop~/makefile
@@ -1,4 +1,4 @@
 NAME=loop~
 CSYM=loop_tilde
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/lrshift~/lrshift~.c b/extra/lrshift~/lrshift~.c
index 166facc16..b3c90ff6b 100644
--- a/extra/lrshift~/lrshift~.c
+++ b/extra/lrshift~/lrshift~.c
@@ -13,8 +13,8 @@ typedef struct _lrshift_tilde
 
 static t_int *leftshift_perform(t_int *w)
 {
-    t_float *in = (t_float *)(w[1]);
-    t_float *out= (t_float *)(w[2]);
+    t_sample *in = (t_sample *)(w[1]);
+    t_sample *out= (t_sample *)(w[2]);
     int n = (int)(w[3]);
     int shift = (int)(w[4]);
     in += shift;
@@ -28,8 +28,8 @@ static t_int *leftshift_perform(t_int *w)
 
 static t_int *rightshift_perform(t_int *w)
 {
-    t_float *in = (t_float *)(w[1]);
-    t_float *out= (t_float *)(w[2]);
+    t_sample *in = (t_sample *)(w[1]);
+    t_sample *out= (t_sample *)(w[2]);
     int n = (int)(w[3]);
     int shift = (int)(w[4]);
     n -= shift;
diff --git a/extra/lrshift~/makefile b/extra/lrshift~/makefile
index d6a24cfe3..cbd9e8a08 100644
--- a/extra/lrshift~/makefile
+++ b/extra/lrshift~/makefile
@@ -1,4 +1,4 @@
 NAME=lrshift~
 CSYM=lrshift_tilde
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/pd~/makefile b/extra/pd~/makefile
index d069c73dc..5fc5d26b3 100644
--- a/extra/pd~/makefile
+++ b/extra/pd~/makefile
@@ -1,7 +1,7 @@
 NAME=pd~
 CSYM=pd_tilde
 
-include ../makefile
+include ../makefile.subdir
 
 pd_linux: pdsched.pd_linux
 
@@ -11,5 +11,4 @@ d_ppc: pdsched.d_ppc
 pdsched.pd_linux: pdsched.c
 	$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
 	$(CC) -shared -o $*.pd_linux $*.o -lc -lm
-	strip --strip-unneeded $*.pd_linux
 	rm -f $*.o
diff --git a/extra/pd~/pdsched.c b/extra/pd~/pdsched.c
index 7efe49a95..6c6060c14 100644
--- a/extra/pd~/pdsched.c
+++ b/extra/pd~/pdsched.c
@@ -17,15 +17,33 @@ outputs audio and messages. */
 #define BUFSIZE 65536
 static char inbuf[BUFSIZE];
 
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+void glob_watchdog(t_pd *dummy);
+
+static void pollwatchdog( void)
+{
+    static int sched_diddsp, sched_nextpingtime;
+    sched_diddsp++;
+    if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
+    {
+        glob_watchdog(0);
+            /* ping every 2 seconds */
+        sched_nextpingtime = sched_diddsp +
+            2 * (int)(sys_dacsr /(double)sys_schedblocksize);
+    }
+}
+#endif
+
 int pd_extern_sched(char *flags)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int i, j, rate, advance, callback, chin, chout, fill = 0, c;
+    int i, j, rate, advance, callback, chin, chout, fill = 0, c, blocksize;
     t_binbuf *b = binbuf_new();
 
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+            &blocksize);
 
     chin = (naudioindev < 1 ? 0 : chindev[0]);
     chout = (naudiooutdev < 1 ? 0 : choutdev[0]);
@@ -57,6 +75,9 @@ int pd_extern_sched(char *flags)
                         *fp++ = 0;
                 sched_tick(sys_time+sys_time_per_dsp_tick);
                 sys_pollgui();
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
+                pollwatchdog();
+#endif
                 printf(";\n");
                 for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++)
                 {
diff --git a/extra/pd~/pd~.c b/extra/pd~/pd~.c
index 165065f8a..8a1f5c398 100644
--- a/extra/pd~/pd~.c
+++ b/extra/pd~/pd~.c
@@ -14,8 +14,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <fcntl.h>
 
-#ifdef NT
+#ifdef _MSC_VER
 #pragma warning (disable: 4305 4244)
 #endif
 
@@ -47,7 +48,7 @@ char *class_gethelpdir(t_class *c);
 
 #endif
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__)
 #ifdef __x86_64__
 static char pd_tilde_dllextent[] = ".l_ia64",
     pd_tilde_dllextent2[] = ".pd_linux";
@@ -60,6 +61,9 @@ static char pd_tilde_dllextent[] = ".l_i386",
 static char pd_tilde_dllextent[] = ".d_fat",
     pd_tilde_dllextent2[] = ".pd_darwin";
 #endif
+#if defined(_WIN32) || defined(__CYGWIN__)
+static char pd_tilde_dllextent[] = ".m_i386", pd_tilde_dllextent2[] = ".dll";
+#endif
 
 /* ------------------------ pd_tilde~ ----------------------------- */
 
@@ -249,6 +253,8 @@ static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir,
         /* OK, we're parent */
     close(pipe1[0]);
     close(pipe2[1]);
+    fcntl(pipe1[1],  F_SETFD, FD_CLOEXEC);
+    fcntl(pipe2[0],  F_SETFD, FD_CLOEXEC);
     x->x_outfd = fdopen(pipe1[1], "w");
     x->x_infd = fdopen(pipe2[0], "r");
     x->x_childpid = pid;
@@ -512,7 +518,7 @@ static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv)
     int ninsig = 2, noutsig = 2, j, fifo = 5;
     float sr = sys_getsr();
     t_sample **g;
-    t_symbol *pddir = sys_guidir,
+    t_symbol *pddir = sys_libdir,
         *scheddir = gensym(class_gethelpdir(pd_tilde_class));
     /* fprintf(stderr, "pd %s, sched %s\n", pddir->s_name, scheddir->s_name); */
     while (argc > 0)
diff --git a/extra/pique/makefile b/extra/pique/makefile
index 562ce23b9..ebcbd93a8 100644
--- a/extra/pique/makefile
+++ b/extra/pique/makefile
@@ -1,4 +1,4 @@
 NAME=pique
 CSYM=pique
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/pique/pique.c b/extra/pique/pique.c
index a53ad765c..19cee2ae2 100644
--- a/extra/pique/pique.c
+++ b/extra/pique/pique.c
@@ -51,7 +51,7 @@ static float hanning(float pidetune, float sinpidetune)
         (sinpidetune/(pidetune+pi) + sinpidetune/(pidetune-pi)));
 }
 
-static float peakerror(float *fpreal, float *fpimag, float pidetune,
+static float peakerror(t_word *fpreal, t_word *fpimag, float pidetune,
     float norm, float peakreal, float peakimag)
 {
     float sinpidetune = sin(pidetune);
@@ -61,8 +61,10 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune,
         peakreal * cospidetune + peakimag * sinpidetune);
     float imagshould =  windowshould * (
         peakimag * cospidetune - peakreal * sinpidetune);
-    float realgot = norm * (fpreal[0] - 0.5 * (fpreal[1] + fpreal[-1]));
-    float imaggot = norm * (fpimag[0] - 0.5 * (fpimag[1] + fpimag[-1]));
+    float realgot = norm * (fpreal[0].w_float -
+        0.5 * (fpreal[1].w_float + fpreal[-1].w_float));
+    float imaggot = norm * (fpimag[0].w_float -
+        0.5 * (fpimag[1].w_float + fpimag[-1].w_float));
     float realdev = realshould - realgot, imagdev = imagshould - imaggot;
     
     /* post("real %f->%f; imag %f->%f", realshould, realgot,
@@ -70,7 +72,7 @@ static float peakerror(float *fpreal, float *fpimag, float pidetune,
     return (realdev * realdev + imagdev * imagdev);
 }
 
-static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
+static void pique_doit(int npts, t_word *fpreal, t_word *fpimag,
     int npeak, int *nfound, t_float *fpfreq, t_float *fpamp,
         t_float *fpampre, t_float *fpampim, float errthresh)
 {
@@ -78,13 +80,15 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
     float oneovern = 1.0/ (float)npts;
     float fperbin = srate * oneovern;
     float pow1, pow2 = 0, pow3 = 0, pow4 = 0, pow5 = 0;
-    float re1, re2 = 0, re3 = *fpreal;
+    float re1, re2 = 0, re3 = fpreal->w_float;
     float im1, im2 = 0, im3 = 0, powthresh, relativeerror;
     int count, peakcount = 0, n2 = (npts >> 1);
     float *fp1, *fp2;
-    for (count = n2, fp1 = fpreal, fp2 = fpimag, powthresh = 0;
-        count--; fp1++, fp2++)
-            powthresh += (*fp1) * (*fp1) + (*fp2) * (*fp2) ; 
+    t_word *wp1, *wp2;
+    for (count = n2, wp1 = fpreal, wp2 = fpimag, powthresh = 0;
+        count--; wp1++, wp2++)
+            powthresh += (wp1->w_float) * (wp1->w_float) +
+                (wp2->w_float) * (wp2->w_float) ; 
     powthresh *= 0.00001;
     for (count = 1; count < n2; count++)
     {
@@ -98,10 +102,10 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
         fpimag++;
         re1 = re2;
         re2 = re3;
-        re3 = *fpreal;
+        re3 = fpreal->w_float;
         im1 = im2;
         im2 = im3;
-        im3 = *fpimag;
+        im3 = fpimag->w_float;
         if (count < 2) continue;
         pow1 = pow2;
         pow2 = pow3;
@@ -118,12 +122,12 @@ static void pique_doit(int npts, t_float *fpreal, t_float *fpimag,
             || pow3 < powthresh)
                 continue;
             /* go back for the raw FFT values around the peak. */
-        rpeak = fpreal[-3];
-        rpeaknext = fpreal[-2];
-        rpeakprev = fpreal[-4];
-        ipeak = fpimag[-3];
-        ipeaknext = fpimag[-2];
-        ipeakprev = fpimag[-4];
+        rpeak = fpreal[-3].w_float;
+        rpeaknext = fpreal[-2].w_float;
+        rpeakprev = fpreal[-4].w_float;
+        ipeak = fpimag[-3].w_float;
+        ipeaknext = fpimag[-2].w_float;
+        ipeakprev = fpimag[-4].w_float;
             /* recalculate Hanning-windowed spectrum by convolution */
         windreal = rpeak - 0.5 * (rpeaknext + rpeakprev);
         windimag = ipeak - 0.5 * (ipeaknext + ipeakprev);
@@ -180,15 +184,15 @@ static void pique_list(t_pique *x, t_symbol *s, int argc, t_atom *argv)
     int npeak = atom_getintarg(3, argc, argv);
     int n;
     t_garray *a;
-    t_float *fpreal, *fpimag;
+    t_word *fpreal, *fpimag;
     if (npts < 8 || npeak < 1) error("pique: bad npoints or npeak");
     if (npeak > x->x_n) npeak = x->x_n;
     if (!(a = (t_garray *)pd_findbyclass(symreal, garray_class)) ||
-        !garray_getfloatarray(a, &n, &fpreal) ||
+        !garray_getfloatwords(a, &n, &fpreal) ||
             n < npts)
                 error("%s: missing or bad array", symreal->s_name);
     else if (!(a = (t_garray *)pd_findbyclass(symimag, garray_class)) ||
-        !garray_getfloatarray(a, &n, &fpimag) ||
+        !garray_getfloatwords(a, &n, &fpimag) ||
             n < npts)
                 error("%s: missing or bad array", symimag->s_name);
     else
diff --git a/extra/sigmund~/makefile b/extra/sigmund~/makefile
index 3dc176b3b..3c2f8f1c0 100644
--- a/extra/sigmund~/makefile
+++ b/extra/sigmund~/makefile
@@ -1,4 +1,4 @@
 NAME=sigmund~
 CSYM=sigmund_tilde
 
-include ../makefile
+include ../makefile.subdir
diff --git a/extra/sigmund~/sigmund~.c b/extra/sigmund~/sigmund~.c
index 92604b7ea..968c5c630 100644
--- a/extra/sigmund~/sigmund~.c
+++ b/extra/sigmund~/sigmund~.c
@@ -13,7 +13,7 @@
 and usable in other contexts.  The one external requirement is a real
 single-precision FFT, invoked as in the Mayer one: */
 
-#ifdef NT
+#ifdef _MSC_VER /* this is only needed with Microsoft's compiler */
 __declspec(dllimport) extern
 #endif
 void mayer_realfft(int npoints, float *buf);
@@ -28,7 +28,7 @@ for example, defines this in the file d_fft_mayer.c or d_fft_fftsg.c. */
 #include <string.h>
 #ifdef _WIN32
 #include <malloc.h>
-#else
+#elif ! defined(_MSC_VER)
 #include <alloca.h>
 #endif
 #include <stdlib.h>
@@ -230,9 +230,12 @@ static void sigmund_remask(int maxbin, int bestindex, float powmask,
     } 
 }
 
+#define PEAKMASKFACTOR 1.
+#define PEAKTHRESHFACTOR 0.6
+
 static void sigmund_getrawpeaks(int npts, float *insamps,
     int npeak, t_peak *peakv, int *nfound, float *power, float srate, int loud,
-    float param1, float param2, float param3, float hifreq)
+    float hifreq)
 {
     float oneovern = 1.0/ (float)npts;
     float fperbin = 0.5 * srate * oneovern, totalpower = 0;
@@ -242,7 +245,6 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
     float *rawreal, *rawimag, *maskbuf, *powbuf;
     float *bigbuf = alloca(sizeof (float ) * (2*NEGBINS + 6*npts));
     int maxbin = hifreq/fperbin;
-    int tweak = (param3 == 0);
     if (maxbin > npts - NEGBINS)
         maxbin = npts - NEGBINS;
     /* if (loud) post("tweak %d", tweak); */
@@ -294,7 +296,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
             pow1 = powbuf[bin];
             if (pow1 > maxpower && pow1 > maskbuf[bin])
             {
-                float thresh = param2 * (powbuf[bin-2]+powbuf[bin+2]);
+                float thresh = PEAKTHRESHFACTOR * (powbuf[bin-2]+powbuf[bin+2]);
                 if (pow1 > thresh)
                     maxpower = pow1, bestindex = bin;
             }
@@ -304,7 +306,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
             break;
         fp1 = rawreal+bestindex;
         fp2 = rawimag+bestindex;
-        powmask = maxpower * exp(-param1 * log(10.) / 10.);
+        powmask = maxpower * PEAKMASKFACTOR;
         /* if (loud > 2)
             post("maxpower %f, powmask %f, param1 %f",
                 maxpower, powmask, param1); */
@@ -344,11 +346,8 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
         peakv[peakcount].p_ampreal = oneovern * ampoutreal;
         peakv[peakcount].p_ampimag = oneovern * ampoutimag;
     }
-    if (tweak)
-    {
-        sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
-        sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
-    }
+    sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
+    sigmund_tweak(npts, rawreal, rawimag, peakcount, peakv, fperbin, loud);
     for (i = 0; i < peakcount; i++)
     {
         peakv[i].p_pit = sigmund_ftom(peakv[i].p_freq);
@@ -360,13 +359,12 @@ static void sigmund_getrawpeaks(int npts, float *insamps,
 /*************** Routines for finding fundamental pitch *************/
 
 #define PITCHNPEAK 12
-#define PITCHUNCERTAINTY 0.3
 #define HALFTONEINC 0.059
 #define SUBHARMONICS 16
 #define DBPERHALFTONE 0.0
 
 static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
-    float npts, float srate, int loud)
+    float npts, float srate, float nharmonics, float amppower, int loud)
 {
     float fperbin = 0.5 * srate / npts;
     int npit = 48 * sigmund_ilog2(npts), i, j, k, nsalient;
@@ -407,7 +405,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
         t_peak *thispeak = bigpeaks[i];
         float weightindex = (48./LOG2) *
             log(thispeak->p_freq/(2.*fperbin));
-        float loudness = sqrt(thispeak->p_amp);
+        float loudness = pow(thispeak->p_amp, amppower);
         /* post("index %f, uncertainty %f", weightindex, pitchuncertainty); */
         for (j = 0; j < SUBHARMONICS; j++)
         {
@@ -422,7 +420,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp,
             if (loindex < 0)
                 loindex = 0;
             for (k = loindex; k <= hiindex; k++)
-                weights[k] += loudness * 6. / (6. + j);
+                weights[k] += loudness * nharmonics / (nharmonics + j);
         }
         sumweight += loudness;
     }
@@ -860,8 +858,8 @@ typedef struct _sigmund
 static void sigmund_preinit(t_sigmund *x)
 {
     x->x_npts = NPOINTS_DEF;
-    x->x_param1 = 0;
-    x->x_param2 = 0.6;
+    x->x_param1 = 6;
+    x->x_param2 = 0.5;
     x->x_param3 = 0;
     x->x_hop = HOP_DEF;
     x->x_mode = MODE_STREAM;
@@ -977,10 +975,10 @@ static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints,
     int nfound, i, cnt;
     float freq = 0, power, note = 0;
     sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv,
-        &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3,
-        x->x_maxfreq);
+        &nfound, &power, srate, loud, x->x_maxfreq);
     if (x->x_dopitch)
-        sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud);
+        sigmund_getpitch(nfound, peakv, &freq, npts, srate, 
+        x->x_param1, x->x_param2, loud);
     if (x->x_donote)
         notefinder_doit(&x->x_notefinder, freq, power, &note, x->x_vibrato, 
             1 + x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop,
@@ -1112,7 +1110,7 @@ static void sigmund_tick(t_sigmund *x)
 static t_int *sigmund_perform(t_int *w)
 {
     t_sigmund *x = (t_sigmund *)(w[1]);
-    float *in = (float *)(w[2]);
+    t_sample *in = (float *)(w[2]);
     int n = (int)(w[3]);
 
     if (x->x_hop % n)
diff --git a/extra/stdout/makefile b/extra/stdout/makefile
index 67801999b..6041eeb71 100644
--- a/extra/stdout/makefile
+++ b/extra/stdout/makefile
@@ -1,4 +1,4 @@
 NAME=stdout
 CSYM=stdout
 
-include ../makefile
+include ../makefile.subdir
diff --git a/src/s_audio.c b/src/s_audio.c
index cfd2c64ea..bff3c3abc 100644
--- a/src/s_audio.c
+++ b/src/s_audio.c
@@ -6,23 +6,21 @@
     audio settings from argparse routine and from dialog window. 
 */
 
-#include "config.h"
-
 #include "m_pd.h"
 #include "s_stuff.h"
 #include <stdio.h>
-#ifdef HAVE_UNISTD_H
+#ifdef _WIN32
+#include <time.h>
+#else
 #include <unistd.h>
-/* XXX Hack!!! These should be checked for independently of unistd.h ... */
 #include <sys/time.h>
 #include <sys/resource.h>
-#endif
+#endif /* _WIN32 */
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 
 #define SYS_DEFAULTCH 2
-#define SYS_MAXCH 100
 typedef long t_pa_sample;
 #define SYS_SAMPLEWIDTH sizeof(t_pa_sample)
 #define SYS_BYTESPERCHAN (DEFDACBLKSIZE * SYS_SAMPLEWIDTH) 
@@ -40,7 +38,6 @@ static void audio_getdevs(char *indevlist, int *nindevs,
 int sys_inchannels;
 int sys_outchannels;
 int sys_advance_samples;        /* scheduler advance in samples */
-int sys_blocksize = 0;          /* audio I/O block size in sample frames */
 int sys_audioapi = API_DEFAULT;
 int sys_audioapiopened = -1;    /* save last API opened for later closing */
 static int sys_meters;          /* true if we're metering */
@@ -67,19 +64,15 @@ static int audio_naudiooutdev = -1;
 static int audio_audiooutdev[MAXAUDIOOUTDEV];
 static int audio_audiochoutdev[MAXAUDIOOUTDEV];
 static int audio_rate;
-static int audio_advance;
+static int audio_advance = -1;
 static int audio_callback;
+static int audio_blocksize;
 
 static int audio_callback_is_open;  /* reflects true actual state */
 static int audio_nextinchans, audio_nextoutchans;
 void sched_audio_callbackfn(void);
 void sched_reopenmeplease(void);
 
-#ifdef USEAPI_JACK
-	/* needed to fix srate when using jack, inclded in s_audio_jack.c */
-extern int jack_get_srate(void);
-#endif /* JACK */
-
 static int audio_isopen(void)
 {
     return (audio_state &&
@@ -90,7 +83,7 @@ static int audio_isopen(void)
 void sys_get_audio_params(
     int *pnaudioindev, int *paudioindev, int *chindev,
     int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
-    int *prate, int *padvance, int *pcallback)
+    int *prate, int *padvance, int *pcallback, int *pblocksize)
 {
     int i;
     *pnaudioindev = audio_naudioindev;
@@ -100,23 +93,17 @@ void sys_get_audio_params(
     *pnaudiooutdev = audio_naudiooutdev;
     for (i = 0; i < MAXAUDIOOUTDEV; i++)
         paudiooutdev[i] = audio_audiooutdev[i],
-            choutdev[i] = audio_audiochoutdev[i];
-#ifdef USEAPI_JACK
-	if (sys_audioapiopened == API_JACK) {
-		if (jack_get_srate()) {
-			audio_rate = jack_get_srate();
-		}
-	}
-#endif /* JACK */
+            choutdev[i] = audio_audiochoutdev[i]; 
     *prate = audio_rate;
     *padvance = audio_advance;
     *pcallback = audio_callback;
+    *pblocksize = audio_blocksize;
 }
 
 void sys_save_audio_params(
     int naudioindev, int *audioindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int *choutdev,
-    int rate, int advance, int callback)
+    int rate, int advance, int callback, int blocksize)
 {
     int i;
     audio_naudioindev = naudioindev;
@@ -130,6 +117,7 @@ void sys_save_audio_params(
     audio_rate = rate;
     audio_advance = advance;
     audio_callback = callback;
+    audio_blocksize = blocksize;
 }
 
     /* init routines for any API which needs to set stuff up before
@@ -171,8 +159,8 @@ void sys_setchsr(int chin, int chout, int sr)
     sys_outchannels = chout;
     sys_dacsr = sr;
     sys_advance_samples = (sys_schedadvance * sys_dacsr) / (1000000.);
-    if (sys_advance_samples < 3 * DEFDACBLKSIZE)
-        sys_advance_samples = 3 * DEFDACBLKSIZE;
+    if (sys_advance_samples < DEFDACBLKSIZE)
+        sys_advance_samples = DEFDACBLKSIZE;
 
     sys_soundin = (t_sample *)getbytes(inbytes);
     memset(sys_soundin, 0, inbytes);
@@ -195,7 +183,7 @@ void sys_setchsr(int chin, int chout, int sr)
 
 void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
-    int *choutdev, int rate, int advance, int callback)
+    int *choutdev, int rate, int advance, int callback, int blocksize)
 {
     int i, *ip;
     int defaultchannels = SYS_DEFAULTCH;
@@ -210,8 +198,10 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
 
     if (rate < 1)
         rate = DEFAULTSRATE;
-    if (advance <= 0)
+    if (advance < 0)
         advance = DEFAULTADVANCE;
+    if (blocksize != (1 << ilog2(blocksize)) || blocksize < DEFDACBLKSIZE)
+        blocksize = DEFDACBLKSIZE;
      audio_init();
         /* Since the channel vector might be longer than the
         audio device vector, or vice versa, we fill the shorter one
@@ -339,7 +329,8 @@ void sys_set_audio_settings(int naudioindev, int *audioindev, int nchindev,
     audio_nextinchans = inchans;
     audio_nextoutchans = outchans;
     sys_save_audio_params(nrealindev, realindev, realinchans,
-        nrealoutdev, realoutdev, realoutchans, rate, advance, callback);
+        nrealoutdev, realoutdev, realoutchans, rate, advance, callback,
+            blocksize);
 }
 
 void sys_close_audio(void)
@@ -374,6 +365,21 @@ void sys_close_audio(void)
     if (sys_audioapiopened == API_MMIO)
         mmio_close_audio();
     else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    if (sys_audioapiopened == API_AUDIOUNIT)
+        audiounit_close_audio();
+    else
+#endif
+#ifdef USEAPI_ESD
+    if (sys_audioapiopened == API_ESD)
+        esd_close_audio();
+    else
+#endif
+#ifdef USEAPI_DUMMY
+    if (sys_audioapiopened == API_DUMMY)
+        dummy_close_audio();
+    else
 #endif
         post("sys_close_audio: unknown API %d", sys_audioapiopened);
     sys_inchannels = sys_outchannels = 0;
@@ -381,6 +387,8 @@ void sys_close_audio(void)
     sched_set_using_audio(SCHED_AUDIO_NONE);
     audio_state = 0;
     audio_callback_is_open = 0;
+
+    sys_vgui("set pd_whichapi 0\n");
 }
 
     /* open audio using whatever parameters were last used */
@@ -388,9 +396,10 @@ void sys_reopen_audio( void)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int rate, advance, callback, outcome = 0;
+    int rate, advance, callback, blocksize, outcome = 0;
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+            &blocksize);
     sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
     if (!naudioindev && !naudiooutdev)
     {
@@ -400,7 +409,9 @@ void sys_reopen_audio( void)
 #ifdef USEAPI_PORTAUDIO
     if (sys_audioapi == API_PORTAUDIO)
     {
-        int blksize = (sys_blocksize ? sys_blocksize : 64);
+        int blksize = (audio_blocksize ? audio_blocksize : 64);
+        if (sys_verbose)
+            fprintf(stderr, "blksize %d, advance %d\n", blksize, sys_advance_samples/blksize);
         outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
         (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
             sys_soundout, blksize, sys_advance_samples/blksize, 
@@ -413,14 +424,16 @@ void sys_reopen_audio( void)
 #ifdef USEAPI_JACK
     if (sys_audioapi == API_JACK) 
         outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
-            (naudioindev > 0 ? choutdev[0] : 0), rate);
+            (naudioindev > 0 ? choutdev[0] : 0), rate,
+                (callback ? sched_audio_callbackfn : 0));
 
     else
 #endif    
 #ifdef USEAPI_OSS
     if (sys_audioapi == API_OSS)
         outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
-            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+                audio_blocksize);
     else
 #endif
 #ifdef USEAPI_ALSA
@@ -428,13 +441,32 @@ void sys_reopen_audio( void)
         be open for both input and output. */
     if (sys_audioapi == API_ALSA)
         outcome = alsa_open_audio(naudioindev, audioindev, naudioindev,
-            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+                audio_blocksize);
     else 
 #endif
 #ifdef USEAPI_MMIO
     if (sys_audioapi == API_MMIO)
         outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
+            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate,
+                audio_blocksize);
+    else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    if (sys_audioapi == API_AUDIOUNIT)
+        outcome = audiounit_open_audio((naudioindev > 0 ? chindev[0] : 0),
+            (naudioindev > 0 ? choutdev[0] : 0), rate);
+    else
+#endif
+#ifdef USEAPI_ESD
+    if (sys_audioapi == API_ALSA)
+        outcome = esd_open_audio(naudioindev, audioindev, naudioindev,
             chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+    else 
+#endif
+#ifdef USEAPI_DUMMY
+    if (sys_audioapi == API_DUMMY)
+        outcome = dummy_open_audio(naudioindev, naudiooutdev, rate);
     else
 #endif
     if (sys_audioapi == API_NONE)
@@ -507,6 +539,21 @@ int sys_send_dacs(void)
     if (sys_audioapi == API_MMIO)
         return (mmio_send_dacs());
     else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    if (sys_audioapi == API_AUDIOUNIT)
+        return (audiounit_send_dacs());
+    else
+#endif
+#ifdef USEAPI_ESD
+    if (sys_audioapi == API_ESD)
+        return (esd_send_dacs());
+    else
+#endif
+#ifdef USEAPI_DUMMY
+    if (sys_audioapi == API_DUMMY)
+        return (dummy_send_dacs());
+    else
 #endif
     post("unknown API");    
     return (0);
@@ -564,6 +611,7 @@ static void audio_getdevs(char *indevlist, int *nindevs,
     {
         jack_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
             maxndev, devdescsize);
+        *cancallback = 1;
     }
     else
 #endif
@@ -590,6 +638,28 @@ static void audio_getdevs(char *indevlist, int *nindevs,
             maxndev, devdescsize);
     }
     else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    if (sys_audioapi == API_AUDIOUNIT)
+    {
+    }
+    else
+#endif
+#ifdef USEAPI_ESD
+    if (sys_audioapi == API_ESD)
+    {
+        esd_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+            maxndev, devdescsize);
+    }
+    else
+#endif
+#ifdef USEAPI_DUMMY
+    if (sys_audioapi == API_DUMMY)
+    {
+        dummy_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
+            maxndev, devdescsize);
+    }
+    else
 #endif
     {
             /* this shouldn't happen once all the above get filled in. */
@@ -650,7 +720,7 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
         audioinchan1, audioinchan2, audioinchan3, audioinchan4,
         audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
         audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4;
-    int rate, advance, callback;
+    int rate, advance, callback, blocksize;
         /* these are all the devices on your system: */
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
     int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i;
@@ -669,13 +739,8 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
             outdevlist + i * DEVDESCSIZE);
 
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
-
-#ifdef USEAPI_JACK
-	if (sys_audioapiopened == API_JACK) {
-		sys_setchsr(audio_nextinchans, audio_nextoutchans, rate);
-	}
-#endif /* JACK */
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+            &blocksize);
 
     /* post("naudioindev %d naudiooutdev %d longform %f",
             naudioindev, naudiooutdev, flongform); */
@@ -702,13 +767,13 @@ void glob_audio_properties(t_pd *dummy, t_floatarg flongform)
 "pdtk_audio_dialog %%s \
 %d %d %d %d %d %d %d %d \
 %d %d %d %d %d %d %d %d \
-%d %d %d %d %d\n",
+%d %d %d %d %d %d\n",
         audioindev1, audioindev2, audioindev3, audioindev4, 
         audioinchan1, audioinchan2, audioinchan3, audioinchan4, 
         audiooutdev1, audiooutdev2, audiooutdev3, audiooutdev4,
         audiooutchan1, audiooutchan2, audiooutchan3, audiooutchan4, 
         rate, advance, canmulti, (cancallback ? callback : -1),
-        (flongform != 0));
+        (flongform != 0), blocksize);
     gfxstub_deleteforkey(0);
     gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf);
 }
@@ -727,6 +792,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
     int newrate = atom_getintarg(16, argc, argv);
     int newadvance = atom_getintarg(17, argc, argv);
     int newcallback = atom_getintarg(18, argc, argv);
+    int newblocksize = atom_getintarg(19, argc, argv);
 
     for (i = 0; i < 4; i++)
     {
@@ -759,14 +825,27 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
         }
     }
     
-    if (newcallback < 0)
-        newcallback = 0;
-    if (!audio_callback_is_open && !newcallback)
-        sys_close_audio();
-    sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan,
+    sys_set_audio_settings_reopen(nindev, newaudioindev, nindev, newaudioinchan,
         noutdev, newaudiooutdev, noutdev, newaudiooutchan,
-        newrate, newadvance, (newcallback >= 0 ? newcallback : 0));
-    if (!audio_callback_is_open && !newcallback)
+        newrate, newadvance, newcallback, newblocksize);
+}
+
+void sys_set_audio_settings_reopen(int naudioindev, int *audioindev, int nchindev,
+    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+    int *choutdev, int rate, int advance, int callback, int newblocksize)
+{
+    if (callback < 0)
+        callback = 0;
+    if (newblocksize != (1<<ilog2(newblocksize)) ||
+        newblocksize < DEFDACBLKSIZE || newblocksize > 2048)
+            newblocksize = DEFDACBLKSIZE;
+    
+    if (!audio_callback_is_open && !callback)
+        sys_close_audio();
+    sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
+        naudiooutdev, audiooutdev, nchoutdev, choutdev,
+        rate, advance, (callback >= 0 ? callback : 0), newblocksize);
+    if (!audio_callback_is_open && !callback)
         sys_reopen_audio();
     else sched_reopenmeplease();
 }
@@ -797,20 +876,35 @@ void sys_listdevs(void )
     if (sys_audioapi == API_MMIO)
         sys_listaudiodevs();
     else
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    if (sys_audioapi == API_AUDIOUNIT)
+        sys_listaudiodevs();
+    else
+#endif
+#ifdef USEAPI_ESD
+    if (sys_audioapi == API_ESD)
+        sys_listaudiodevs();
+    else
+#endif
+#ifdef USEAPI_DUMMY
+    if (sys_audioapi == API_DUMMY)
+        sys_listaudiodevs();
+    else
 #endif
     post("unknown API");    
 
     sys_listmididevs();
 }
 
-void sys_setblocksize(int n)
+void sys_get_audio_devs(char *indevlist, int *nindevs,
+    char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, 
+                        int maxndev, int devdescsize)
 {
-    if (n < 1)
-        n = 1;
-    if (n != (1 << ilog2(n)))
-        post("warning: adjusting blocksize to power of 2: %d", 
-            (n = (1 << ilog2(n))));
-    sys_blocksize = n;
+  audio_getdevs(indevlist, nindevs,
+                outdevlist, noutdevs, 
+                canmulti, cancallback, 
+                maxndev, devdescsize);
 }
 
 void sys_set_audio_api(int which)
@@ -892,6 +986,15 @@ void sys_get_audio_apis(char *buf)
 #endif
 #ifdef USEAPI_JACK
     sprintf(buf + strlen(buf), "{jack %d} ", API_JACK); n++;
+#endif
+#ifdef USEAPI_AUDIOUNIT
+    sprintf(buf + strlen(buf), "{AudioUnit %d} ", API_AUDIOUNIT); n++;
+#endif
+#ifdef USEAPI_ESD
+    sprintf(buf + strlen(buf), "{ESD %d} ", API_ESD); n++;
+#endif
+#ifdef USEAPI_DUMMY
+    sprintf(buf + strlen(buf), "{dummy %d} ", API_DUMMY); n++;
 #endif
     strcat(buf, "}");
         /* then again, if only one API (or none) we don't offer any choice. */
diff --git a/src/s_audio_alsa.c b/src/s_audio_alsa.c
index a5034c8dc..cf7311091 100644
--- a/src/s_audio_alsa.c
+++ b/src/s_audio_alsa.c
@@ -90,9 +90,17 @@ static int alsaio_canmmap(t_alsa_dev *dev)
     return ((err1 < 0) && (err2 >= 0));
 }
 
+static void check_setup_error(int err, int out, const char *why) {
+        char bf[256];
+        snprintf(bf, sizeof bf, "%s (%s)", why, out ? "output" : "input");
+        check_error(err, bf);
+}
+
 static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
     int nfrags, int frag_size)
 {
+#define CHECK_ERROR(why_) check_setup_error(err, out, why_)
+
     int bufsizeforthis, err;
     snd_pcm_hw_params_t* hw_params;
     unsigned int tmp_uint;
@@ -110,14 +118,14 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
 
         /* get the default params */
     err = snd_pcm_hw_params_any(dev->a_handle, hw_params);
-    check_error(err, "snd_pcm_hw_params_any");
+    CHECK_ERROR("snd_pcm_hw_params_any");
 
         /* try to set interleaved access */
     err = snd_pcm_hw_params_set_access(dev->a_handle,
         hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
     if (err < 0)
         return (-1);
-    check_error(err, "snd_pcm_hw_params_set_access");
+    CHECK_ERROR("snd_pcm_hw_params_set_access");
 #if 0       /* enable this to print out which formats are available */
     {
         int i;
@@ -141,7 +149,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
                 "PD-ALSA: 32/24 bit format not available - using 16\n"); */
             err = snd_pcm_hw_params_set_format(dev->a_handle, hw_params,
                 SND_PCM_FORMAT_S16);
-            check_error(err, "snd_pcm_hw_params_set_format");
+            CHECK_ERROR("_pcm_hw_params_set_format");
             dev->a_sampwidth = 2;
         }
         else dev->a_sampwidth = 3;
@@ -154,22 +162,22 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
         /* set the subformat */
     err = snd_pcm_hw_params_set_subformat(dev->a_handle,
         hw_params, SND_PCM_SUBFORMAT_STD);
-    check_error(err, "snd_pcm_hw_params_set_subformat");
+    CHECK_ERROR("snd_pcm_hw_params_set_subformat");
     
         /* set the number of channels */
     tmp_uint = *channels;
     err = snd_pcm_hw_params_set_channels_min(dev->a_handle,
         hw_params, &tmp_uint);
-    check_error(err, "snd_pcm_hw_params_set_channels");
+    CHECK_ERROR("snd_pcm_hw_params_set_channels");
     if (tmp_uint != (unsigned)*channels)
         post("ALSA: set %s channels to %d", (out?"output":"input"), tmp_uint);
     *channels = tmp_uint;
     dev->a_channels = *channels;
 
         /* set the sampling rate */
-    err = snd_pcm_hw_params_set_rate_min(dev->a_handle, hw_params, 
+    err = snd_pcm_hw_params_set_rate_near(dev->a_handle, hw_params, 
         (unsigned int *)rate, 0);
-    check_error(err, "snd_pcm_hw_params_set_rate_min (input)");
+    CHECK_ERROR("snd_pcm_hw_params_set_rate_min");
 #if 0
     err = snd_pcm_hw_params_get_rate(hw_params, &subunitdir);
     post("input sample rate %d", err);
@@ -185,7 +193,7 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
     err = snd_pcm_hw_params_set_period_size_near(dev->a_handle,
         hw_params, &tmp_snd_pcm_uframes, 0);
 #endif
-    check_error(err, "snd_pcm_hw_params_set_period_size_near (input)");
+    CHECK_ERROR("snd_pcm_hw_params_set_period_size_near");
 
         /* set the buffer size */
 #ifdef ALSAAPI9
@@ -196,10 +204,10 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
     err = snd_pcm_hw_params_set_buffer_size_near(dev->a_handle,
         hw_params, &tmp_snd_pcm_uframes);
 #endif
-    check_error(err, "snd_pcm_hw_params_set_buffer_size_near (input)");
+    CHECK_ERROR("snd_pcm_hw_params_set_buffer_size_near");
 
     err = snd_pcm_hw_params(dev->a_handle, hw_params);
-    check_error(err, "snd_pcm_hw_params (input)");
+    CHECK_ERROR("snd_pcm_hw_params");
 
         /* set up the buffer */
     bufsizeforthis = DEFDACBLKSIZE * dev->a_sampwidth * *channels;
@@ -227,18 +235,19 @@ static int alsaio_setup(t_alsa_dev *dev, int out, int *channels, int *rate,
         alsa_snd_bufsize = bufsizeforthis;
     }
     return (1);
+#undef CHECK_ERROR
 }
 
 
     /* return 0 on success */
 int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
-    int *choutdev, int rate)
+    int *choutdev, int rate, int blocksize)
 {
     int err, inchans = 0, outchans = 0, subunitdir;
     char devname[512];
     snd_output_t* out;
-    int frag_size = (sys_blocksize ? sys_blocksize : ALSA_DEFFRAGSIZE);
+    int frag_size = (blocksize ? blocksize : ALSA_DEFFRAGSIZE);
     int nfrags, i, iodev, dev2;
     int wantinchans, wantoutchans, device;
 
@@ -292,7 +301,7 @@ int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
     if (alsa_usemmap)
     {
         post("using mmap audio interface");
-        if (alsamm_open_audio(rate))
+        if (alsamm_open_audio(rate, blocksize))
             goto blewit;
         else return (0);
     }
@@ -469,7 +478,7 @@ int alsa_send_dacs(void)
                 ((char *)(alsa_snd_buf))[3*j+1] = ((s>>8) & 255);
                 ((char *)(alsa_snd_buf))[3*j+2] = ((s>>16) & 255);
 #else
-                fprintf(stderr("big endian 24-bit not supported");
+                fprintf(stderr, "big endian 24-bit not supported");
 #endif
             }
             for (; i < thisdevchans; i++, ch++)
@@ -581,7 +590,7 @@ int alsa_send_dacs(void)
                         * (1./ INT32_MAX);
             }
 #else
-                fprintf(stderr("big endian 24-bit not supported");
+                fprintf(stderr, "big endian 24-bit not supported");
 #endif
         }
         else
diff --git a/src/s_audio_alsa.h b/src/s_audio_alsa.h
index 813be2114..f59cff3c2 100644
--- a/src/s_audio_alsa.h
+++ b/src/s_audio_alsa.h
@@ -35,6 +35,6 @@ extern t_alsa_dev alsa_outdev[ALSA_MAXDEV];
 extern int alsa_nindev;
 extern int alsa_noutdev;
 
-int alsamm_open_audio(int rate);
+int alsamm_open_audio(int rate, int blocksize);
 void alsamm_close_audio(void);
 int alsamm_send_dacs(void);
diff --git a/src/s_audio_alsamm.c b/src/s_audio_alsamm.c
index 3bc4b3692..abcb0a85e 100644
--- a/src/s_audio_alsamm.c
+++ b/src/s_audio_alsamm.c
@@ -182,7 +182,7 @@ static void check_error(int err, const char *why)
         error("%s: %s\n", why, snd_strerror(err));
 }
 
-int alsamm_open_audio(int rate)
+int alsamm_open_audio(int rate, int blocksize)
 {
   int err;
   char devname[80];
@@ -238,16 +238,16 @@ int alsamm_open_audio(int rate)
   
   /* set the asked buffer time (alsa buffertime in us)*/  
   alsamm_buffertime = alsamm_buffersize = 0;
-  if(sys_blocksize == 0)
+  if(blocksize == 0)
     alsamm_buffertime = sys_schedadvance;
   else
-    alsamm_buffersize = sys_blocksize;
+    alsamm_buffersize = blocksize;
    
   if(sys_verbose)
     post("syschedadvance=%d us(%d Samples)so buffertime max should be this=%d" 
          "or sys_blocksize=%d (samples) to use buffersize=%d",
          sys_schedadvance,sys_advance_samples,alsamm_buffertime,
-         sys_blocksize,alsamm_buffersize);
+         blocksize,alsamm_buffersize);
   
   alsamm_periods = 0; /* no one wants periods setting from command line ;-) */
 
diff --git a/src/s_audio_jack.c b/src/s_audio_jack.c
index 5181085b9..79d4692ee 100644
--- a/src/s_audio_jack.c
+++ b/src/s_audio_jack.c
@@ -11,88 +11,140 @@
 #include <jack/jack.h>
 #include <regex.h>
 
-
 #define MAX_CLIENTS 100
-#define NUM_JACK_PORTS 128
+#define MAX_JACK_PORTS 128  /* seems like higher values give bad xrun problems */
 #define BUF_JACK 4096
 static jack_nframes_t jack_out_max;
 #define JACK_OUT_MAX  64
 static jack_nframes_t jack_filled = 0;
-static t_sample jack_outbuf[NUM_JACK_PORTS*BUF_JACK];
-static t_sample jack_inbuf[NUM_JACK_PORTS*BUF_JACK];
+static t_sample *jack_outbuf;
+static t_sample *jack_inbuf;
 static int jack_started = 0;
 
 
-static jack_port_t *input_port[NUM_JACK_PORTS];
-static jack_port_t *output_port[NUM_JACK_PORTS];
+static jack_port_t *input_port[MAX_JACK_PORTS];
+static jack_port_t *output_port[MAX_JACK_PORTS];
 static int outport_count = 0;
 static jack_client_t *jack_client = NULL;
 char *jack_client_names[MAX_CLIENTS];
 static int jack_dio_error;
-
+static t_audiocallback jack_callback;
 
 pthread_mutex_t jack_mutex;
 pthread_cond_t jack_sem;
 
-int jack_get_srate(void)
-{
-	if (jack_client) return jack_get_sample_rate (jack_client);
-	else return 0;
-}
 
 static int
 process (jack_nframes_t nframes, void *arg)
 {
-        int j;
-        jack_default_audio_sample_t *out, *in;
-        
-        if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
-        else jack_out_max = JACK_OUT_MAX;
-        if (jack_filled >= nframes) {
-                if (jack_filled != nframes) fprintf(stderr,"Partial read");
-                /* hmm, how to find out whether 't_sample' and 'jack_default_audio_sample_t' are actually the same type??? */
-                if(sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) 
+    int j;
+    jack_default_audio_sample_t *out, *in;
+
+    pthread_mutex_lock(&jack_mutex);
+    if (nframes > JACK_OUT_MAX) jack_out_max = nframes;
+    else jack_out_max = JACK_OUT_MAX;
+    if (jack_filled >= nframes)
+    {
+        if (jack_filled != nframes)
+            fprintf(stderr,"Partial read\n");
+        /* hmm, how to find out whether 't_sample' and
+            'jack_default_audio_sample_t' are actually the same type??? */
+        if (sizeof(t_sample)==sizeof(jack_default_audio_sample_t)) 
+        {
+            for (j = 0; j < sys_outchannels;  j++)
+            {
+                out = jack_port_get_buffer (output_port[j], nframes);
+                memcpy(out, jack_outbuf + (j * BUF_JACK),
+                    sizeof (jack_default_audio_sample_t) * nframes);
+            }
+            for (j = 0; j < sys_inchannels; j++)
+            {
+                in = jack_port_get_buffer( input_port[j], nframes);
+                memcpy(jack_inbuf + (j * BUF_JACK), in,
+                    sizeof (jack_default_audio_sample_t) * nframes);
+            }
+        } 
+        else
+        {
+            unsigned int frame=0;
+            t_sample*data;
+            for (j = 0; j < sys_outchannels;  j++)
+            {
+                out = jack_port_get_buffer (output_port[j], nframes);
+                data = jack_outbuf + (j * BUF_JACK);
+                for(frame=0; frame<nframes; frame++)
                 {
-                  for (j = 0; j < sys_outchannels;  j++) {
-                        out = jack_port_get_buffer (output_port[j], nframes);
-                        memcpy(out, jack_outbuf + (j * BUF_JACK), sizeof (jack_default_audio_sample_t) * nframes);
-                  }
-                  for (j = 0; j < sys_inchannels; j++) {
-                        in = jack_port_get_buffer( input_port[j], nframes);
-                        memcpy(jack_inbuf + (j * BUF_JACK), in, sizeof (jack_default_audio_sample_t) * nframes);
-                  }
-                } 
-                else
+                    *out++=*data++;
+                }
+            }
+            for (j = 0; j < sys_inchannels; j++)
+            {
+                in = jack_port_get_buffer( input_port[j], nframes);
+                data = jack_inbuf + (j * BUF_JACK);
+                for(frame=0; frame<nframes; frame++)
                 {
-                  unsigned int frame=0;
-                  t_sample*data;
-                  for (j = 0; j < sys_outchannels;  j++) {
-                        out = jack_port_get_buffer (output_port[j], nframes);
-                        data=jack_outbuf + (j * BUF_JACK);
-                        for(frame=0; frame<nframes; frame++) {
-                          *out++=*data++;
-                        }
-                  }
-                  for (j = 0; j < sys_inchannels; j++) {
-                        in = jack_port_get_buffer( input_port[j], nframes);
-                        data=jack_inbuf+(j*BUF_JACK);
-                        for(frame=0; frame<nframes; frame++) {
-                          *data++=*in++;
-                        }
-                  }
+                    *data++=*in++;
                 }
-                jack_filled -= nframes;
-        } else { /* PD could not keep up ! */
-             if (jack_started) jack_dio_error = 1;
-             for (j = 0; j < outport_count;  j++) {
-                  out = jack_port_get_buffer (output_port[j], nframes);
-                  memset(out, 0, sizeof (float) * nframes); 
-             }
-             memset(jack_outbuf,0,sizeof(jack_outbuf));
-             jack_filled = 0;
+            }
         }
-        pthread_cond_broadcast(&jack_sem);
-        return 0;
+        jack_filled -= nframes;
+    }
+    else
+            { /* PD could not keep up ! */
+        if (jack_started) jack_dio_error = 1;
+        for (j = 0; j < outport_count;  j++)
+        {
+            out = jack_port_get_buffer (output_port[j], nframes);
+            memset(out, 0, sizeof (float) * nframes); 
+            memset(jack_outbuf + j * BUF_JACK, 0, BUF_JACK * sizeof(t_sample));
+        }
+        jack_filled = 0;
+    }
+    pthread_cond_broadcast(&jack_sem);
+    pthread_mutex_unlock(&jack_mutex);
+    return 0;
+}
+
+static int callbackprocess(jack_nframes_t nframes, void *arg)
+{
+    int chan, j, k;
+    unsigned int n;
+    jack_default_audio_sample_t *out[MAX_JACK_PORTS], *in[MAX_JACK_PORTS], *jp;
+
+    if (nframes % DEFDACBLKSIZE)
+    {
+        fprintf(stderr, "jack: nframes %d not a multiple of blocksize %d\n",
+            nframes, DEFDACBLKSIZE);
+        nframes -= (nframes % DEFDACBLKSIZE);
+    }
+    for (chan = 0; chan < sys_inchannels; chan++)
+        in[chan] = jack_port_get_buffer(input_port[chan], nframes);
+    for (chan = 0; chan < sys_outchannels; chan++)
+        out[chan] = jack_port_get_buffer(output_port[chan], nframes);
+    for (n = 0; n < nframes; n += DEFDACBLKSIZE)
+    {
+        t_sample *fp;
+        for (chan = 0; chan < sys_inchannels; chan++)
+        {
+            for (fp = sys_soundin + chan*DEFDACBLKSIZE,
+                jp = in[chan] + n, j=0; j < DEFDACBLKSIZE; j++)
+                    *fp++ = *jp++;
+        }
+        for (chan = 0; chan < sys_outchannels; chan++)
+        {
+            for (fp = sys_soundout + chan*DEFDACBLKSIZE,
+                j = 0; j < DEFDACBLKSIZE; j++)
+                    *fp++ = 0;
+        }
+        (*jack_callback)();
+        for (chan = 0; chan < sys_outchannels; chan++)
+        {
+            for (fp = sys_soundout + chan*DEFDACBLKSIZE, jp = out[chan] + n,
+                j=0; j < DEFDACBLKSIZE; j++)
+                    *jp++ = *fp++;
+        }
+    }       
+    return 0;
 }
 
 static int
@@ -102,16 +154,22 @@ jack_srate (jack_nframes_t srate, void *arg)
         return 0;
 }
 
+
+void glob_audio_setapi(void *dummy, t_floatarg f);
+
 static void
 jack_shutdown (void *arg)
 {
-  verbose(1, "JACK-server shut down");
-  sys_close_audio();
+  error("JACK: server shut down");
+  
+  jack_deactivate (jack_client);
+  //jack_client_close(jack_client); /* likely to hang if the server shut down */
   jack_client = NULL;
+
+  glob_audio_setapi(NULL, API_NONE); // set pd_whichapi 0
 }
 
 static int jack_xrun(void* arg) {
-  verbose(1, "JACK-server xrun");
   jack_dio_error = 1;
   return 0;
 }
@@ -129,55 +187,55 @@ static char** jack_get_clients(void)
     jack_client_names[0] = NULL;
 
     /* Build a list of clients from the list of ports */
-	if (jack_ports != NULL) {
-		for( i = 0; jack_ports[i] != NULL; i++ )
-		{
-		    int client_seen;
-		    regmatch_t match_info;
-		    char tmp_client_name[100];
-
-		    /* extract the client name from the port name, using a regex
-		     * that parses the clientname:portname syntax */
-		    regexec( &port_regex, jack_ports[i], 1, &match_info, 0 );
-		    memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so],
-		            match_info.rm_eo - match_info.rm_so );
-		    tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0';
-
-		    /* do we know about this port's client yet? */
-		    client_seen = 0;
-
-		    for( j = 0; j < num_clients; j++ )
-		        if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 )
-		            client_seen = 1;
-
-		    if( client_seen == 0 )
-		    {
-		        jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1);
-
-		        /* The alsa_pcm client should go in spot 0.  If this
-		         * is the alsa_pcm client AND we are NOT about to put
-		         * it in spot 0 put it in spot 0 and move whatever
-		         * was already in spot 0 to the end. */
-
-		        if( strcmp( "system", tmp_client_name ) == 0 && num_clients > 0 )
-		        {
-		          char* tmp;
-		            /* alsa_pcm goes in spot 0 */
-		          tmp = jack_client_names[ num_clients ];
-		          jack_client_names[ num_clients ] = jack_client_names[0];
-		          jack_client_names[0] = tmp;
-		          strcpy( jack_client_names[0], tmp_client_name);
-		        }
-		        else
-		        {
-		            /* put the new client at the end of the client list */
-		            strcpy( jack_client_names[ num_clients ], tmp_client_name );
-		        }
-		        num_clients++;
-
-		    }
-		}
-	}
+    for( i = 0; jack_ports[i] != NULL; i++ )
+    {
+        int client_seen;
+        regmatch_t match_info;
+        char tmp_client_name[100];
+
+        if(num_clients>=MAX_CLIENTS)break;
+
+
+        /* extract the client name from the port name, using a regex
+         * that parses the clientname:portname syntax */
+        regexec( &port_regex, jack_ports[i], 1, &match_info, 0 );
+        memcpy( tmp_client_name, &jack_ports[i][match_info.rm_so],
+                match_info.rm_eo - match_info.rm_so );
+        tmp_client_name[ match_info.rm_eo - match_info.rm_so ] = '\0';
+
+        /* do we know about this port's client yet? */
+        client_seen = 0;
+
+        for( j = 0; j < num_clients; j++ )
+            if( strcmp( tmp_client_name, jack_client_names[j] ) == 0 )
+                client_seen = 1;
+
+        if( client_seen == 0 )
+        {
+            jack_client_names[num_clients] = (char*)getbytes(strlen(tmp_client_name) + 1);
+
+            /* The alsa_pcm client should go in spot 0.  If this
+             * is the alsa_pcm client AND we are NOT about to put
+             * it in spot 0 put it in spot 0 and move whatever
+             * was already in spot 0 to the end. */
+
+            if( strcmp( "alsa_pcm", tmp_client_name ) == 0 && num_clients > 0 )
+            {
+              char* tmp;
+                /* alsa_pcm goes in spot 0 */
+              tmp = jack_client_names[ num_clients ];
+              jack_client_names[ num_clients ] = jack_client_names[0];
+              jack_client_names[0] = tmp;
+              strcpy( jack_client_names[0], tmp_client_name);
+            }
+            else
+            {
+                /* put the new client at the end of the client list */
+                strcpy( jack_client_names[ num_clients ], tmp_client_name );
+            }
+            num_clients++;
+        }
+    }
 
     /*    for (i=0;i<num_clients;i++) post("client: %s",jack_client_names[i]); */
 
@@ -205,7 +263,7 @@ static int jack_connect_ports(char* client)
   if (jack_ports) 
     for (i=0;jack_ports[i] != NULL && i < sys_inchannels;i++)      
       if (jack_connect (jack_client, jack_ports[i], jack_port_name (input_port[i]))) 
-        error("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i]));
+        error ("JACK: cannot connect input ports %s -> %s", jack_ports[i],jack_port_name (input_port[i]));
       
   
   
@@ -214,7 +272,7 @@ static int jack_connect_ports(char* client)
   if (jack_ports) 
     for (i=0;jack_ports[i] != NULL && i < sys_outchannels;i++)      
       if (jack_connect (jack_client, jack_port_name (output_port[i]), jack_ports[i])) 
-        error("JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]);
+        error( "JACK: cannot connect output ports %s -> %s", jack_port_name (output_port[i]),jack_ports[i]);
   
   
   
@@ -223,199 +281,244 @@ static int jack_connect_ports(char* client)
 }
 
 
-void jack_error(const char *desc) {
-  error("JACK error: %s", desc);
+static void pd_jack_error_callback(const char *desc) {
+  error("JACKerror: %s", desc);
   return;
 }
 
-
 int
-jack_open_audio(int inchans, int outchans, int rate)
-
+jack_open_audio(int inchans, int outchans, int rate, t_audiocallback callback)
 {
-        int j;
-        char port_name[80] = "";
-        int client_iterator = 0;
-        int new_jack = 0;
-        int srate;
-        jack_status_t status;
+    int j;
+    char port_name[80] = "";
+    char client_name[80] = "";
 
-        jack_dio_error = 0;
-        
-        if ((inchans == 0) && (outchans == 0)) return 0;
+    int client_iterator = 0;
+    int new_jack = 0;
+    int srate;
+    jack_status_t status;
 
-        if (outchans > NUM_JACK_PORTS) {
-                error("JACK: %d output ports not supported, setting to %d",outchans, NUM_JACK_PORTS);
-                outchans = NUM_JACK_PORTS;
-        }
+    if (NULL==jack_client_new)
+    {
+        fprintf(stderr,"JACK framework not available\n");
+        return 1;
+    }
 
-        if (inchans > NUM_JACK_PORTS) {
-                error("JACK: %d input ports not supported, setting to %d",inchans, NUM_JACK_PORTS);
-                inchans = NUM_JACK_PORTS;
-        }
+    jack_dio_error = 0;
 
-        /* try to become a client of the JACK server */
-        /* if no JACK server exists, start a default one (jack_client_open() does that for us... */
-        if (!jack_client) {
-          do {
-            sprintf(port_name,"pure_data_%d",client_iterator);
-            client_iterator++;
-            /* do not try to start the jack-server...seems to make problems... */
-            jack_client = jack_client_open (port_name, JackNoStartServer, &status, NULL);
-            if (status & JackServerFailed) {
-              error("JACK: unable to connect to JACK server");
-              jack_client=NULL;
-              break;
-            }
-          } while (status & JackNameNotUnique);
+    if ((inchans == 0) && (outchans == 0)) return 0;
 
-          if(status) {
-            if (status & JackServerStarted) {
-              post("JACK: started JACK server?");
-            } else {
-              post("JACK: jack returned status %d", status);
-            }
+    if (outchans > MAX_JACK_PORTS) {
+        error("JACK: %d output ports not supported, setting to %d",
+            outchans, MAX_JACK_PORTS);
+        outchans = MAX_JACK_PORTS;
+    }
+
+    if (inchans > MAX_JACK_PORTS) {
+        error("JACK: %d input ports not supported, setting to %d",
+            inchans, MAX_JACK_PORTS);
+        inchans = MAX_JACK_PORTS;
+    }
+    /* try to become a client of the JACK server */
+    /* if no JACK server exists, start a default one (jack_client_open() does that for us... */
+    if (!jack_client) {
+        do {
+          sprintf(client_name,"pure_data_%d",client_iterator);
+          client_iterator++;
+          jack_client = jack_client_open (client_name, JackNullOption, &status, NULL);
+          if (status & JackServerFailed) {
+            error("JACK: unable to connect to JACK server");
+            jack_client=NULL;
+            break;
           }
-          
-          if (!jack_client) { // jack spits out enough messages already, do not warn
+        } while (status & JackNameNotUnique);
+
+        if(status) {
+          if (status & JackServerStarted) {
+            verbose(1, "JACK: started server");
+          } else {
+            error("JACK: server returned status %d", status);
+          }
+        }
+        verbose(1, "JACK: started server as '%s'", client_name);
+
+        if (!jack_client) {
+            /* jack spits out enough messages already, do not warn */
             sys_inchannels = sys_outchannels = 0;
             return 1;
-          }
-          
-          jack_get_clients();
-
-          /* tell the JACK server to call `process()' whenever
-             there is work to be done.
-          */
-          
-          jack_set_process_callback (jack_client, process, 0);
-          
-          //          jack_set_error_function (jack_error);
-          
+        }
+        
+        sys_inchannels = inchans;
+        sys_outchannels = outchans;
+        if (jack_inbuf)
+            free(jack_inbuf);
+        if (sys_inchannels)
+            jack_inbuf = calloc(sizeof(t_sample), sys_inchannels * BUF_JACK); 
+        if (jack_outbuf)
+            free(jack_outbuf);
+        if (sys_outchannels)
+            jack_outbuf = calloc(sizeof(t_sample), sys_outchannels * BUF_JACK); 
+
+        jack_get_clients();
+
+        /* tell the JACK server to call `process()' whenever
+           there is work to be done.
+        */
+        jack_callback = callback;
+        jack_set_process_callback (jack_client, 
+            (callback? callbackprocess : process), 0);
+
+        jack_set_error_function (pd_jack_error_callback);
+
 #ifdef JACK_XRUN
-          jack_set_xrun_callback (jack_client, jack_xrun, NULL);
+      jack_set_xrun_callback (jack_client, jack_xrun, NULL);
 #endif
-          
-          /* tell the JACK server to call `srate()' whenever
-             the sample rate of the system changes.
-          */
-          
-          jack_set_sample_rate_callback (jack_client, jack_srate, 0);
-          
-          
-          /* tell the JACK server to call `jack_shutdown()' if
-             it ever shuts down, either entirely, or if it
-             just decides to stop calling us.
-          */
-          
-          jack_on_shutdown (jack_client, jack_shutdown, 0);
-          
-          for (j=0;j<NUM_JACK_PORTS;j++) {
-               input_port[j]=NULL;
-               output_port[j] = NULL;
-          }
-          
-          new_jack = 1;
-        }
 
-        /* display the current sample rate. once the client is activated
-           (see below), you should rely on your own sample rate
-           callback (see above) for this value.
+        /* tell the JACK server to call `srate()' whenever
+           the sample rate of the system changes.
         */
-        
-        srate = jack_get_sample_rate (jack_client);
-        sys_dacsr = srate;
-                
-        /* create the ports */
-        
-        for (j = 0; j < inchans; j++) {
-                sprintf(port_name, "input%d", j);
-                if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
-                if (!input_port[j]) {
-                  error("JACK: can only register %d input ports (instead of requested %d)", j, inchans);
-                  sys_inchannels = inchans = j;
-                  break;
-                }
+
+        jack_set_sample_rate_callback (jack_client, jack_srate, 0);
+
+
+        /* tell the JACK server to call `jack_shutdown()' if
+           it ever shuts down, either entirely, or if it
+           just decides to stop calling us.
+        */
+
+        jack_on_shutdown (jack_client, jack_shutdown, 0);
+
+        for (j=0; j<sys_inchannels; j++)
+             input_port[j]=NULL;
+        for (j=0; j<sys_outchannels; j++)
+             output_port[j] = NULL;
+
+        new_jack = 1;
+    }
+
+    /* display the current sample rate. once the client is activated
+       (see below), you should rely on your own sample rate
+       callback (see above) for this value.
+    */
+
+    srate = jack_get_sample_rate (jack_client);
+    sys_dacsr = srate;
+
+    /* create the ports */
+
+    for (j = 0; j < inchans; j++) {
+        sprintf(port_name, "input%d", j);
+        if (!input_port[j]) input_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
+        if (!input_port[j]) {
+          error("JACK: can only register %d input ports (instead of requested %d)", j, inchans);
+          sys_inchannels = inchans = j;
+          break;
         }
+    }
 
-        for (j = 0; j < outchans; j++) {
-                sprintf(port_name, "output%d", j);
-                if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
-                if (!output_port[j]) {
-                  error("JACK: can only register %d output ports (instead of requested %d)", j, outchans);
-                  sys_outchannels = outchans = j;
-                  break;
-                }
-        } 
-        outport_count = outchans;
+    for (j = 0; j < outchans; j++) {
+        sprintf(port_name, "output%d", j);
+        if (!output_port[j]) output_port[j] = jack_port_register (jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+        if (!output_port[j]) {
+          error("JACK: can only register %d output ports (instead of requested %d)", j, outchans);
+          sys_outchannels = outchans = j;
+          break;
+        }
+    } 
+    outport_count = outchans;
 
-        /* tell the JACK server that we are ready to roll */
- 
-        if (new_jack) {
-          if (jack_activate (jack_client)) {
-            error("JACK: cannot activate client");
+    /* tell the JACK server that we are ready to roll */
+
+    if (new_jack) {
+        if (jack_activate (jack_client)) {
+            error("cannot activate client");
             sys_inchannels = sys_outchannels = 0;
             return 1;
-          }
-          
-          memset(jack_outbuf,0,sizeof(jack_outbuf));
-          
-          if (jack_client_names[0])
+        }
+
+        for (j = 0; j < outchans; j++) 
+            memset(jack_outbuf + j * BUF_JACK, 0,
+                BUF_JACK * sizeof(t_sample));
+
+        if (jack_client_names[0])
             jack_connect_ports(jack_client_names[0]);
 
-          pthread_mutex_init(&jack_mutex,NULL);
-          pthread_cond_init(&jack_sem,NULL);
-        }
-        return 0;
+        pthread_mutex_init(&jack_mutex, NULL);
+        pthread_cond_init(&jack_sem, NULL);
+    }
+    return 0;
 }
 
 void jack_close_audio(void) 
-
 {
-        jack_started = 0;
+    if (jack_client){
+        jack_deactivate (jack_client);
+        jack_client_close(jack_client);
+    }
+
+    jack_client=NULL;
+    jack_started = 0;
+
+    pthread_cond_broadcast(&jack_sem);
+
+    pthread_cond_destroy(&jack_sem);
+    pthread_mutex_destroy(&jack_mutex);
+    if (jack_inbuf)
+        free(jack_inbuf), jack_inbuf = 0;
+    if (jack_outbuf)
+        free(jack_outbuf), jack_outbuf = 0;
+ 
 }
 
 int jack_send_dacs(void)
 
 {
-        t_sample * fp;
-        int j;
-        int rtnval =  SENDDACS_YES;
-        int timenow;
-        int timeref = sys_getrealtime();
-                
-        if (!jack_client) return SENDDACS_NO;
-
-        if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO); 
-
-        if (jack_dio_error) {
-                sys_log_error(ERR_RESYNC);
-                jack_dio_error = 0;
-        }
-        if (jack_filled >= jack_out_max)
-          pthread_cond_wait(&jack_sem,&jack_mutex);
-          
-        jack_started = 1;
-
-        fp = sys_soundout;
-        for (j = 0; j < sys_outchannels; j++) {
-                memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled,fp, DEFDACBLKSIZE*sizeof(t_sample));
-                fp += DEFDACBLKSIZE;  
-        }
-        fp = sys_soundin;
-        for (j = 0; j < sys_inchannels; j++) {
-                memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled, DEFDACBLKSIZE*sizeof(t_sample));
-                fp += DEFDACBLKSIZE;
-        }
+    t_sample * fp;
+    int j;
+    int rtnval =  SENDDACS_YES;
+    int timenow;
+    int timeref = sys_getrealtime();
+    if (!jack_client) return SENDDACS_NO;
+    if (!sys_inchannels && !sys_outchannels) return (SENDDACS_NO); 
+    if (jack_dio_error)
+    {
+        sys_log_error(ERR_RESYNC);
+        jack_dio_error = 0;
+    }
+    pthread_mutex_lock(&jack_mutex);
+    if (jack_filled >= jack_out_max)
+        pthread_cond_wait(&jack_sem,&jack_mutex);
 
-        if ((timenow = sys_getrealtime()) - timeref > 0.002)
-          {
-            rtnval = SENDDACS_SLEPT;
-          }
+    if (!jack_client)
+    {
+        pthread_mutex_unlock(&jack_mutex);
+        return SENDDACS_NO;
+    }
+    jack_started = 1;
 
-        memset(sys_soundout,0,DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
-        jack_filled += DEFDACBLKSIZE;
-        return rtnval;
+    fp = sys_soundout;
+    for (j = 0; j < sys_outchannels; j++)
+    {
+        memcpy(jack_outbuf + (j * BUF_JACK) + jack_filled, fp,
+            DEFDACBLKSIZE*sizeof(t_sample));
+        fp += DEFDACBLKSIZE;  
+    }
+    fp = sys_soundin;
+    for (j = 0; j < sys_inchannels; j++)
+    {
+        memcpy(fp, jack_inbuf + (j * BUF_JACK) + jack_filled,
+            DEFDACBLKSIZE*sizeof(t_sample));
+        fp += DEFDACBLKSIZE;
+    }
+    jack_filled += DEFDACBLKSIZE;
+    pthread_mutex_unlock(&jack_mutex);
+
+    if ((timenow = sys_getrealtime()) - timeref > 0.002)
+    {
+        rtnval = SENDDACS_SLEPT;
+    }
+    memset(sys_soundout, 0, DEFDACBLKSIZE*sizeof(t_sample)*sys_outchannels);
+    return rtnval;
 }
 
 void jack_getdevs(char *indevlist, int *nindevs,
@@ -435,7 +538,7 @@ void jack_getdevs(char *indevlist, int *nindevs,
 
 void jack_listdevs( void)
 {
-    error("device listing not implemented for jack yet");
+    post("device listing not implemented for jack yet\n");
 }
 
 #endif /* JACK */
diff --git a/src/s_audio_oss.c b/src/s_audio_oss.c
index 73f916ce2..10329fed9 100644
--- a/src/s_audio_oss.c
+++ b/src/s_audio_oss.c
@@ -5,7 +5,11 @@
 
 /* this file inputs and outputs audio using the OSS API available on linux. */
 
-#include <linux/soundcard.h>
+#if defined(__FreeBSD_kernel__)
+# include <sys/soundcard.h>
+#else
+# include <linux/soundcard.h>
+#endif
 
 #include "m_pd.h"
 #include "s_stuff.h"
@@ -45,7 +49,7 @@ static int linux_meters;        /* true if we're metering */
 static t_sample linux_inmax;       /* max input amplitude */
 static t_sample linux_outmax;      /* max output amplitude */
 static int linux_fragsize = 0;  /* for block mode; block size (sample frames) */
-
+extern int audio_blocksize;     /* stolen from s_audio.c */
 /* our device handles */
 
 typedef struct _oss_dev
@@ -121,7 +125,8 @@ int oss_reset(int fd) {
      return err;
 }
 
-void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
+void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize,
+    int suggestedblocksize)
 {
     int orig, param, nblk, fd = dev->d_fd, wantformat;
     int nchannels = dev->d_nchannels;
@@ -153,7 +158,7 @@ void oss_configure(t_oss_dev *dev, int srate, int dac, int skipblocksize)
     {
         int fragbytes, logfragsize, nfragment;
             /* setting fragment count and size.  */
-        linux_fragsize = sys_blocksize;
+        linux_fragsize = suggestedblocksize;
         if (!linux_fragsize)
         {
             linux_fragsize = OSS_DEFFRAGSIZE;
@@ -256,7 +261,8 @@ whynot:
 #define O_AUDIOFLAG O_NDELAY
 
 int oss_open_audio(int nindev,  int *indev,  int nchin,  int *chin,
-    int noutdev, int *outdev, int nchout, int *chout, int rate)
+    int noutdev, int *outdev, int nchout, int *chout, int rate,
+        int blocksize)
 {
     int capabilities = 0;
     int inchannels = 0, outchannels = 0;
@@ -358,7 +364,7 @@ int oss_open_audio(int nindev,  int *indev,  int nchin,  int *chin,
         {
             linux_dacs[linux_noutdevs].d_nchannels = gotchans;
             linux_dacs[linux_noutdevs].d_fd = fd;
-            oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0);
+            oss_configure(linux_dacs+linux_noutdevs, rate, 1, 0, blocksize);
 
             linux_noutdevs++;
             outchannels += gotchans;
@@ -433,7 +439,8 @@ int oss_open_audio(int nindev,  int *indev,  int nchin,  int *chin,
 
         linux_adcs[linux_nindevs].d_nchannels = gotchans;
         
-        oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened);
+        oss_configure(linux_adcs+linux_nindevs, rate, 0, alreadyopened,
+            blocksize);
 
         inchannels += gotchans;
         linux_nindevs++;
diff --git a/src/s_file.c b/src/s_file.c
index 7fe081a50..7d4ddb6fa 100644
--- a/src/s_file.c
+++ b/src/s_file.c
@@ -322,7 +322,8 @@ void sys_loadpreferences( void)
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
     int nmidiindev, midiindev[MAXMIDIINDEV];
     int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
-    int i, rate = 0, advance = 0, callback = 0, api, nolib, maxi;
+    int i, rate = 0, advance = -1, callback = 0, blocksize = 0,
+        api, nolib, maxi;
     char prefbuf[MAXPDSTRING], keybuf[80];
 
     sys_initloadpreferences();
@@ -373,9 +374,11 @@ void sys_loadpreferences( void)
         sscanf(prefbuf, "%d", &advance);
     if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &callback);
+    if (sys_getpreference("blocksize", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &blocksize);
     sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev,
         naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
-        callback);
+        callback, blocksize);
         
         /* load MIDI preferences */
         /* JMZ/MB: brackets for initializing */
@@ -460,7 +463,7 @@ void glob_savepreferences(t_pd *dummy)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int i, rate, advance, callback;
+    int i, rate, advance, callback, blocksize;
     char buf1[MAXPDSTRING], buf2[MAXPDSTRING];
     int nmidiindev, midiindev[MAXMIDIINDEV];
     int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
@@ -473,7 +476,8 @@ void glob_savepreferences(t_pd *dummy)
     sys_putpreference("audioapi", buf1);
 
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback,
+            &blocksize);
 
     sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False"));
     for (i = 0; i < naudioindev; i++)
@@ -499,6 +503,9 @@ void glob_savepreferences(t_pd *dummy)
     sprintf(buf1, "%d", callback);
     sys_putpreference("callback", buf1);
 
+    sprintf(buf1, "%d", blocksize);
+    sys_putpreference("blocksize", buf1);
+
         /* MIDI settings */
     sys_get_midi_params(&nmidiindev, midiindev, &nmidioutdev, midioutdev);
     sys_putpreference("nomidiin", (nmidiindev <= 0 ? "True" : "False"));
diff --git a/src/s_main.c b/src/s_main.c
index 7f4079e49..af13585c0 100644
--- a/src/s_main.c
+++ b/src/s_main.c
@@ -73,6 +73,7 @@ char sys_fontweight[] = "normal"; /* currently only used for iemguis */
 static int sys_main_srate;
 static int sys_main_advance;
 static int sys_main_callback;
+static int sys_main_blocksize;
 static int sys_listplease;
 
 int sys_externalschedlib;
@@ -582,7 +583,7 @@ int sys_argparse(int argc, char **argv)
         }
         else if (!strcmp(*argv, "-blocksize"))
         {
-            sys_setblocksize(atoi(argv[1]));
+            sys_main_blocksize = atoi(argv[1]);
             argc -= 2; argv += 2;
         }
         else if (!strcmp(*argv, "-sleepgrain") && (argc > 1))
@@ -928,7 +929,7 @@ static void sys_afterargparse(void)
     int i;
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int nchindev, nchoutdev, rate, advance, callback;
+    int nchindev, nchoutdev, rate, advance, callback, blocksize;
     int nmidiindev = 0, midiindev[MAXMIDIINDEV];
     int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV];
             /* add "extra" library to path */
@@ -964,7 +965,8 @@ static void sys_afterargparse(void)
             else are the default.  Overwrite them with any results
             of argument parsing, and store them again. */
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance,
+            &callback, &blocksize);
     if (sys_nchin >= 0)
     {
         nchindev = sys_nchin;
@@ -1012,9 +1014,11 @@ static void sys_afterargparse(void)
         rate = sys_main_srate;
     if (sys_main_callback)
         callback = sys_main_callback;
+	if (sys_main_blocksize)
+        blocksize = sys_main_blocksize;
     sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
         naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, 
-        callback);
+        callback, blocksize);
     sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);
 }
 
diff --git a/src/s_stuff.h b/src/s_stuff.h
index ceec125ff..18e602abc 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -78,12 +78,17 @@ extern int sys_blocksize;       /* audio I/O block size in sample frames */
 extern t_float sys_dacsr;
 extern int sys_schedadvance;
 extern int sys_sleepgrain;
-void sys_set_audio_settings(int naudioindev, int *audioindev,
+EXTERN void sys_set_audio_settings(int naudioindev, int *audioindev,
     int nchindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
-    int srate, int advance, int callback);
-void sys_reopen_audio( void);
-void sys_close_audio(void);
+    int srate, int advance, int callback, int blocksize);
+/* the same as above, but reopens the audio subsystem if needed */
+EXTERN void sys_set_audio_settings_reopen(int naudioindev, int *audioindev,
+    int nchindev, int *chindev,
+    int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
+    int srate, int advance, int callback, int blocksize);
+EXTERN void sys_reopen_audio( void);
+EXTERN void sys_close_audio(void);
 
 
 int sys_send_dacs(void);
@@ -236,7 +241,7 @@ void pa_getdevs(char *indevlist, int *nindevs,
 
 int oss_open_audio(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
-    int *choutdev, int rate);
+    int *choutdev, int rate, int blocksize);
 void oss_close_audio(void);
 int oss_send_dacs(void);
 void oss_reportidle(void);
@@ -246,7 +251,7 @@ void oss_getdevs(char *indevlist, int *nindevs,
 
 int alsa_open_audio(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
-    int *choutdev, int rate);
+    int *choutdev, int rate, int blocksize);
 void alsa_close_audio(void);
 int alsa_send_dacs(void);
 void alsa_reportidle(void);
@@ -254,7 +259,8 @@ void alsa_getdevs(char *indevlist, int *nindevs,
     char *outdevlist, int *noutdevs, int *canmulti, 
         int maxndev, int devdescsize);
 
-int jack_open_audio(int wantinchans, int wantoutchans, int srate);
+int jack_open_audio(int wantinchans, int wantoutchans, int srate,
+    t_audiocallback callback);
 void jack_close_audio(void);
 int jack_send_dacs(void);
 void jack_reportidle(void);
@@ -265,7 +271,7 @@ void jack_listdevs(void);
 
 int mmio_open_audio(int naudioindev, int *audioindev,
     int nchindev, int *chindev, int naudiooutdev, int *audiooutdev,
-    int nchoutdev, int *choutdev, int rate);
+    int nchoutdev, int *choutdev, int rate, int blocksize);
 void mmio_close_audio( void);
 void mmio_reportidle(void);
 int mmio_send_dacs(void);
@@ -273,6 +279,33 @@ void mmio_getdevs(char *indevlist, int *nindevs,
     char *outdevlist, int *noutdevs, int *canmulti, 
         int maxndev, int devdescsize);
 
+int audiounit_open_audio(int naudioindev, int *audioindev, int nchindev,
+    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+    int *choutdev, int rate);
+void audiounit_close_audio(void);
+int audiounit_send_dacs(void);
+void audiounit_listdevs(void);
+void audiounit_getdevs(char *indevlist, int *nindevs,
+    char *outdevlist, int *noutdevs, int *canmulti, 
+        int maxndev, int devdescsize);
+
+int esd_open_audio(int naudioindev, int *audioindev, int nchindev,
+    int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
+    int *choutdev, int rate);
+void esd_close_audio(void);
+int esd_send_dacs(void);
+void esd_listdevs(void);
+void esd_getdevs(char *indevlist, int *nindevs,
+    char *outdevlist, int *noutdevs, int *canmulti, 
+        int maxndev, int devdescsize);
+
+int dummy_open_audio(int nin, int nout, int sr);
+int dummy_close_audio( void);
+int dummy_send_dacs( void);
+void dummy_getdevs(char *indevlist, int *nindevs, char *outdevlist,
+    int *noutdevs, int *canmulti, int maxndev, int devdescsize);
+void dummy_listdevs( void);
+
 void sys_listmididevs(void);
 void sys_set_midi_api(int whichapi);
 void sys_set_audio_api(int whichapi);
@@ -284,14 +317,14 @@ void sys_set_audio_state(int onoff);
 void oss_set32bit( void);
 void linux_alsa_devname(char *devname);
 
-void sys_get_audio_params(
+EXTERN void sys_get_audio_params(
     int *pnaudioindev, int *paudioindev, int *chindev,
     int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
-    int *prate, int *padvance, int *callback);
+    int *prate, int *padvance, int *callback, int *blocksize);
 void sys_save_audio_params(
     int naudioindev, int *audioindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int *choutdev,
-    int rate, int advance, int callback);
+    int rate, int advance, int callback, int blocksize);
 
 /* s_file.c */
 
-- 
GitLab