From c84701024f03c241fb915edb33a45a11463ee339 Mon Sep 17 00:00:00 2001
From: Miller Puckette <msp@ucsd.edu>
Date: Wed, 15 Aug 2007 10:37:44 -0700
Subject: [PATCH] first cut at callback scheduler

---
 src/m_sched.c    |  58 ++++++++++++++-----
 src/s_audio.c    | 143 +++++++++++++++++++++++-----------------------
 src/s_audio_pa.c | 146 +++++++++++++++++++++++++++++++++++++++++++----
 src/s_file.c     |   4 +-
 src/s_main.c     |  10 ++--
 src/s_stuff.h    |  16 ++++--
 6 files changed, 269 insertions(+), 108 deletions(-)

diff --git a/src/m_sched.c b/src/m_sched.c
index bce50cd5b..b69d8f60b 100644
--- a/src/m_sched.c
+++ b/src/m_sched.c
@@ -15,7 +15,8 @@
 #define THREAD_LOCKING  
 #include "pthread.h"
 
-
+#define SYS_QUIT_QUIT 1
+#define SYS_QUIT_RESTART 2
 static int sys_quit;
 double sys_time;
 static double sys_time_per_msec = TIMEUNITPERSEC / 1000.;
@@ -326,14 +327,14 @@ void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
 
 void dsp_tick(void);
 
-static int sched_usedacs = 1;
+static int sched_useaudio = SCHED_AUDIO_POLL;
 static double sched_referencerealtime, sched_referencelogicaltime;
 double sys_time_per_dsp_tick;
 
-void sched_set_using_dacs(int flag)
+void sched_set_using_audio(int flag)
 {
-    sched_usedacs = flag;
-    if (!flag)
+    sched_useaudio = flag;
+    if (flag == SCHED_AUDIO_NONE)
     {
         sched_referencerealtime = sys_getrealtime();
         sched_referencelogicaltime = clock_getlogicaltime();
@@ -385,7 +386,7 @@ nonzero if you actually used the time; otherwise we're really really idle and
 will now sleep. */
 int (*sys_idlehook)(void);
 
-int m_scheduler( void)
+static void m_pollingscheduler( void)
 {
     int idlecount = 0;
     sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
@@ -410,7 +411,7 @@ int m_scheduler( void)
 
         sys_addhist(0);
     waitfortick:
-        if (sched_usedacs)
+        if (sched_useaudio != SCHED_AUDIO_NONE)
         {
 #ifdef THREAD_LOCKING
             /* T.Grill - send_dacs may sleep -> 
@@ -441,7 +442,7 @@ int m_scheduler( void)
                     {
                         post("audio I/O stuck... closing audio\n");
                         sys_close_audio();
-                        sched_set_using_dacs(0);
+                        sched_set_using_audio(SCHED_AUDIO_NONE);
                         goto waitfortick;
                     }
                 }
@@ -475,7 +476,6 @@ int m_scheduler( void)
         {
             sched_pollformeters();
             sys_reportidle();
-
 #ifdef THREAD_LOCKING
             sys_unlock();   /* unlock while we idle */
 #endif
@@ -489,20 +489,52 @@ int m_scheduler( void)
 #ifdef THREAD_LOCKING
             sys_lock();
 #endif
-
             sys_addhist(5);
             sched_didnothing++;
-
         }
     }
 
 #ifdef THREAD_LOCKING
     sys_unlock();
 #endif
+}
 
-    return (0);
+void sched_audio_callbackfn(void)
+{
+    sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
+    sys_addhist(1);
+    sched_tick(sys_time + sys_time_per_dsp_tick);
+    sys_addhist(2);
+    sys_pollmidiqueue();
+    sys_addhist(3);
+    sys_pollgui();
+    sys_addhist(5);
+    sched_pollformeters();
+    sys_addhist(0);
+}
+
+static void m_callbackscheduler(void)
+{
+    sys_initmidiqueue();
+    while (1)
+    {
+        sleep(1);
+        if (sys_idlehook)
+            sys_idlehook();
+    }
 }
 
+int m_mainloop(void)
+{
+    while (sys_quit != SYS_QUIT_QUIT)
+    {
+        post("sched %d", sched_useaudio);
+        if (sched_useaudio == SCHED_AUDIO_CALLBACK)
+            m_callbackscheduler();
+        else m_pollingscheduler();
+    }
+    return (0);
+}
 
 /* ------------ thread locking ------------------- */
 
@@ -534,5 +566,5 @@ int sys_trylock(void) {}
 
 void sys_exit(void)
 {
-        sys_quit = 1;
+    sys_quit = SYS_QUIT_QUIT;
 }
diff --git a/src/s_audio.c b/src/s_audio.c
index ed4c9776d..b33c85a55 100644
--- a/src/s_audio.c
+++ b/src/s_audio.c
@@ -67,7 +67,7 @@ static int audio_rate;
 static int audio_advance;
 static int audio_callback;
 
-void sched_set_callback(int flag);
+void sched_audio_callbackfn(void);
 
 static int audio_isopen(void)
 {
@@ -170,14 +170,14 @@ void sys_setchsr(int chin, int chout, int sr)
 
 /* ----------------------- public routines ----------------------- */
 
-    /* open audio devices (after cleaning up the specified device and channel
-    vectors).  The audio devices are "zero based" (i.e. "0" means the first
-    one.)  We also save the cleaned-up device specification so that we
-    can later re-open audio and/or show the settings on a dialog window. */
+    /* set audio device settings (after cleaning up the specified device and
+    channel vectors).  The audio devices are "zero based" (i.e. "0" means the
+    first one.)  We can later re-open audio and/or show the settings on a\
+    dialog window. */
 
-void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
+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 enable)
+    int *choutdev, int rate, int advance, int callback)
 {
     int i, *ip;
     int defaultchannels = SYS_DEFAULTCH;
@@ -189,7 +189,6 @@ void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
     int indevs = 0, outdevs = 0, canmulti = 0, cancallback = 0;
     audio_getdevs(indevlist, &indevs, outdevlist, &outdevs, &canmulti,
         &cancallback, MAXNDEV, DEVDESCSIZE);
-
     if (sys_externalschedlib)
     {
         return;
@@ -324,62 +323,11 @@ void sys_open_audio(int naudioindev, int *audioindev, int nchindev,
         outchans += choutdev[i];
         nrealoutdev++;
     }
-        /* if no input or output devices seem to have been specified,
-        this really means just disable audio, which we now do. */
-    if (!inchans && !outchans)
-        enable = 0;
     sys_schedadvance = advance * 1000;
     sys_setchsr(inchans, outchans, rate);
     sys_log_error(ERR_NOTHING);
-    if (enable)
-    {
-#ifdef USEAPI_PORTAUDIO
-        if (sys_audioapi == API_PORTAUDIO)
-        {
-            int blksize = (sys_blocksize ? sys_blocksize : 64);
-            pa_open_audio(inchans, outchans, rate, sys_soundin, sys_soundout,
-                blksize, sys_advance_samples/blksize, callback,
-                    (naudiooutdev > 0 ? audioindev[0] : 0),
-                        (naudiooutdev > 0 ? audiooutdev[0] : 0));
-        }
-else
-#endif
-#ifdef USEAPI_JACK
-        if (sys_audioapi == API_JACK) 
-            jack_open_audio((nrealindev > 0 ? realinchans[0] : 0),
-                (nrealoutdev > 0 ? realoutchans[0] : 0), rate);
-
-        else
-#endif    
-#ifdef USEAPI_OSS
-        if (sys_audioapi == API_OSS)
-            oss_open_audio(nrealindev, realindev, nrealindev, realinchans,
-                nrealoutdev, realoutdev, nrealoutdev, realoutchans, rate);
-        else
-#endif
-#ifdef USEAPI_ALSA
-            /* for alsa, only one device is supported; it may
-            be open for both input and output. */
-        if (sys_audioapi == API_ALSA)
-            alsa_open_audio(nrealindev, audioindev, nrealindev, realinchans,
-                nrealoutdev, audiooutdev, nrealoutdev, realoutchans, rate);
-        else 
-#endif
-#ifdef USEAPI_MMIO
-        if (sys_audioapi == API_MMIO)
-            mmio_open_audio(nrealindev, audioindev, nrealindev, realinchans,
-                nrealoutdev, audiooutdev, nrealoutdev, realoutchans, rate);
-        else
-#endif
-            post("unknown audio API specified");
-    }
-    sys_save_audio_params(naudioindev, audioindev, chindev,
-        naudiooutdev, audiooutdev, choutdev, sys_dacsr, advance, callback);
-    if (sys_inchannels == 0 && sys_outchannels == 0)
-        enable = 0;
-    audio_state = enable;
-    sys_vgui("set pd_whichapi %d\n",  (audio_isopen() ? sys_audioapi : 0));
-    sched_set_using_dacs(enable);
+    sys_save_audio_params(nrealindev, realindev, realinchans,
+        nrealoutdev, realoutdev, realoutchans, sys_dacsr, advance, callback);
 }
 
 void sys_close_audio(void)
@@ -417,6 +365,7 @@ void sys_close_audio(void)
 #endif
         post("sys_close_audio: unknown API %d", sys_audioapi);
     sys_inchannels = sys_outchannels = 0;
+    sched_set_using_audio(SCHED_AUDIO_NONE);
 }
 
     /* open audio using whatever parameters were last used */
@@ -424,12 +373,67 @@ void sys_reopen_audio( void)
 {
     int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
     int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
-    int rate, advance, callback;
+    int rate, advance, callback, outcome = 0;
     sys_get_audio_params(&naudioindev, audioindev, chindev,
         &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
-    sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
-        naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance, 
-        callback, 1);
+    if (!naudioindev && !naudiooutdev)
+    {
+        sched_set_using_audio(SCHED_AUDIO_NONE);
+        return;
+    }
+#ifdef USEAPI_PORTAUDIO
+    if (sys_audioapi == API_PORTAUDIO)
+    {
+        int blksize = (sys_blocksize ? sys_blocksize : 64);
+        outcome = pa_open_audio((naudioindev > 0 ? chindev[0] : 0),
+        (naudiooutdev > 0 ? choutdev[0] : 0), rate, sys_soundin,
+            sys_soundout, blksize, sys_advance_samples/blksize, 
+             (naudioindev > 0 ? audioindev[0] : 0),
+              (naudiooutdev > 0 ? audiooutdev[0] : 0),
+               (callback ? sched_audio_callbackfn : 0));
+    }
+    else
+#endif
+#ifdef USEAPI_JACK
+    if (sys_audioapi == API_JACK) 
+        outcome = jack_open_audio((naudioindev > 0 ? chindev[0] : 0),
+            (naudioindev > 0 ? choutdev[0] : 0), rate);
+
+    else
+#endif    
+#ifdef USEAPI_OSS
+    if (sys_audioapi == API_OSS)
+        outcome = oss_open_audio(naudioindev, audioindev, naudioindev,
+            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+    else
+#endif
+#ifdef USEAPI_ALSA
+        /* for alsa, only one device is supported; it may
+        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);
+    else 
+#endif
+#ifdef USEAPI_MMIO
+    if (sys_audioapi == API_MMIO)
+        outcome = mmio_open_audio(naudioindev, audioindev, naudioindev,
+            chindev, naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate);
+    else
+#endif
+        post("unknown audio API specified");
+    if (outcome)    /* failed */
+    {
+        audio_state = 0;
+        sched_set_using_audio(SCHED_AUDIO_NONE);
+    }
+    else
+    {
+        audio_state = 1;
+        sched_set_using_audio(
+            (callback ? SCHED_AUDIO_CALLBACK : SCHED_AUDIO_POLL));
+    }
+    sys_vgui("set pd_whichapi %d\n",  (outcome == 0 ? sys_audioapi : 0));
 }
 
 int sys_send_dacs(void)
@@ -727,9 +731,10 @@ 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,
+    sys_set_audio_settings(nindev, newaudioindev, nindev, newaudioinchan,
         noutdev, newaudiooutdev, noutdev, newaudiooutchan,
-        newrate, newadvance, newcallback, 1);
+        newrate, newadvance, newcallback);
+    sys_reopen_audio();
 }
 
 void sys_listdevs(void )
@@ -807,7 +812,6 @@ void glob_audio_setapi(void *dummy, t_floatarg f)
     {
         sys_close_audio();
         audio_state = 0;
-        sched_set_using_dacs(0);
     }
 }
 
@@ -822,10 +826,7 @@ void sys_set_audio_state(int onoff)
     else
     {
         if (audio_isopen())
-        {
             sys_close_audio();
-            sched_set_using_dacs(0);
-        }
     }
     audio_state = onoff;
 }
diff --git a/src/s_audio_pa.c b/src/s_audio_pa.c
index 5f2af7f39..c89d463e6 100644
--- a/src/s_audio_pa.c
+++ b/src/s_audio_pa.c
@@ -23,19 +23,133 @@
 static PABLIO_Stream  *pa_stream;
 static int pa_inchans, pa_outchans;
 static float *pa_soundin, *pa_soundout;
+static t_audiocallback pa_callback;
 
 #define MAX_PA_CHANS 32
 #define MAX_SAMPLES_PER_FRAME MAX_PA_CHANS * DEFDACBLKSIZE
 
+static int pa_lowlevel_callback(const void *inputBuffer,
+    void *outputBuffer, unsigned long framesPerBuffer,
+    const PaStreamCallbackTimeInfo *outTime, PaStreamCallbackFlags myflags, 
+    void *userData)
+{
+    int i; 
+    unsigned int j;
+    float *fbuf, *fp2, *fp3, *soundiop;
+
+    if (inputBuffer != NULL)
+    {
+        fbuf = (float *)inputBuffer;
+        soundiop = pa_soundin;
+        for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
+            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
+                *soundiop++ = *fp3;
+    }
+    else memset((void *)pa_soundin, 0,
+        framesPerBuffer * pa_inchans * sizeof(float));
+    (*pa_callback)();
+    if (outputBuffer != NULL)
+    {
+        fbuf = (float *)outputBuffer;
+        soundiop = pa_soundout;
+        for (i = 0, fp2 = fbuf; i < pa_inchans; i++, fp2++)
+            for (j = 0, fp3 = fp2; j < framesPerBuffer; j++, fp3 += pa_inchans)
+                *fp3 = *soundiop;
+    }
+
+    return 0;
+}
+
+PaError pa_open_callback(double sampleRate, int inchannels, int outchannels,
+    int framesperbuf, int nbuffers, int indeviceno, int outdeviceno)
+{
+    long   bytesPerSample;
+    PaError err;
+    PABLIO_Stream *pastream;
+    long   numFrames;
+    PaStreamParameters instreamparams, outstreamparams;
+
+    if (indeviceno < 0) 
+    {
+        indeviceno = Pa_GetDefaultInputDevice();
+        fprintf(stderr, "using default input device number: %d\n", indeviceno);
+    }
+    if (outdeviceno < 0)
+    {
+        outdeviceno = Pa_GetDefaultOutputDevice();
+        fprintf(stderr, "using default output device number: %d\n", outdeviceno);
+    }
+    /* fprintf(stderr, "nchan %d, flags %d, bufs %d, framesperbuf %d\n",
+            nchannels, flags, nbuffers, framesperbuf); */
+
+    /* Allocate PABLIO_Stream structure for caller. */
+    pastream = (PABLIO_Stream *)malloc( sizeof(PABLIO_Stream));
+    if (pastream == NULL)
+        return (1);
+    memset(pastream, 0, sizeof(PABLIO_Stream));
+
+    /* Determine size of a sample. */
+    bytesPerSample = Pa_GetSampleSize(paFloat32);
+    if (bytesPerSample < 0)
+    {
+        err = (PaError) bytesPerSample;
+        goto error;
+    }
+    pastream->insamplesPerFrame = inchannels;
+    pastream->inbytesPerFrame = bytesPerSample * pastream->insamplesPerFrame;
+    pastream->outsamplesPerFrame = outchannels;
+    pastream->outbytesPerFrame = bytesPerSample * pastream->outsamplesPerFrame;
+
+    numFrames = nbuffers * framesperbuf;
+
+    instreamparams.device = indeviceno;
+    instreamparams.channelCount = inchannels;
+    instreamparams.sampleFormat = paFloat32;
+    instreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+    instreamparams.hostApiSpecificStreamInfo = 0;
+    
+    outstreamparams.device = outdeviceno;
+    outstreamparams.channelCount = outchannels;
+    outstreamparams.sampleFormat = paFloat32;
+    outstreamparams.suggestedLatency = nbuffers*framesperbuf/sampleRate;
+    outstreamparams.hostApiSpecificStreamInfo = 0;
+
+    err = Pa_OpenStream(
+              &pastream->stream,
+              (inchannels ? &instreamparams : 0),
+              (outchannels ? &outstreamparams : 0),
+              sampleRate,
+              framesperbuf,
+              paNoFlag,      /* portaudio will clip for us */
+              pa_lowlevel_callback,
+              pastream);
+    if (err != paNoError)
+        goto error;
+
+    err = Pa_StartStream(pastream->stream);
+    if (err != paNoError)
+    {
+        fprintf(stderr, "Pa_StartStream failed; closing audio stream...\n");
+        CloseAudioStream( pastream );
+        goto error;
+    }
+    pa_stream = pastream;
+    return paNoError;
+error:
+    pa_stream = NULL;
+    return err;
+}
+
 int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
-    t_sample *soundout, int framesperbuf, int nbuffers, int callback,
-    int indeviceno, int outdeviceno)
+    t_sample *soundout, int framesperbuf, int nbuffers,
+    int indeviceno, int outdeviceno, t_audiocallback callbackfn)
 {
     PaError err;
     static int initialized;
     int j, devno, pa_indev = 0, pa_outdev = 0;
-
-    if (callback)
+    
+    pa_callback = callbackfn;
+    if (callbackfn)
         fprintf(stderr, "callback enabled\n");
     if (!initialized)
     {
@@ -103,26 +217,34 @@ int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
         post("output device %d, channels %d", pa_outdev, outchans);
         post("framesperbuf %d, nbufs %d", framesperbuf, nbuffers);
     }
-    if (inchans || outchans)
+    pa_inchans = inchans;
+    pa_outchans = outchans;
+    pa_soundin = soundin;
+    pa_soundout = soundout;
+    if (! inchans && !outchans)
+        return(0);
+    if (callbackfn)
+    {
+        pa_callback = callbackfn;
+        err = pa_open_callback(rate, inchans, outchans,
+            framesperbuf, nbuffers, pa_indev, pa_outdev);
+    }
+    else
+    {
         err = OpenAudioStream( &pa_stream, rate, paFloat32,
             inchans, outchans, framesperbuf, nbuffers,
                 pa_indev, pa_outdev);
-    else err = 0;
+    }
     if ( err != paNoError ) 
     {
-        fprintf( stderr, "Error number %d occured opening portaudio stream\n",
+        fprintf(stderr, "Error number %d opening portaudio stream\n",
             err); 
         fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
         Pa_Terminate();
-        sys_inchannels = sys_outchannels = 0;
         return (1);
     }
     else if (sys_verbose)
         post("... opened OK.");
-    pa_inchans = inchans;
-    pa_outchans = outchans;
-    pa_soundin = soundin;
-    pa_soundout = soundout;
     return (0);
 }
 
diff --git a/src/s_file.c b/src/s_file.c
index dcf54b49f..c81d423b8 100644
--- a/src/s_file.c
+++ b/src/s_file.c
@@ -339,9 +339,9 @@ void sys_loadpreferences( void)
         sscanf(prefbuf, "%d", &advance);
     if (sys_getpreference("callback", prefbuf, MAXPDSTRING))
         sscanf(prefbuf, "%d", &callback);
-    sys_open_audio(naudioindev, audioindev, naudioindev, chindev,
+    sys_set_audio_settings(naudioindev, audioindev, naudioindev, chindev,
         naudiooutdev, audiooutdev, naudiooutdev, choutdev, rate, advance,
-        callback, 0);
+        callback);
         
         /* load MIDI preferences */
         /* JMZ/MB: brackets for initializing */
diff --git a/src/s_main.c b/src/s_main.c
index 0224923e8..ded67c886 100644
--- a/src/s_main.c
+++ b/src/s_main.c
@@ -31,7 +31,7 @@ int sys_argparse(int argc, char **argv);
 void sys_findprogdir(char *progname);
 int sys_startgui(const char *guipath);
 int sys_rcfile(void);
-int m_scheduler(void);
+int m_mainloop(void);
 void sys_addhelppath(char *p);
 #ifdef USEAPI_ALSA
 void alsa_adddev(char *name);
@@ -71,7 +71,7 @@ char sys_extraflagsstring[MAXPDSTRING];
 
 
     /* here the "-1" counts signify that the corresponding vector hasn't been
-    specified in command line arguments; sys_open_audio will detect this
+    specified in command line arguments; sys_set_audio_settings will detect it
     and fill things in. */
 static int sys_nsoundin = -1;
 static int sys_nsoundout = -1;
@@ -314,7 +314,7 @@ int sys_main(int argc, char **argv)
         sys_reopen_midi();
         sys_reopen_audio();
             /* run scheduler until it quits */
-        return (m_scheduler());
+        return (m_mainloop());
     }
 }
 
@@ -989,9 +989,9 @@ static void sys_afterargparse(void)
         rate = sys_main_srate;
     if (sys_main_callback)
         callback = sys_main_callback;
-    sys_open_audio(naudioindev, audioindev, nchindev, chindev,
+    sys_set_audio_settings(naudioindev, audioindev, nchindev, chindev,
         naudiooutdev, audiooutdev, nchoutdev, choutdev, rate, advance, 
-        callback, 0);
+        callback);
     sys_open_midi(nmidiindev, midiindev, nmidioutdev, midioutdev, 0);
 }
 
diff --git a/src/s_stuff.h b/src/s_stuff.h
index 8320558da..c4c26928e 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -71,10 +71,10 @@ extern int sys_blocksize;       /* audio I/O block size in sample frames */
 extern float sys_dacsr;
 extern int sys_schedadvance;
 extern int sys_sleepgrain;
-void sys_open_audio(int naudioindev, int *audioindev,
+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, int enable);
+    int srate, int advance, int callback);
 void sys_reopen_audio( void);
 void sys_close_audio(void);
 
@@ -139,7 +139,11 @@ EXTERN void sys_log_error(int type);
 #define ERR_DACSLEPT 2
 #define ERR_RESYNC 3
 #define ERR_DATALATE 4
-void sched_set_using_dacs(int flag);
+
+#define SCHED_AUDIO_NONE 0
+#define SCHED_AUDIO_POLL 1 
+#define SCHED_AUDIO_CALLBACK 2
+void sched_set_using_audio(int flag);
 
 /* s_inter.c */
 
@@ -205,9 +209,11 @@ void sys_setvirtualalarm( void);
 #define DEFAULTADVANCE 50
 #endif
 
+typedef void (*t_audiocallback)(vid);
+
 int pa_open_audio(int inchans, int outchans, int rate, t_sample *soundin,
-    t_sample *soundout, int framesperbuf, int nbuffers, int callback,
-    int indeviceno, int outdeviceno);
+    t_sample *soundout, int framesperbuf, int nbuffers,
+    int indeviceno, int outdeviceno, t_audiocallback callback);
 void pa_close_audio(void);
 int pa_send_dacs(void);
 void sys_reportidle(void);
-- 
GitLab