diff --git a/src/CHANGELOG.txt b/src/CHANGELOG.txt
index ccd8641dfaf1b52d4578d5941ce442bf83063dcc..6c0dc1e3982fd489853f2232d866d7742b0569f4 100644
--- a/src/CHANGELOG.txt
+++ b/src/CHANGELOG.txt
@@ -2,6 +2,10 @@ This file describes implementation and API changes; stuff more visible to the
 user appears in the "release notes" instead.  See the bottom of this file
 for original notes on source stype and organization.
 
+0.41.0
+
+add support for callback-based audio I/O; changes in 
+
 0.40.0
 
 0.39.0
diff --git a/src/s_audio.c b/src/s_audio.c
index f33a135b7618213e37ce0c933ee612a38eb22475..ed4c9776d9f3a3910da9b4b81d2cc4a4c6f99f1c 100644
--- a/src/s_audio.c
+++ b/src/s_audio.c
@@ -29,7 +29,7 @@ typedef long t_pa_sample;
 #define DEVDESCSIZE 80
 
 static void audio_getdevs(char *indevlist, int *nindevs,
-    char *outdevlist, int *noutdevs, int *canmulti, 
+    char *outdevlist, int *noutdevs, int *canmulti, int *cancallback, 
         int maxndev, int devdescsize);
 
     /* these are set in this file when opening audio, but then may be reduced,
@@ -65,6 +65,9 @@ static int audio_audiooutdev[MAXAUDIOOUTDEV];
 static int audio_audiochoutdev[MAXAUDIOOUTDEV];
 static int audio_rate;
 static int audio_advance;
+static int audio_callback;
+
+void sched_set_callback(int flag);
 
 static int audio_isopen(void)
 {
@@ -76,7 +79,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 *prate, int *padvance, int *pcallback)
 {
     int i;
     *pnaudioindev = audio_naudioindev;
@@ -89,12 +92,13 @@ void sys_get_audio_params(
             choutdev[i] = audio_audiochoutdev[i]; 
     *prate = audio_rate;
     *padvance = audio_advance;
+    *pcallback = audio_callback;
 }
 
 void sys_save_audio_params(
     int naudioindev, int *audioindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int *choutdev,
-    int rate, int advance)
+    int rate, int advance, int callback)
 {
     int i;
     audio_naudioindev = naudioindev;
@@ -107,6 +111,7 @@ void sys_save_audio_params(
             audio_audiochoutdev[i] = choutdev[i]; 
     audio_rate = rate;
     audio_advance = advance;
+    audio_callback = callback;
 }
 
     /* init routines for any API which needs to set stuff up before
@@ -172,7 +177,7 @@ void sys_setchsr(int chin, int chout, int sr)
 
 void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
     int *chindev, int naudiooutdev, int *audiooutdev, int nchoutdev,
-    int *choutdev, int rate, int advance, int enable)
+    int *choutdev, int rate, int advance, int callback, int enable)
 {
     int i, *ip;
     int defaultchannels = SYS_DEFAULTCH;
@@ -181,9 +186,9 @@ void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
     int realinchans[MAXAUDIOINDEV], realoutchans[MAXAUDIOOUTDEV];
 
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
-    int indevs = 0, outdevs = 0, canmulti = 0;
+    int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0;
     audio_getdevs(indevlist, &indevs, outdevlist, &outdevs, &canmulti,
-        MAXNDEV, DEVDESCSIZE);
+        &cancallback, MAXNDEV, DEVDESCSIZE);
 
     if (sys_externalschedlib)
     {
@@ -333,7 +338,7 @@ void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
         {
             int blksize = (sys_blocksize ? sys_blocksize : 64);
             pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
-                blksize, sys_advance_samples/blksize,
+                blksize, sys_advance_samples/blksize, callback,
                     (naudiooutdev > 0 ? audioindev[0] : 0),
                         (naudiooutdev > 0 ? audiooutdev[0] : 0));
         }
@@ -360,17 +365,6 @@ else
                 nrealoutdev, audiooutdev, nrealoutdev, realoutchans, rate);
         else 
 #endif
-#ifdef USEAPI_SGI
-        if (sys_audioapi == API_SGI)
-        {
-            xtern int sgi_open_audio(int nindev,  int *indev,  int nchin,
-                int *chin,  int noutdev, int *outdev, int nchout, int *chout,
-                int rate);
-            sgi_open_audio(naudioindev, audioindev, nchindev, chindev,
-                    naudiooutdev, audiooutdev, nchoutdev, choutdev, rate);
-        }
-        else
-#endif
 #ifdef USEAPI_MMIO
         if (sys_audioapi == API_MMIO)
             mmio_open_audio(nrealindev, audioindev, nrealindev, realinchans,
@@ -380,7 +374,7 @@ else
             post("unknown audio API specified");
     }
     sys_save_audio_params(naudioindev, audioindev, chindev,
-        naudiooutdev, audiooutdev, choutdev, sys_dacsr, advance);
+        naudiooutdev, audiooutdev, choutdev, sys_dacsr, advance, callback);
     if (sys_inchannels == 0 && sys_outchannels == 0)
         enable = 0;
     audio_state = enable;
@@ -416,14 +410,6 @@ void sys_close_audio(void)
         alsa_close_audio();
     else
 #endif
-#ifdef USEAPI_SGI
-    if (sys_audioapi == API_SGI)
-    {
-        extern void sgi_close_audio(void);
-        sgi_close_audio();
-    }
-    else
-#endif
 #ifdef USEAPI_MMIO
     if (sys_audioapi == API_MMIO)
         mmio_close_audio();
@@ -438,11 +424,12 @@ void sys_reopen_audio( void)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int rate, advance;
+    int rate, advance, callback;
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
     sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
-        naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 1);
+        naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 
+        callback, 1);
 }
 
 int sys_send_dacs(void)
@@ -489,14 +476,6 @@ int sys_send_dacs(void)
         return (alsa_send_dacs());
     else
 #endif
-#ifdef USEAPI_SGI
-    if (sys_audioapi == API_SGI)
-    {
-        extern int sgi_send_dacs(void);
-        return (sgi_send_dacs());
-    }
-    else
-#endif
 #ifdef USEAPI_MMIO
     if (sys_audioapi == API_MMIO)
         return (mmio_send_dacs());
@@ -539,15 +518,17 @@ void sys_reportidle(void)
 }
 
 static void audio_getdevs(char *indevlist, int *nindevs,
-    char *outdevlist, int *noutdevs, int *canmulti, 
+    char *outdevlist, int *noutdevs, int *canmulti, int *cancallback,
         int maxndev, int devdescsize)
 {
     audio_init();
+    *cancallback = 0;   /* may be overridden by specific API implementation */
 #ifdef USEAPI_PORTAUDIO
     if (sys_audioapi == API_PORTAUDIO)
     {
         pa_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
             maxndev, devdescsize);
+        *cancallback = 1;
     }
     else
 #endif
@@ -575,17 +556,6 @@ static void audio_getdevs(char *indevlist, int *nindevs,
     }
     else
 #endif
-#ifdef USEAPI_SGI
-    if (sys_audioapi == API_SGI)
-    {
-        extern void sgi_getdevs(char *indevlist, int *nindevs,
-            char *outdevlist, int *noutdevs, int *canmulti, 
-            int maxndev, int devdescsize);
-        sgi_getdevs(indevlist, nindevs, outdevlist, noutdevs, canmulti,
-            maxndev, devdescsize);
-    }
-    else
-#endif
 #ifdef USEAPI_MMIO
     if (sys_audioapi == API_MMIO)
     {
@@ -611,10 +581,10 @@ static void audio_getdevs(char *indevlist, int *nindevs,
 static void sys_listaudiodevs(void )
 {
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
-    int nindevs = 0, noutdevs = 0, i, canmulti = 0;
+    int nindevs = 0, noutdevs = 0, i, canmulti = 0, cancallback = 0;
 
     audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
-        MAXNDEV, DEVDESCSIZE);
+        &cancallback, MAXNDEV, DEVDESCSIZE);
 
     if (!nindevs)
         post("no audio input devices found");
@@ -653,13 +623,13 @@ 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;
+    int rate, advance, callback;
         /* these are all the devices on your system: */
     char indevlist[MAXNDEV*DEVDESCSIZE], outdevlist[MAXNDEV*DEVDESCSIZE];
-    int nindevs = 0, noutdevs = 0, canmulti = 0, i;
+    int nindevs = 0, noutdevs = 0, canmulti = 0, cancallback = 0, i;
 
     audio_getdevs(indevlist, &nindevs, outdevlist, &noutdevs, &canmulti,
-        MAXNDEV, DEVDESCSIZE);
+         &cancallback, MAXNDEV, DEVDESCSIZE);
 
     sys_gui("global audio_indevlist; set audio_indevlist {}\n");
     for (i = 0; i < nindevs; i++)
@@ -672,7 +642,7 @@ 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);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
 
     /* post("naudioindev %d naudiooutdev %d longform %f",
             naudioindev, naudiooutdev, flongform); */
@@ -699,12 +669,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\n",
+%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, (flongform != 0));
+        rate, advance, canmulti, (cancallback ? callback : -1),
+        (flongform != 0));
     gfxstub_deleteforkey(0);
     gfxstub_new(&glob_pdobject, (void *)glob_audio_properties, buf);
 }
@@ -721,6 +692,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
         /* the new values the dialog came back with: */
     int newrate = atom_getintarg(16, argc, argv);
     int newadvance = atom_getintarg(17, argc, argv);
+    int newcallback = atom_getintarg(18, argc, argv);
     int statewas;
 
     for (i = 0; i < 4; i++)
@@ -757,7 +729,7 @@ void glob_audio_dialog(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
     sys_close_audio();
     sys_open_audio(nindev, newaudioindev, nindev, newaudioinchan,
         noutdev, newaudiooutdev, noutdev, newaudiooutchan,
-        newrate, newadvance, 1);
+        newrate, newadvance, newcallback, 1);
 }
 
 void sys_listdevs(void )
@@ -782,12 +754,6 @@ void sys_listdevs(void )
         sys_listaudiodevs();
     else
 #endif
-#ifdef USEAPI_SGI
-        extern void sgi_listaudiodevs(void);
-    if (sys_audioapi == API_SGI)
-        sgi_listaudiodevs();
-    else
-#endif
 #ifdef USEAPI_MMIO
     if (sys_audioapi == API_MMIO)
         sys_listaudiodevs();
@@ -888,9 +854,6 @@ void sys_get_audio_apis(char *buf)
 #else
     sprintf(buf + strlen(buf), "{portaudio %d} ", API_PORTAUDIO);
 #endif
-#ifdef USEAPI_SGI
-    sprintf(buf + strlen(buf), "{SGI %d} ", API_SGI); n++;
-#endif
 #endif
      n++;
 #endif
@@ -901,7 +864,6 @@ void sys_get_audio_apis(char *buf)
         /* then again, if only one API (or none) we don't offer any choice. */
     if (n < 2)
         strcpy(buf, "{}");
-    
 }
 
 #ifdef USEAPI_ALSA
diff --git a/src/s_audio_pa.c b/src/s_audio_pa.c
index e8ba1a25c00d10807d7a4284e9e2f922c1cde772..5f2af7f397613fbeddd90859c03e4b01233b4168 100644
--- a/src/s_audio_pa.c
+++ b/src/s_audio_pa.c
@@ -28,13 +28,15 @@ static float *pa_soundin, *pa_soundout;
 #define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
 
 int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
-    t_sample *soundout, int framesperbuf, int nbuffers,
+    t_sample *soundout, int framesperbuf, int nbuffers, int callback,
     int indeviceno, int outdeviceno)
 {
     PaError err;
     static int initialized;
     int j, devno, pa_indev = 0, pa_outdev = 0;
 
+    if (callback)
+        fprintf(stderr, "callback enabled\n");
     if (!initialized)
     {
         /* Initialize PortAudio  */
diff --git a/src/s_file.c b/src/s_file.c
index 53d71bfaada571c3acae6944007992af548fd720..dcf54b49f8325108daa963d11b7cca49eee04bdb 100644
--- a/src/s_file.c
+++ b/src/s_file.c
@@ -288,7 +288,7 @@ void sys_loadpreferences( void)
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
     int nmidiindev, midiindev[MAXMIDIINDEV];
     int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
-    int i, rate = 0, advance = 0, api, nolib, maxi;
+    int i, rate = 0, advance = 0, callback = 0, api, nolib, maxi;
     char prefbuf[MAXPDSTRING], keybuf[80];
 
     sys_initloadpreferences();
@@ -337,8 +337,11 @@ void sys_loadpreferences( void)
         sscanf(prefbuf, "%d", &rate);
     if (sys_getpreference("audiobuf", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &advance);
+    if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
+        sscanf(prefbuf, "%d", &callback);
     sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
-        naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 0);
+        naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
+        callback, 0);
         
         /* load MIDI preferences */
         /* JMZ/MB: brackets for initializing */
@@ -423,7 +426,7 @@ void glob_savepreferences(t_pd *dummy)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int i, rate, advance;
+    int i, rate, advance, callback;
     char buf1[MAXPDSTRING], buf2[MAXPDSTRING];
     int nmidiindev, midiindev[MAXMIDIINDEV];
     int nmidioutdev, midioutdev[MAXMIDIOUTDEV];
@@ -436,7 +439,7 @@ void glob_savepreferences(t_pd *dummy)
     sys_putpreference("audioapi", buf1);
 
     sys_get_audio_params(&naudioindev, audioindev, chindev,
-        &naudiooutdev, audiooutdev, choutdev, &rate, &advance);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
 
     sys_putpreference("noaudioin", (naudioindev <= 0 ? "True" : "False"));
     for (i = 0; i < naudioindev; i++)
@@ -459,6 +462,9 @@ void glob_savepreferences(t_pd *dummy)
     sprintf(buf1, "%d", rate);
     sys_putpreference("rate", buf1);
 
+    sprintf(buf1, "%d", callback);
+    sys_putpreference("callback", 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 c170aec5fea604ebe240a5e18a8156927fe5f365..0224923e825d446b7e22f275d9dbfd649ff366c3 100644
--- a/src/s_main.c
+++ b/src/s_main.c
@@ -43,6 +43,7 @@ int sys_noloadbang;
 int sys_nogui;
 int sys_hipriority = -1;    /* -1 = don't care; 0 = no; 1 = yes */
 int sys_guisetportnumber;   /* if started from the GUI, this is the port # */
+int sys_nosleep = 0;  /* skip all "sleep" calls and spin instead */
 
 char *sys_guicmd;
 t_symbol *sys_libdir;
@@ -60,6 +61,7 @@ int sys_midioutdevlist[MAXMIDIOUTDEV] = {1};
 char sys_font[100] = "courier"; /* tb: font name */
 static int sys_main_srate;
 static int sys_main_advance;
+static int sys_main_callback;
 static int sys_listplease;
 
 int sys_externalschedlib;
@@ -81,7 +83,6 @@ static int sys_nchout = -1;
 static int sys_chinlist[MAXAUDIOINDEV];
 static int sys_choutlist[MAXAUDIOOUTDEV];
 
-int sys_nosleep = 0;  /* skip all "sleep" calls and spin instead */
 t_sample* get_sys_soundout() { return sys_soundout; }
 t_sample* get_sys_soundin() { return sys_soundin; }
 int* get_sys_main_advance() { return &sys_main_advance; }
@@ -580,6 +581,11 @@ int sys_argparse(int argc, char **argv)
             sys_main_advance = atoi(argv[1]);
             argc -= 2; argv += 2;
         }
+        else if (!strcmp(*argv, "-callback"))
+        {
+            sys_main_callback = 1;
+            argc--; argv++;
+        }
         else if (!strcmp(*argv, "-blocksize"))
         {
             sys_setblocksize(atoi(argv[1]));
@@ -899,7 +905,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;
+    int nchindev, nchoutdev, rate, advance, callback;
     int nmidiindev = 0, midiindev[MAXMIDIINDEV];
     int nmidioutdev = 0, midioutdev[MAXMIDIOUTDEV];
             /* add "extra" library to path */
@@ -935,7 +941,7 @@ 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);
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
     if (sys_nchin >= 0)
     {
         nchindev = sys_nchin;
@@ -981,8 +987,11 @@ static void sys_afterargparse(void)
         advance = sys_main_advance;
     if (sys_main_srate)
         rate = sys_main_srate;
+    if (sys_main_callback)
+        callback = sys_main_callback;
     sys_open_audio(naudioindev, audioindev, nchindev, chindev,
-        naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, 0);
+        naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, 
+        callback, 0);
     sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);
 }
 
diff --git a/src/s_stuff.h b/src/s_stuff.h
index 17974833a5b141534c3f7715ffb6ee9bc3d4f39e..8320558da82206f7035752a4b7119a51b2338484 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -74,7 +74,7 @@ extern int sys_sleepgrain;
 void sys_open_audio(int naudioindev, int *audioindev,
     int nchindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int nchoutdev, int *choutdev,
-    int srate, int advance, int enable);
+    int srate, int advance, int callback, int enable);
 void sys_reopen_audio( void);
 void sys_close_audio(void);
 
@@ -206,7 +206,7 @@ void sys_setvirtualalarm( void);
 #endif
 
 int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
-    t_sample *soundout, int framesperbuf, int nbuffers,
+    t_sample *soundout, int framesperbuf, int nbuffers, int callback,
     int indeviceno, int outdeviceno);
 void pa_close_audio(void);
 int pa_send_dacs(void);
@@ -269,11 +269,11 @@ void linux_alsa_devname(char *devname);
 void sys_get_audio_params(
     int *pnaudioindev, int *paudioindev, int *chindev,
     int *pnaudiooutdev, int *paudiooutdev, int *choutdev,
-    int *prate, int *padvance);
+    int *prate, int *padvance, int *callback);
 void sys_save_audio_params(
     int naudioindev, int *audioindev, int *chindev,
     int naudiooutdev, int *audiooutdev, int *choutdev,
-    int rate, int advance);
+    int rate, int advance, int callback);
 
 /* s_file.c */
 
diff --git a/src/u_main.tk b/src/u_main.tk
index b44aedabb49790997191fe3e7ffd22f2a70f30b8..2a736ca5dfbf9465b9494714cb7f72a85f65ec5f 100644
--- a/src/u_main.tk
+++ b/src/u_main.tk
@@ -3479,7 +3479,7 @@ proc audio_apply {id} {
     global audio_outdev1 audio_outdev2 audio_outdev3 audio_outdev4 
     global audio_outchan1 audio_outchan2 audio_outchan3 audio_outchan4
     global audio_outenable1 audio_outenable2 audio_outenable3 audio_outenable4
-    global audio_sr audio_advance
+    global audio_sr audio_advance audio_callback
 
     pd [concat pd audio-dialog \
         $audio_indev1 \
@@ -3500,6 +3500,7 @@ proc audio_apply {id} {
         [expr $audio_outchan4 * ( $audio_outenable4 ? 1 : -1 ) ]\
         $audio_sr \
         $audio_advance \
+        $audio_callback \
         \;]
 }
 
@@ -3543,14 +3544,15 @@ proc audio_popup {name buttonname varname devlist} {
 proc pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
         inchan1 inchan2 inchan3 inchan4 \
         outdev1 outdev2 outdev3 outdev4 \
-        outchan1 outchan2 outchan3 outchan4 sr advance multi longform} {
+        outchan1 outchan2 outchan3 outchan4 sr advance multi callback \
+        longform} {
     global audio_indev1 audio_indev2 audio_indev3 audio_indev4 
     global audio_inchan1 audio_inchan2 audio_inchan3 audio_inchan4
     global audio_inenable1 audio_inenable2 audio_inenable3 audio_inenable4
     global audio_outdev1 audio_outdev2 audio_outdev3 audio_outdev4
     global audio_outchan1 audio_outchan2 audio_outchan3 audio_outchan4
     global audio_outenable1 audio_outenable2 audio_outenable3 audio_outenable4
-    global audio_sr audio_advance
+    global audio_sr audio_advance audio_callback
     global audio_indevlist audio_outdevlist
     global pd_indev pd_outdev
 
@@ -3584,7 +3586,7 @@ proc pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
 
     set audio_sr $sr
     set audio_advance $advance
-
+    set audio_callback $callback
     toplevel $id
     wm title $id {audio}
     wm protocol $id WM_DELETE_WINDOW [concat audio_cancel $id]
@@ -3597,9 +3599,10 @@ proc pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
         -command "audio_apply $id"
     button $id.buttonframe.ok -text {OK}\
         -command "audio_ok $id"
-    pack $id.buttonframe.cancel -side left -expand 1
-    pack $id.buttonframe.apply -side left -expand 1
-    pack $id.buttonframe.ok -side left -expand 1
+    button $id.buttonframe.save -text {Save all settings}\
+        -command "audio_apply $id \; pd pd save-preferences \\;"
+    pack $id.buttonframe.cancel $id.buttonframe.apply $id.buttonframe.ok \
+        $id.buttonframe.save -side left -expand 1
     
         # sample rate and advance
     frame $id.srf
@@ -3610,7 +3613,11 @@ proc pdtk_audio_dialog {id indev1 indev2 indev3 indev4 \
     label $id.srf.l2 -text "delay (msec):"
     entry $id.srf.x2 -textvariable audio_advance -width 4
     pack $id.srf.l1 $id.srf.x1 $id.srf.l2 $id.srf.x2 -side left
-    
+    if {$audio_callback >= 0} {
+        checkbutton $id.srf.x3 -variable audio_callback \
+            -text {use callbacks} -anchor e
+        pack $id.srf.x3 -side left
+    }
         # input device 1
     frame $id.in1f
     pack $id.in1f -side top