openbsd-ports/audio/timidity/patches/patch-linux_a_c
espie 5173f3bd1d /dev/dsp is linux
Don't open audio R/W, it's stupid.
2001-07-05 10:50:30 +00:00

175 lines
4.4 KiB
Plaintext

$OpenBSD: patch-linux_a_c,v 1.2 2001/07/05 10:50:30 espie Exp $
--- linux_a.c.orig Mon May 20 15:09:46 1996
+++ linux_a.c Thu Jul 5 12:49:08 2001
@@ -37,6 +37,11 @@
#include <machine/soundcard.h>
#endif
+#ifdef __OpenBSD__
+#include <sys/ioctl.h>
+#include <soundcard.h>
+#endif
+
#include "config.h"
#include "output.h"
#include "controls.h"
@@ -56,7 +61,7 @@ PlayMode dpm = {
-1,
{0}, /* default: get all the buffer fragments you can */
"Linux dsp device", 'd',
- "/dev/dsp",
+ "/dev/audio",
open_output,
close_output,
output_data,
@@ -71,12 +76,15 @@ PlayMode dpm = {
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 luigi_driver = 0;
+
static int open_output(void)
{
int fd, tmp, i, warnings=0;
/* Open the audio device */
- fd=open(dpm.name, O_RDWR | O_NDELAY);
+ fd=open(dpm.name, O_WRONLY);
if (fd<0)
{
ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
@@ -84,6 +92,23 @@ static int open_output(void)
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 defined (AIOGFMT)
+
+ 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,6 +117,29 @@ static int open_output(void)
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,6 +157,7 @@ static int open_output(void)
dpm.encoding ^= PE_16BIT;
warnings=1;
}
+ }
if (dpm.encoding & PE_16BIT)
dpm.encoding |= PE_SIGNED;
else
@@ -163,6 +212,8 @@ static int open_output(void)
/* 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,28 +240,35 @@ static int open_output(void)
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)
- {
+ 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
- {
+ res = count*2;
+ } else {
/* Convert to 8-bit unsigned and write out. */
s32tou8(buf, count);
-
- while ((-1==write(dpm.fd, buf, count)) && errno==EINTR)
- ;
+ 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)
@@ -220,10 +278,10 @@ static void close_output(void)
static void flush_output(void)
{
- ioctl(dpm.fd, SNDCTL_DSP_SYNC);
+ ioctl(dpm.fd, SNDCTL_DSP_SYNC,0);
}
static void purge_output(void)
{
- ioctl(dpm.fd, SNDCTL_DSP_RESET);
+ ioctl(dpm.fd, SNDCTL_DSP_RESET,0);
}