diff options
| author | Skip Montanaro <[email protected]> | 2021-02-16 20:14:16 -0600 |
|---|---|---|
| committer | Skip Montanaro <[email protected]> | 2021-02-16 20:14:16 -0600 |
| commit | c2587c76f1b416cdbecb979e54941933246bf856 (patch) | |
| tree | bb61ee9128075ce22af4eafa232f13c2e5a07896 /src/asa.c | |
| parent | d90761a005b24018ae237bf551515772a1de656f (diff) | |
| download | python-0.9.1-patched-QoL-c2587c76f1b416cdbecb979e54941933246bf856.tar.xz python-0.9.1-patched-QoL-c2587c76f1b416cdbecb979e54941933246bf856.zip | |
starting over
Diffstat (limited to 'src/asa.c')
| -rw-r--r-- | src/asa.c | 670 |
1 files changed, 335 insertions, 335 deletions
@@ -2,12 +2,12 @@ Copyright 1991 by Stichting Mathematisch Centrum, Amsterdam, The Netherlands. - All Rights Reserved + All Rights Reserved -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in +both that copyright notice and this permission notice appear in supporting documentation, and that the names of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. @@ -23,86 +23,86 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* Asynchronous audio module for Silicon Graphics 4D/20 under IRIX 3.3 - Copyright 1990 Stichting Mathematisch Centrum, Amsterdam - Author: Guido van Rossum, <[email protected]> - Last modified: [email protected], Oct 14, 1990 - - Callers should #include "asa.h". - - This code is strongly IRIX 3.3 dependent. (Or are sproc() and - friends standard SYSV now?) - - Caution: if you put printf's in the slave for debugging, use "-lmpc" - to get the semaphore version of stdio! - - - This file contains two library layers and a test program: - - - The lower layer implements a simple asynchronous execution facility, - built directly on the system calls sproc() and [un]blockproc(). - - A slave thread sits in an infinite loop waiting for work assigned to - it by the master thread. Work is represented by a function pointer - and an argument of type void*. The function returns a void* pointer - which is transferred back to the master when it submits the next bit - of work. Submitting a NULL function pointer can be used by the - master to wait for completion of the previous work. This lower - layer could be generally useful, but is currently implemented by - static functions, for exclusive by the asynchronous audio layer. - - - The higher layer implements an asynchronous interface to the - /dev/audio device on the Silicon Graphics 4D/20. It defines the - following functions: - - int asa_init() - Required initialization function. The other functions will call - abort() when they are called before asa_init(). It creates the - slave process and returns a file descriptor for the audio - device which can be used to set the sampling rate and output - gain, etc. It prints a message to stderr and returns -1 if the - initialization failed. Calling this function more than onece is - harmless. - - void asa_start_read(char *buf, int len) - Starts an asynchronous read call on the audio device. This - waits for completion of the previous request, if any. - - void asa_start_write(char *buf, int len) - Starts an asynchronous write call on the audio device. This - waits for completion of the previous request, if any. - - int asa_poll() - Polls whether the last asynchronous read or write request is - finished. Returns -1 if no request was queued, 0 if the request - is not yet finished, and 1 if it is finished. - - int asa_wait() - Waits for completion if the last asynchronous read or write - request. It returns the result of the read or write request, - and sets the error code to the error code set by the request if - the result is -1. If no request was queued, this also returns - -1 but leaves the error code unchanged. Note: to get the error - code, don't inspect the global variable errno but call the - function oserror(). - - int asa_cancel() - Cancels the last asynchronous read or write request (by sending - the slave thread a signal for which it has a handler) then - returns its result and error code as asa_wait(). - - void asa_done() - Kills the slave process and closes the audio device. After - this, if further use of the module is required, asa_init() - should be called again. Calling this function when asa_init() - has not been called is harmless. - - - Finally, this file contains a simple test program that is compiled if - MAIN is defined (e.g., compile with cc -DMAIN). It makes a recording - and plays it back. The user must indicate begin and end of recording - and play-back by pressing the Return key. + Copyright 1990 Stichting Mathematisch Centrum, Amsterdam + Author: Guido van Rossum, <[email protected]> + Last modified: [email protected], Oct 14, 1990 + + Callers should #include "asa.h". + + This code is strongly IRIX 3.3 dependent. (Or are sproc() and + friends standard SYSV now?) + + Caution: if you put printf's in the slave for debugging, use "-lmpc" + to get the semaphore version of stdio! + + + This file contains two library layers and a test program: + + + The lower layer implements a simple asynchronous execution facility, + built directly on the system calls sproc() and [un]blockproc(). + + A slave thread sits in an infinite loop waiting for work assigned to + it by the master thread. Work is represented by a function pointer + and an argument of type void*. The function returns a void* pointer + which is transferred back to the master when it submits the next bit + of work. Submitting a NULL function pointer can be used by the + master to wait for completion of the previous work. This lower + layer could be generally useful, but is currently implemented by + static functions, for exclusive by the asynchronous audio layer. + + + The higher layer implements an asynchronous interface to the + /dev/audio device on the Silicon Graphics 4D/20. It defines the + following functions: + + int asa_init() + Required initialization function. The other functions will call + abort() when they are called before asa_init(). It creates the + slave process and returns a file descriptor for the audio + device which can be used to set the sampling rate and output + gain, etc. It prints a message to stderr and returns -1 if the + initialization failed. Calling this function more than onece is + harmless. + + void asa_start_read(char *buf, int len) + Starts an asynchronous read call on the audio device. This + waits for completion of the previous request, if any. + + void asa_start_write(char *buf, int len) + Starts an asynchronous write call on the audio device. This + waits for completion of the previous request, if any. + + int asa_poll() + Polls whether the last asynchronous read or write request is + finished. Returns -1 if no request was queued, 0 if the request + is not yet finished, and 1 if it is finished. + + int asa_wait() + Waits for completion if the last asynchronous read or write + request. It returns the result of the read or write request, + and sets the error code to the error code set by the request if + the result is -1. If no request was queued, this also returns + -1 but leaves the error code unchanged. Note: to get the error + code, don't inspect the global variable errno but call the + function oserror(). + + int asa_cancel() + Cancels the last asynchronous read or write request (by sending + the slave thread a signal for which it has a handler) then + returns its result and error code as asa_wait(). + + void asa_done() + Kills the slave process and closes the audio device. After + this, if further use of the module is required, asa_init() + should be called again. Calling this function when asa_init() + has not been called is harmless. + + + Finally, this file contains a simple test program that is compiled if + MAIN is defined (e.g., compile with cc -DMAIN). It makes a recording + and plays it back. The user must indicate begin and end of recording + and play-back by pressing the Return key. */ @@ -135,20 +135,20 @@ static void *work_result; /*ARGSUSED*/ static void handler(sig) - int sig; + int sig; { - /* Reinstate the handler (non-BSD signal semantics) */ - signal(sig, handler); + /* Reinstate the handler (non-BSD signal semantics) */ + signal(sig, handler); } /* Subroutine to fiddle signals */ static void dosig(sig) - int sig; + int sig; { - if (signal(sig, SIG_IGN) != SIG_IGN) - signal(sig, SIG_DFL); + if (signal(sig, SIG_IGN) != SIG_IGN) + signal(sig, SIG_DFL); } /* Slave control flow */ @@ -156,148 +156,148 @@ dosig(sig) /*ARGSUSED*/ static void slave(arg) - void *arg; + void *arg; { - void * (*func)(); - void *arg; - void *result; - - /* Reset signal handlers that interactive programs often catch. - The assumption is that if the master has a handler for these - signals, it will be a cleanup function. The slave must die - from these. */ - dosig(SIGHUP); - dosig(SIGQUIT); - dosig(SIGTERM); - dosig(SIGPIPE); - - /* Ignore SIGINT if caught or ignored */ - if (signal(SIGINT, SIG_IGN) == SIG_DFL) - signal(SIGINT, SIG_DFL); - - /* Let the handler install itself */ - handler(MYSIG); - - /* Set slave_pid. This is also done in the master thread, but - there is a race condition whereby the slave begins execution - before the master has assigned the result of sproc() to - slave_pid. So we set it here as well -- since this sets the - same value it should be OK. */ - slave_pid = getpid(); - - /* Set the dummy result returned by the first rendezvous */ - result = NULL; - - /* Loop forever, waiting for and executing work */ - for (;;) { - /* First rendezvous: store previous result */ - if (blockproc(slave_pid) < 0) - perror("slave: [result] blockproc(slave_pid)"); - work_result = result; - if (unblockproc(master_pid) < 0) - perror("slave: [result] unblockproc(master_pid)"); - - /* Second rendezvous: fetch work */ - if (blockproc(slave_pid) < 0) - perror("slave: [func,arg] blockproc(slave_pid)"); - func = work_func; - arg = work_arg; - if (unblockproc(master_pid) < 0) - perror("slave: [func,arg] unblockproc(master_pid)"); - - /* Execute work, computing new result */ - if (func == NULL) { - result = arg; - } - else { - result = (*func)(arg); - } - } + void * (*func)(); + void *arg; + void *result; + + /* Reset signal handlers that interactive programs often catch. + The assumption is that if the master has a handler for these + signals, it will be a cleanup function. The slave must die + from these. */ + dosig(SIGHUP); + dosig(SIGQUIT); + dosig(SIGTERM); + dosig(SIGPIPE); + + /* Ignore SIGINT if caught or ignored */ + if (signal(SIGINT, SIG_IGN) == SIG_DFL) + signal(SIGINT, SIG_DFL); + + /* Let the handler install itself */ + handler(MYSIG); + + /* Set slave_pid. This is also done in the master thread, but + there is a race condition whereby the slave begins execution + before the master has assigned the result of sproc() to + slave_pid. So we set it here as well -- since this sets the + same value it should be OK. */ + slave_pid = getpid(); + + /* Set the dummy result returned by the first rendezvous */ + result = NULL; + + /* Loop forever, waiting for and executing work */ + for (;;) { + /* First rendezvous: store previous result */ + if (blockproc(slave_pid) < 0) + perror("slave: [result] blockproc(slave_pid)"); + work_result = result; + if (unblockproc(master_pid) < 0) + perror("slave: [result] unblockproc(master_pid)"); + + /* Second rendezvous: fetch work */ + if (blockproc(slave_pid) < 0) + perror("slave: [func,arg] blockproc(slave_pid)"); + func = work_func; + arg = work_arg; + if (unblockproc(master_pid) < 0) + perror("slave: [func,arg] unblockproc(master_pid)"); + + /* Execute work, computing new result */ + if (func == NULL) { + result = arg; + } + else { + result = (*func)(arg); + } + } } static int slave_init() { - if (slave_pid > 0) - return slave_pid; - master_pid = getpid(); - - /* Reset the queue, in case this is a re-init after asa_done() */ - work_result = NULL; - work_func = NULL; - work_arg = NULL; - - /* Create the slave process, sharing all segments and properties */ - slave_pid = sproc(slave, PR_SALL, (char *)NULL); - if (slave_pid < 0) - perror("slave_init: sproc(slave, PR_SALL, NULL)"); - - /* Set up initial conditions---tricky! - Both the master and the slave start with one credit, since - both the result slot and the work/func slots are initially - free. - Note that we use setblockproccnt() for the master so a - possible indeterminate semaphore value caused by a previous - asa_done() at an unfortunate moment doesn't harm us. - */ - setblockproccnt(master_pid, 1); - unblockproc(slave_pid); - - return slave_pid; + if (slave_pid > 0) + return slave_pid; + master_pid = getpid(); + + /* Reset the queue, in case this is a re-init after asa_done() */ + work_result = NULL; + work_func = NULL; + work_arg = NULL; + + /* Create the slave process, sharing all segments and properties */ + slave_pid = sproc(slave, PR_SALL, (char *)NULL); + if (slave_pid < 0) + perror("slave_init: sproc(slave, PR_SALL, NULL)"); + + /* Set up initial conditions---tricky! + Both the master and the slave start with one credit, since + both the result slot and the work/func slots are initially + free. + Note that we use setblockproccnt() for the master so a + possible indeterminate semaphore value caused by a previous + asa_done() at an unfortunate moment doesn't harm us. + */ + setblockproccnt(master_pid, 1); + unblockproc(slave_pid); + + return slave_pid; } static void slave_done() { - if (slave_pid > 0) { - if (kill(slave_pid, SIGKILL) < 0) - perror("slave_done: kill(slave_pid, SIGKILL)"); - } - slave_pid = -1; + if (slave_pid > 0) { + if (kill(slave_pid, SIGKILL) < 0) + perror("slave_done: kill(slave_pid, SIGKILL)"); + } + slave_pid = -1; } /* Queue new work and return result of previous work */ static void * rendezvous(func, arg) - void * (*func)(); - void *arg; + void * (*func)(); + void *arg; { - void *result; - - if (slave_pid <= 0) - abort(); /* Illegal call: not initialized properly */ - - /* First rendezvous: store new work */ - if (blockproc(master_pid) < 0) - perror("rendezvous: [func,arg] blockproc(master_pid)"); - work_func = func; - work_arg = arg; - if (unblockproc(slave_pid) < 0) - perror("rendezvous: [func,arg] unblockproc(slave_pid)"); - - /* Second rendezvous: fetch previous result */ - if (blockproc(master_pid) < 0) - perror("rendezvous: [result] blockproc(master_pid)"); - result = work_result; - if (unblockproc(slave_pid) < 0) - perror("rendezvous: [result] unblockproc(slave_pid)"); - - return result; + void *result; + + if (slave_pid <= 0) + abort(); /* Illegal call: not initialized properly */ + + /* First rendezvous: store new work */ + if (blockproc(master_pid) < 0) + perror("rendezvous: [func,arg] blockproc(master_pid)"); + work_func = func; + work_arg = arg; + if (unblockproc(slave_pid) < 0) + perror("rendezvous: [func,arg] unblockproc(slave_pid)"); + + /* Second rendezvous: fetch previous result */ + if (blockproc(master_pid) < 0) + perror("rendezvous: [result] blockproc(master_pid)"); + result = work_result; + if (unblockproc(slave_pid) < 0) + perror("rendezvous: [result] unblockproc(slave_pid)"); + + return result; } /* Asynchronous audio interface (higher layer) */ -int audio_fd = -1; /* File descriptor -- not initialized yet */ +int audio_fd = -1; /* File descriptor -- not initialized yet */ static struct queue { - int func; /* 0 = read, 1 = write */ - char *buf; - int len; - int result; - int error; + int func; /* 0 = read, 1 = write */ + char *buf; + int len; + int result; + int error; } queue[2]; static int qindex = 0; @@ -305,135 +305,135 @@ static int qindex = 0; int asa_init() { - int fd; - char *p; - - if (audio_fd >= 0) - return audio_fd; - fd = open("/dev/audio", 2); - if (fd < 0) { - perror("asa_init: Can't open /dev/audio"); - return -1; - } - if (slave_init() < 0) { - perror("asa_init: Can't create slave process"); - close(fd); - return -1; - } - audio_fd = fd; - return fd; + int fd; + char *p; + + if (audio_fd >= 0) + return audio_fd; + fd = open("/dev/audio", 2); + if (fd < 0) { + perror("asa_init: Can't open /dev/audio"); + return -1; + } + if (slave_init() < 0) { + perror("asa_init: Can't create slave process"); + close(fd); + return -1; + } + audio_fd = fd; + return fd; } void asa_done() { - slave_done(); - if (audio_fd >= 0) { - if (close(audio_fd) < 0) - perror("asa_done: close(audio_fd)"); - } - audio_fd = -1; + slave_done(); + if (audio_fd >= 0) { + if (close(audio_fd) < 0) + perror("asa_done: close(audio_fd)"); + } + audio_fd = -1; } static void * runjob(arg) - void *arg; + void *arg; { - extern int errno; - struct queue *q = (struct queue *)arg; - char *buf = q->buf; - int len = q->len; - int n = 0; - - if (q->func == 0) - n = read(audio_fd, buf, len); - else - n = write(audio_fd, buf, len); - if (q->func == 0 && n >= 0) { - while (--len >= n && buf[len] == '\0') - ; - n = len+1; - } - q->result = n; - q->error = oserror(); - return arg; + extern int errno; + struct queue *q = (struct queue *)arg; + char *buf = q->buf; + int len = q->len; + int n = 0; + + if (q->func == 0) + n = read(audio_fd, buf, len); + else + n = write(audio_fd, buf, len); + if (q->func == 0 && n >= 0) { + while (--len >= n && buf[len] == '\0') + ; + n = len+1; + } + q->result = n; + q->error = oserror(); + return arg; } static void startjob(func, buf, len) - int func; - char *buf; - int len; + int func; + char *buf; + int len; { - struct queue *q; - - q = &queue[qindex]; - qindex = (qindex+1) & 1; - q->func = func; - q->buf = buf; - q->len = len; - (void) rendezvous(runjob, (void *)q); + struct queue *q; + + q = &queue[qindex]; + qindex = (qindex+1) & 1; + q->func = func; + q->buf = buf; + q->len = len; + (void) rendezvous(runjob, (void *)q); } void asa_start_read(buf, len) - char *buf; - int len; + char *buf; + int len; { - memset(buf, '\0', len); - startjob(0, buf, len); + memset(buf, '\0', len); + startjob(0, buf, len); } void asa_start_write(buf, len) - char *buf; - int len; + char *buf; + int len; { - startjob(1, buf, len); + startjob(1, buf, len); } int asa_wait() { - struct queue *q; - - q = (struct queue *) rendezvous((void*(*)())NULL, (void *)NULL); - if (q == NULL) { - setoserror(0); - return -1; /* No work was queued */ - } - setoserror(q->error); - return q->result; + struct queue *q; + + q = (struct queue *) rendezvous((void*(*)())NULL, (void *)NULL); + if (q == NULL) { + setoserror(0); + return -1; /* No work was queued */ + } + setoserror(q->error); + return q->result; } int asa_poll() { - int err; - - err = prctl(PR_ISBLOCKED, slave_pid); - if (err < 0) { - perror("prctl(PR_ISBLOCKED, slave_pid)"); - return -1; - } - else if (err == 0) - return 0; - else if (work_result == NULL) { - setoserror(0); - return -1; - } - else - return 1; + int err; + + err = prctl(PR_ISBLOCKED, slave_pid); + if (err < 0) { + perror("prctl(PR_ISBLOCKED, slave_pid)"); + return -1; + } + else if (err == 0) + return 0; + else if (work_result == NULL) { + setoserror(0); + return -1; + } + else + return 1; } int asa_cancel() { - int result; - - kill(slave_pid, MYSIG); - result = asa_wait(); - return result; + int result; + + kill(slave_pid, MYSIG); + result = asa_wait(); + return result; } @@ -445,50 +445,50 @@ asa_cancel() main() { - static char buf[10*16*1024]; /* 10 seconds of sound at 16K/sec */ - int n; - int afd; - - if ((afd = asa_init()) < 0) - exit(1); - ioctl(afd, AUDIOCSETRATE, 3); - ioctl(afd, AUDIOCSETOUTGAIN, 0); - printf("Poll returns %d\n", asa_poll()); - go("Hit enter to start recording:\n"); - asa_start_read(buf, sizeof buf); - go("Hit enter to stop recording:\n"); - /*printf("Poll returns %d\n", asa_poll());*/ - n = asa_cancel(); - if (n < 0) - perror("Read failed"); - else { - printf("Got %d bytes\n", n); - printf("Poll returns %d\n", asa_poll()); - go("Hit enter to start playing:\n"); - ioctl(afd, AUDIOCSETOUTGAIN, 50); - asa_start_write(buf, n); - go("Hit enter to stop playing:\n"); - printf("Poll returns %d\n", asa_poll()); - n = asa_cancel(); - if (n < 0) - perror("Write failed"); - else - printf("Stopped at %d bytes\n", n); - } - ioctl(afd, AUDIOCSETOUTGAIN, 0); - asa_done(); - exit(n < 0 ? 1 : 0); + static char buf[10*16*1024]; /* 10 seconds of sound at 16K/sec */ + int n; + int afd; + + if ((afd = asa_init()) < 0) + exit(1); + ioctl(afd, AUDIOCSETRATE, 3); + ioctl(afd, AUDIOCSETOUTGAIN, 0); + printf("Poll returns %d\n", asa_poll()); + go("Hit enter to start recording:\n"); + asa_start_read(buf, sizeof buf); + go("Hit enter to stop recording:\n"); + /*printf("Poll returns %d\n", asa_poll());*/ + n = asa_cancel(); + if (n < 0) + perror("Read failed"); + else { + printf("Got %d bytes\n", n); + printf("Poll returns %d\n", asa_poll()); + go("Hit enter to start playing:\n"); + ioctl(afd, AUDIOCSETOUTGAIN, 50); + asa_start_write(buf, n); + go("Hit enter to stop playing:\n"); + printf("Poll returns %d\n", asa_poll()); + n = asa_cancel(); + if (n < 0) + perror("Write failed"); + else + printf("Stopped at %d bytes\n", n); + } + ioctl(afd, AUDIOCSETOUTGAIN, 0); + asa_done(); + exit(n < 0 ? 1 : 0); } go(str) - char *str; + char *str; { - char line[100]; - - sleep(1); - fputs(str, stdout); - fflush(stdout); - fgets(line, sizeof line, stdin); + char line[100]; + + sleep(1); + fputs(str, stdout); + fflush(stdout); + fgets(line, sizeof line, stdin); } #endif /* MAIN */ |
