This is sunplay.c in view mode; [Download] [Up]
#include <config.h> #include <useconfig.h> #include <stdio.h> #include <math.h> #include <errno.h> #include <ctype.h> #include <fcntl.h> #include <sys/file.h> #include <sys/filio.h> #include <sys/stat.h> #include <sys/param.h> #include <signal.h> #include <stropts.h> #include <sys/ioctl.h> #include "proto.h" #ifdef HAVE_SYS_IOCCOM_H #include <sys/ioccom.h> #endif #ifdef HAVE_SYS_AUDIOIO_H #include <sys/audioio.h> #endif #ifdef HAVE_SUN_AUDIOIO_H #include <sun/audioio.h> #endif #include "l2u.h" #include "getargs.h" #include "hplay.h" #define SAMP_RATE 8000 long samp_rate = SAMP_RATE; /* Audio Parameters */ int Verbose = 0; /* verbose messages */ int Wait = 1; /* Should we hang waiting for device ? */ static int async = 1; static audio_info_t dev_info; /* audio header for device */ #ifdef AUDIO_DEV_AMD static int dev_kind = AUDIO_DEV_AMD; #endif static int dev_fd = -1; /* file descriptor for audio device */ char *dev_file = "/dev/audio"; char *Ifile; /* current filename */ static RETSIGTYPE audio_catch PROTO((int)); static RETSIGTYPE audio_catch(sig) int sig; { fprintf(stderr, "signal\n"); } static int audio_open PROTO((void)) { /* Try it quickly, first */ dev_fd = open(dev_file, O_WRONLY | O_NDELAY); if ((dev_fd < 0) && (errno == EBUSY)) { if (!Wait) { if (Verbose) fprintf(stderr, "%s: %s is busy\n", program, dev_file); exit(1); } if (Verbose) { fprintf(stderr, "%s: waiting for %s...", program, dev_file); (void) fflush(stderr); } /* Now hang until it's open */ dev_fd = open(dev_file, O_WRONLY); if (Verbose) fprintf(stderr, "%s\n", (dev_fd < 0) ? "" : "open"); } else if (dev_fd >= 0) { int flags = fcntl(dev_fd, F_GETFL, NULL); if (flags >= 0) fcntl(dev_fd, F_SETFL, flags & ~O_NDELAY); else perror("fcntl - F_GETFL"); } if (dev_fd < 0) { fprintf(stderr, "%s: error opening ", program); perror(dev_file); return 0; } else { #ifdef AUDIO_DEV_AMD /* Get the device output encoding configuration */ if (ioctl(dev_fd, AUDIO_GETDEV, &dev_kind)) { /* Old releases of SunOs don't support the ioctl, but can only be run on old machines which have AMD device... */ dev_kind = AUDIO_DEV_AMD; } #endif if (ioctl(dev_fd, AUDIO_GETINFO, &dev_info) != 0) { perror(dev_file); return 0; } } return 1; } int audio_init(argc, argv) int argc; char *argv[]; { int rate_set = 0; int use_linear = 0; int use_audio = 1; double gain = -1.0; int headphone = 2; int speaker = 2; argc = getargs("Sun Audio",argc, argv, "g", "%lg", &gain, "Gain 0 .. 0.1", "r", "%d", &rate_set, "Sample rate", "h", NULL, &headphone, "Headphones", "s", NULL, &speaker, "Speaker", "W", NULL, &Wait, "Wait till idle", "a", NULL, &use_audio, "Use audio", "L", NULL, &use_linear,"Force linear", NULL); if (help_only) return argc; if (rate_set) { samp_rate = rate_set; } if (use_audio && audio_open()) { if (!rate_set) samp_rate = dev_info.play.sample_rate; if (rate_set || use_linear) { dev_info.play.sample_rate = samp_rate; #ifdef AUDIO_ENCODING_LINEAR if (samp_rate > 8000 || use_linear) { dev_info.play.encoding = AUDIO_ENCODING_LINEAR; dev_info.play.precision = 16; } #endif if (ioctl(dev_fd, AUDIO_SETINFO, &dev_info) != 0) { perror(dev_file); close(dev_fd); dev_fd = -1; } } } if (dev_fd >= 0) { if (gain >= 0.0) { dev_info.play.gain = (unsigned) (AUDIO_MAX_GAIN * gain); if (ioctl(dev_fd, AUDIO_SETINFO, &dev_info) != 0) perror("gain"); } if (speaker != 2 || headphone != 2) { if (headphone != 2) { if (headphone) dev_info.play.port |= AUDIO_HEADPHONE; else dev_info.play.port &= ~AUDIO_HEADPHONE; } if (speaker != 2) { if (speaker) dev_info.play.port |= AUDIO_SPEAKER; else dev_info.play.port &= ~AUDIO_SPEAKER; } if (ioctl(dev_fd, AUDIO_SETINFO, &dev_info) != 0) perror("port"); } if (async) { int flag = 1; /* May need to use streams calls to send a SIGPOLL when write buffer is no longer full and use non-blocking writes, and manipluate our own buffer of unwritten data. However, at present just use FIOASYNC which means write returns as soon as it can queue the data (I think). */ signal(SIGIO, audio_catch); ioctl(dev_fd, FIOASYNC, &flag); } } return argc; } void audio_term() { /* Close audio system */ if (dev_fd >= 0) { ioctl(dev_fd, AUDIO_DRAIN, 0); close(dev_fd); dev_fd = -1; if (async) signal(SIGPOLL, SIG_DFL); } } void audio_play(n, data) int n; short *data; { if (n > 0 && dev_fd >= 0) { #ifdef AUDIO_ENCODING_LINEAR if (dev_info.play.encoding == AUDIO_ENCODING_LINEAR) { unsigned size = n * sizeof(short); if (write(dev_fd, data, n * sizeof(short)) != size) perror("write"); } else #endif if (dev_info.play.encoding == AUDIO_ENCODING_ULAW) { unsigned char *plabuf = (unsigned char *) malloc(n); if (plabuf) { int w; unsigned char *p = plabuf; unsigned char *e = p + n; while (p < e) { *p++ = short2ulaw(*data++); } p = plabuf; while ((w = write(dev_fd, p, n)) != n) { if (w == -1) { fprintf(stderr, "%d,%s:%d\n", errno, __FILE__, __LINE__); perror("audio"); abort(); } else { fprintf(stderr, "Writing %u, only wrote %u\n", n, w); p += w; n -= w; } } free(plabuf); } else { fprintf(stderr, "%s : No memory for ulaw data\n", program); } } } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.