*** linux_a.c.orig Mon May 20 17:09:46 1996 --- linux_a.c Tue Jun 16 21:40:17 1998 *************** *** 71,82 **** then 8-bit unsigned if it fails. If you have a sound device that can't handle either, let me know. */ static int open_output(void) { int fd, tmp, i, warnings=0; /* Open the audio device */ ! fd=open(dpm.name, O_RDWR | O_NDELAY); if (fd<0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", --- 71,85 ---- then 8-bit unsigned if it fails. If you have a sound device that can't handle either, let me know. */ + /* Flag for Luigi Rizzo new sound driver (as opposed to VoxWare) */ + static int luigi_driver = 0; + static int open_output(void) { int fd, tmp, i, warnings=0; /* Open the audio device */ ! fd=open(dpm.name, O_RDWR); if (fd<0) { ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s", *************** *** 84,89 **** --- 87,109 ---- return -1; } + /* Figure out if we're running with the Luigi driver or + the original VoxWare driver, with code based on dburr/luigi + in ports/5607. It'd be great if we could do this before + opening the audio device, but oh well... */ + #if defined(AIOGFMT) /* only defined in Luigi driver */ + { + snd_chan_param s; + int i; + i = ioctl(fd, AIOGFMT, &s); + if (i != -1) + luigi_driver = 1; + } + #endif + + ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "Using %s sound driver", + luigi_driver ? "luigi" : "VoxWare"); + /* They can't mean these */ dpm.encoding &= ~(PE_ULAW|PE_BYTESWAP); *************** *** 92,97 **** --- 112,140 ---- the other one. */ i=tmp=(dpm.encoding & PE_16BIT) ? 16 : 8; + if (luigi_driver) + { + if (dpm.encoding & PE_16BIT) { + int fmt = AFMT_S16_LE ; + + if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0 || fmt != AFMT_S16_LE) { + fmt = AFMT_U8 ; + if (ioctl(fd, SNDCTL_DSP_SETFMT, &fmt) < 0 || fmt != AFMT_U8) { + ctl->cmsg(CMSG_ERROR, VERB_NORMAL, + "%s doesn't support 16- or 8-bit sample width", + dpm.name); + close(fd); + return -1; + } + ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, + "Sample width adjusted to %d bits", tmp); + dpm.encoding ^= PE_16BIT; + warnings = 1; + } + } + } + else + { if (ioctl(fd, SNDCTL_DSP_SAMPLESIZE, &tmp)<0 || tmp!=i) { /* Try the other one */ *************** *** 109,114 **** --- 152,158 ---- dpm.encoding ^= PE_16BIT; warnings=1; } + } if (dpm.encoding & PE_16BIT) dpm.encoding |= PE_SIGNED; else *************** *** 163,168 **** --- 207,214 ---- /* Set buffer fragments (in extra_param[0]) */ tmp=AUDIO_BUFFER_BITS; + if (luigi_driver) + tmp += 2; if (!(dpm.encoding & PE_MONO)) tmp++; if (dpm.encoding & PE_16BIT) tmp++; tmp |= (dpm.extra_param[0]<<16); *************** *** 189,216 **** return warnings; } static void output_data(int32 *buf, int32 count) { if (!(dpm.encoding & PE_MONO)) count*=2; /* Stereo samples */ ! if (dpm.encoding & PE_16BIT) ! { /* Convert data to signed 16-bit PCM */ s32tos16(buf, count); ! ! /* Write the data out. Linux likes to give an EINTR if you suspend ! a program while waiting on a write, so we may need to retry. */ ! while ((-1==write(dpm.fd, buf, count * 2)) && errno==EINTR) ! ; ! } ! else ! { /* Convert to 8-bit unsigned and write out. */ s32tou8(buf, count); ! ! while ((-1==write(dpm.fd, buf, count)) && errno==EINTR) ! ; } } static void close_output(void) --- 235,269 ---- return warnings; } + /* output_data comes from Luigi's linux_a.c. This version seems to allow + for partial writes to the sound device, where as the original version + doesn't. */ static void output_data(int32 *buf, int32 count) { + char *p; + int res, l; + if (!(dpm.encoding & PE_MONO)) count*=2; /* Stereo samples */ ! if (dpm.encoding & PE_16BIT) { /* Convert data to signed 16-bit PCM */ s32tos16(buf, count); ! res = count*2; ! } else { /* Convert to 8-bit unsigned and write out. */ s32tou8(buf, count); ! res = count; ! } ! for (p = (char *) buf; res > 0; res -= l) { ! again: ! l = write(dpm.fd, p, res); ! if (l < 0) { ! if (errno == EINTR) ! goto again; ! return; } + p += l; + } } static void close_output(void)