summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/m_sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/m_sched.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/m_sched.c580
1 files changed, 0 insertions, 580 deletions
diff --git a/apps/plugins/pdbox/PDa/src/m_sched.c b/apps/plugins/pdbox/PDa/src/m_sched.c
index f40f0ff..9d3bed8 100644
--- a/apps/plugins/pdbox/PDa/src/m_sched.c
+++ b/apps/plugins/pdbox/PDa/src/m_sched.c
@@ -579,584 +579,4 @@ void sys_exit(void)
{
sys_quit = 1;
}
-/* Copyright (c) 1997-1999 Miller Puckette.
-* For information on usage and redistribution, and for a DISCLAIMER OF ALL
-* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
-
-/* scheduling stuff */
-
-#include "m_pd.h"
-#include "m_imp.h"
-#include "s_stuff.h"
-
- /* LATER consider making this variable. It's now the LCM of all sample
- rates we expect to see: 32000, 44100, 48000, 88200, 96000. */
-#define TIMEUNITPERSEC (32.*441000.)
-
-
-/* T.Grill - enable PD global thread locking - sys_lock, sys_unlock, sys_trylock functions */
-#define THREAD_LOCKING
-#include "pthread.h"
-
-
-static int sys_quit;
-static t_time sys_time;
-static t_time sys_time_per_msec = TIMEUNITPERSEC / 1000.;
-
-int sys_schedblocksize = DEFDACBLKSIZE;
-int sys_usecsincelastsleep(void);
-int sys_sleepgrain;
-
-typedef void (*t_clockmethod)(void *client);
-
-struct _clock
-{
- t_time c_settime;
- void *c_owner;
- t_clockmethod c_fn;
- struct _clock *c_next;
-};
-
-t_clock *clock_setlist;
-
-#ifdef UNIX
-#include <unistd.h>
-#endif
-
-t_clock *clock_new(void *owner, t_method fn)
-{
- t_clock *x = (t_clock *)getbytes(sizeof *x);
- x->c_settime = -1;
- x->c_owner = owner;
- x->c_fn = (t_clockmethod)fn;
- x->c_next = 0;
- return (x);
-}
-
-void clock_unset(t_clock *x)
-{
- if (x->c_settime >= 0)
- {
- if (x == clock_setlist) clock_setlist = x->c_next;
- else
- {
- t_clock *x2 = clock_setlist;
- while (x2->c_next != x) x2 = x2->c_next;
- x2->c_next = x->c_next;
- }
- x->c_settime = -1;
- }
-}
-
- /* set the clock to call back at an absolute system time */
-void clock_set(t_clock *x, t_time setticks)
-{
- if (setticks < sys_time) setticks = sys_time;
- clock_unset(x);
- x->c_settime = setticks;
- if (clock_setlist && clock_setlist->c_settime <= setticks)
- {
- t_clock *cbefore, *cafter;
- for (cbefore = clock_setlist, cafter = clock_setlist->c_next;
- cbefore; cbefore = cafter, cafter = cbefore->c_next)
- {
- if (!cafter || cafter->c_settime > setticks)
- {
- cbefore->c_next = x;
- x->c_next = cafter;
- return;
- }
- }
- }
- else x->c_next = clock_setlist, clock_setlist = x;
-}
-
- /* set the clock to call back after a delay in msec */
-void clock_delay(t_clock *x, t_time delaytime)
-{
- clock_set(x, sys_time + sys_time_per_msec * delaytime);
-}
-
- /* get current logical time. We don't specify what units this is in;
- use clock_gettimesince() to measure intervals from time of this call.
- This was previously, incorrectly named "clock_getsystime"; the old
- name is aliased to the new one in m_pd.h. */
-t_time clock_getlogicaltime( void)
-{
- return (sys_time);
-}
- /* OBSOLETE NAME */
-t_time clock_getsystime( void) { return (sys_time); }
-
- /* elapsed time in milliseconds since the given system time */
-t_time clock_gettimesince(t_time prevsystime)
-{
- return ((sys_time - prevsystime)/sys_time_per_msec);
-}
-
- /* what value the system clock will have after a delay */
-t_time clock_getsystimeafter(t_time delaytime)
-{
- return (sys_time + sys_time_per_msec * delaytime);
-}
-
-void clock_free(t_clock *x)
-{
- clock_unset(x);
- freebytes(x, sizeof *x);
-}
-
-
-/* the following routines maintain a real-execution-time histogram of the
-various phases of real-time execution. */
-
-static int sys_bin[] = {0, 2, 5, 10, 20, 30, 50, 100, 1000};
-#define NBIN (sizeof(sys_bin)/sizeof(*sys_bin))
-#define NHIST 10
-static int sys_histogram[NHIST][NBIN];
-static t_time sys_histtime;
-static int sched_diddsp, sched_didpoll, sched_didnothing;
-
-static void sys_clearhist( void)
-{
- unsigned int i, j;
- for (i = 0; i < NHIST; i++)
- for (j = 0; j < NBIN; j++) sys_histogram[i][j] = 0;
- sys_histtime = sys_getrealtime();
- sched_diddsp = sched_didpoll = sched_didnothing = 0;
-}
-
-void sys_printhist( void)
-{
- unsigned int i, j;
- for (i = 0; i < NHIST; i++)
- {
- int doit = 0;
- for (j = 0; j < NBIN; j++) if (sys_histogram[i][j]) doit = 1;
- if (doit)
- {
- post("%2d %8d %8d %8d %8d %8d %8d %8d %8d", i,
- sys_histogram[i][0],
- sys_histogram[i][1],
- sys_histogram[i][2],
- sys_histogram[i][3],
- sys_histogram[i][4],
- sys_histogram[i][5],
- sys_histogram[i][6],
- sys_histogram[i][7]);
- }
- }
- post("dsp %d, pollgui %d, nothing %d",
- sched_diddsp, sched_didpoll, sched_didnothing);
-}
-
-static int sys_histphase;
-
-int sys_addhist(int phase)
-{
-#ifndef FIXEDPOINT
- int i, j, phasewas = sys_histphase;
- t_time newtime = sys_getrealtime();
- int msec = (newtime - sys_histtime) * 1000.;
- for (j = NBIN-1; j >= 0; j--)
- {
- if (msec >= sys_bin[j])
- {
- sys_histogram[phasewas][j]++;
- break;
- }
- }
- sys_histtime = newtime;
- sys_histphase = phase;
- return (phasewas);
-#else
- return 0;
-#endif
-}
-
-#define NRESYNC 20
-
-typedef struct _resync
-{
- int r_ntick;
- int r_error;
-} t_resync;
-
-static int oss_resyncphase = 0;
-static int oss_nresync = 0;
-static t_resync oss_resync[NRESYNC];
-
-
-static char *(oss_errornames[]) = {
-"unknown",
-"ADC blocked",
-"DAC blocked",
-"A/D/A sync",
-"data late"
-};
-
-void glob_audiostatus(void)
-{
- int dev, nresync, nresyncphase, i;
- nresync = (oss_nresync >= NRESYNC ? NRESYNC : oss_nresync);
- nresyncphase = oss_resyncphase - 1;
- post("audio I/O error history:");
- post("seconds ago\terror type");
- for (i = 0; i < nresync; i++)
- {
- int errtype;
- if (nresyncphase < 0)
- nresyncphase += NRESYNC;
- errtype = oss_resync[nresyncphase].r_error;
- if (errtype < 0 || errtype > 4)
- errtype = 0;
-
- post("%9.2f\t%s",
- (sched_diddsp - oss_resync[nresyncphase].r_ntick)
- * ((double)sys_schedblocksize) / sys_dacsr,
- oss_errornames[errtype]);
- nresyncphase--;
- }
-}
-
-static int sched_diored;
-static int sched_dioredtime;
-static int sched_meterson;
-
-void sys_log_error(int type)
-{
- oss_resync[oss_resyncphase].r_ntick = sched_diddsp;
- oss_resync[oss_resyncphase].r_error = type;
- oss_nresync++;
- if (++oss_resyncphase == NRESYNC) oss_resyncphase = 0;
- if (type != ERR_NOTHING && !sched_diored &&
- (sched_diddsp >= sched_dioredtime))
- {
- sys_vgui("pdtk_pd_dio 1\n");
- sched_diored = 1;
- }
- sched_dioredtime =
- sched_diddsp + (int)(sys_dacsr /(double)sys_schedblocksize);
-}
-
-static int sched_lastinclip, sched_lastoutclip,
- sched_lastindb, sched_lastoutdb;
-
-void glob_ping(t_pd *dummy);
-
-static void sched_pollformeters( void)
-{
- int inclip, outclip, indb, outdb;
- static int sched_nextmeterpolltime, sched_nextpingtime;
-
- /* if there's no GUI but we're running in "realtime", here is
- where we arrange to ping the watchdog every 2 seconds. */
-#ifdef __linux__
- if (sys_nogui && sys_hipriority && (sched_diddsp - sched_nextpingtime > 0))
- {
- glob_ping(0);
- /* ping every 2 seconds */
- sched_nextpingtime = sched_diddsp +
- (2* sys_dacsr) /(int)sys_schedblocksize;
- }
-#endif
-
- if (sched_diddsp - sched_nextmeterpolltime < 0)
- return;
- if (sched_diored && (sched_diddsp - sched_dioredtime > 0))
- {
- sys_vgui("pdtk_pd_dio 0\n");
- sched_diored = 0;
- }
- if (sched_meterson)
- {
- float inmax, outmax;
- sys_getmeters(&inmax, &outmax);
- indb = 0.5 + rmstodb(inmax);
- outdb = 0.5 + rmstodb(outmax);
- inclip = (inmax > 0.999);
- outclip = (outmax >= 1.0);
- }
- else
- {
- indb = outdb = 0;
- inclip = outclip = 0;
- }
- if (inclip != sched_lastinclip || outclip != sched_lastoutclip
- || indb != sched_lastindb || outdb != sched_lastoutdb)
- {
- sys_vgui("pdtk_pd_meters %d %d %d %d\n", indb, outdb, inclip, outclip);
- sched_lastinclip = inclip;
- sched_lastoutclip = outclip;
- sched_lastindb = indb;
- sched_lastoutdb = outdb;
- }
- sched_nextmeterpolltime =
- sched_diddsp + (int)(sys_dacsr /(double)sys_schedblocksize);
-}
-
-void glob_meters(void *dummy, float f)
-{
- if (f == 0)
- sys_getmeters(0, 0);
- sched_meterson = (f != 0);
- sched_lastinclip = sched_lastoutclip = sched_lastindb = sched_lastoutdb =
- -1;
-}
-
-#if 0
-void glob_foo(void *dummy, t_symbol *s, int argc, t_atom *argv)
-{
- if (argc) sys_clearhist();
- else sys_printhist();
-}
-#endif
-
-void dsp_tick(void);
-
-static int sched_usedacs = 1;
-static t_time sched_referencerealtime, sched_referencelogicaltime;
-static t_time sys_time_per_dsp_tick;
-
-void sched_set_using_dacs(int flag)
-{
- sched_usedacs = flag;
- if (!flag)
- {
- sched_referencerealtime = sys_getrealtime();
- sched_referencelogicaltime = clock_getlogicaltime();
- post("schedsetuding");
- }
- sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
- ((double)sys_schedblocksize) / sys_dacsr;
-}
-
- /* take the scheduler forward one DSP tick, also handling clock timeouts */
-static void sched_tick(t_time next_sys_time)
-{
- int countdown = 5000;
- while (clock_setlist && clock_setlist->c_settime < next_sys_time)
- {
- t_clock *c = clock_setlist;
- sys_time = c->c_settime;
- clock_unset(clock_setlist);
- outlet_setstacklim();
- (*c->c_fn)(c->c_owner);
- if (!countdown--)
- {
- countdown = 5000;
- sys_pollgui();
- }
- if (sys_quit)
- return;
- }
- sys_time = next_sys_time;
- dsp_tick();
- sched_diddsp++;
-}
-
-/*
-Here is Pd's "main loop." This routine dispatches clock timeouts and DSP
-"ticks" deterministically, and polls for input from MIDI and the GUI. If
-we're left idle we also poll for graphics updates; but these are considered
-lower priority than the rest.
-
-The time source is normally the audio I/O subsystem via the "sys_send_dacs()"
-call. This call returns true if samples were transferred; false means that
-the audio I/O system is still busy with previous transfers.
-*/
-
-void sys_pollmidiqueue( void);
-void sys_initmidiqueue( void);
-
-int m_scheduler_pda( void)
-{
- int idlecount = 0;
- sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
- ((double)sys_schedblocksize) / sys_dacsr;
-
-
- sys_clearhist();
- if (sys_sleepgrain < 1000)
- sys_sleepgrain = sys_schedadvance/4;
- if (sys_sleepgrain < 100)
- sys_sleepgrain = 100;
- else if (sys_sleepgrain > 5000)
- sys_sleepgrain = 5000;
- sys_initmidiqueue();
- while (!sys_quit)
- {
- int didsomething = 0;
- int timeforward;
-
- sys_addhist(0);
- waitfortick:
- if (sched_usedacs)
- {
- timeforward = sys_send_dacs();
- sys_pollgui();
- }
- else {
- if ((sys_getrealtime() - sched_referencerealtime)
- > (t_time)clock_gettimesince(sched_referencelogicaltime)*1000)
- timeforward = SENDDACS_YES;
- else timeforward = SENDDACS_NO;
- if (timeforward == SENDDACS_YES)
- sys_microsleep(sys_sleepgrain);
- }
- if (timeforward != SENDDACS_NO) {
- sched_tick(sys_time + sys_time_per_dsp_tick);
- }
- }
- return 0;
-}
-
-
-int m_scheduler( void)
-{
- int idlecount = 0;
- sys_time_per_dsp_tick = (TIMEUNITPERSEC) *
- ((double)sys_schedblocksize) / sys_dacsr;
-
-#ifdef THREAD_LOCKING
- /* T.Grill - lock mutex */
- sys_lock();
-#endif
- sys_clearhist();
- if (sys_sleepgrain < 1000)
- sys_sleepgrain = sys_schedadvance/4;
- if (sys_sleepgrain < 100)
- sys_sleepgrain = 100;
- else if (sys_sleepgrain > 5000)
- sys_sleepgrain = 5000;
- sys_initmidiqueue();
- while (!sys_quit)
- {
- int didsomething = 0;
- int timeforward;
-
- sys_addhist(0);
- waitfortick:
- if (sched_usedacs)
- {
- timeforward = sys_send_dacs();
-
- /* if dacs remain "idle" for 1 sec, they're hung up. */
- if (timeforward != 0)
- idlecount = 0;
- else
- {
- idlecount++;
- if (!(idlecount & 31))
- {
- static t_time idletime;
- /* on 32nd idle, start a clock watch; every
- 32 ensuing idles, check it */
- if (idlecount == 32)
- idletime = sys_getrealtime();
- else if (sys_getrealtime() - idletime > 1.)
- {
- post("audio I/O stuck... closing audio\n");
- sys_close_audio();
- sched_set_using_dacs(0);
- goto waitfortick;
- }
- }
- }
- }
- else
- {
- if (1000. * (sys_getrealtime() - sched_referencerealtime)
- > clock_gettimesince(sched_referencelogicaltime))
- timeforward = SENDDACS_YES;
- else timeforward = SENDDACS_NO;
- }
- sys_setmiditimediff(0, 1e-6 * sys_schedadvance);
- sys_addhist(1);
- if (timeforward != SENDDACS_NO)
- sched_tick(sys_time + sys_time_per_dsp_tick);
- if (timeforward == SENDDACS_YES)
- didsomething = 1;
-
- sys_addhist(2);
- // sys_pollmidiqueue();
- if (sys_pollgui())
- {
- if (!didsomething)
- sched_didpoll++;
- didsomething = 1;
- }
- sys_addhist(3);
- /* test for idle; if so, do graphics updates. */
- if (!didsomething)
- {
- sched_pollformeters();
- sys_reportidle();
-
-#ifdef THREAD_LOCKING
- /* T.Grill - enter idle phase -> unlock thread lock */
- sys_unlock();
-#endif
- if (timeforward != SENDDACS_SLEPT)
- sys_microsleep(sys_sleepgrain);
-#ifdef THREAD_LOCKING
- /* T.Grill - leave idle phase -> lock thread lock */
- sys_lock();
-#endif
-
- sys_addhist(5);
- sched_didnothing++;
-
- }
- }
-
-#ifdef THREAD_LOCKING
- /* T.Grill - done */
- sys_unlock();
-#endif
-
- return (0);
-}
-
-
-/* ------------ thread locking ------------------- */
-/* added by Thomas Grill */
-
-#ifdef THREAD_LOCKING
-static pthread_mutex_t sys_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-void sys_lock(void)
-{
- pthread_mutex_lock(&sys_mutex);
-}
-
-void sys_unlock(void)
-{
- pthread_mutex_unlock(&sys_mutex);
-}
-
-int sys_trylock(void)
-{
- return pthread_mutex_trylock(&sys_mutex);
-}
-
-#else
-
-void sys_lock(void) {}
-void sys_unlock(void) {}
-int sys_trylock(void) {}
-
-#endif
-
-
-/* ------------ soft quit ------------------- */
-/* added by Thomas Grill -
- just set the quit flag for the scheduler loop
- this is useful for applications using the PD shared library to signal the scheduler to terminate
-*/
-
-void sys_exit(void)
-{
- sys_quit = 1;
-}