diff --git a/README b/README index 2a23bb8393f1839bee2a5af6c52987ee54384dec..2597635cd113fb34b443b938abaca3a72dac1292 100644 --- a/README +++ b/README @@ -51,3 +51,15 @@ could be provided. The API was revised for version 0.8.0. This code is being maintained by Stan Seibert (indigo@aztec.asu.edu) and various other individuals. Please DO NOT annoy Aaron Holtzman about bugs, features, comments, etc. regarding this code. + +WORKAROUNDS + +The OSS emulation in ALSA deviates from the OSS spec by not returning +immediately from an open() call if the OSS device is already in use. +Instead, it makes the application wait until the device is available. +This is not desirable during the autodetection phase of libao, so a +workaround has been included in the source. Since the workaround +itself violates the OSS spec and causes other problems on some +platforms, it is only enabled when ALSA is detected. The workaround +can be turned on or off by passing the --enable-broken-oss or +--disable-broken-oss flag to the configure script. diff --git a/configure.in b/configure.in index 6dfc987058d5c3b13a73b43e7c42354616603350..169760fb39871e82a0c10d2ab5678488eb0f3a8b 100644 --- a/configure.in +++ b/configure.in @@ -196,7 +196,19 @@ else fi AC_SUBST(ALSA09_LIBS) +dnl Decide whether we need to enable the workaround for broken OSS APIs +dnl such as the OSS emulation in ALSA. +AC_ARG_ENABLE(broken-oss, [ --enable-broken-oss workaround for some OSS drivers (see README for details)],, +if test "x$have_alsa" = "xyes" -o "x$have_alsa09" = "xyes"; then + enable_broken_oss="yes" +fi) + +if test "x$enable_broken_oss" = "xyes"; then + AC_DEFINE(BROKEN_OSS) + AC_MSG_WARN(Broken OSS API workaround enabled. See README for details.) +fi + dnl Check for Sun audio AC_CHECK_HEADERS(sys/audioio.h) diff --git a/src/plugins/oss/ao_oss.c b/src/plugins/oss/ao_oss.c index 637b44596dbc270221524ebbc2fe8496405b8f30..9580df96d81b47896faaae1ad7cbe5d6c95f30ab 100644 --- a/src/plugins/oss/ao_oss.c +++ b/src/plugins/oss/ao_oss.c @@ -70,10 +70,11 @@ typedef struct ao_oss_internal { * *dev_path. Assumes that *dev_path does not need to be free()'ed * initially. * - * This opens the device in non-blocking mode at first in order to prevent - * deadlock caused by ALSA's OSS emulation and some OSS drivers if the - * device is already in use. If blocking is non-zero, we remove the blocking - * flag if possible so that the device can be used for actual output. + * If BROKEN_OSS is defined, this opens the device in non-blocking + * mode at first in order to prevent deadlock caused by ALSA's OSS + * emulation and some OSS drivers if the device is already in use. If + * blocking is non-zero, we remove the blocking flag if possible so + * that the device can be used for actual output. */ int _open_default_oss_device (char **dev_path, int blocking) { @@ -83,7 +84,11 @@ int _open_default_oss_device (char **dev_path, int blocking) /* default: first try the devfs path */ *dev_path = strdup("/dev/sound/dsp"); +#ifdef BROKEN_OSS fd = open(*dev_path, O_WRONLY | O_NONBLOCK); +#else + fd = open(*dev_path, O_WRONLY); +#endif /* BROKEN_OSS */ /* then try the original dsp path */ if(fd < 0) @@ -93,9 +98,14 @@ int _open_default_oss_device (char **dev_path, int blocking) dev = strdup(*dev_path); free(*dev_path); *dev_path = strdup("/dev/dsp"); +#ifdef BROKEN_OSS fd = open(*dev_path, O_WRONLY | O_NONBLOCK); +#else + fd = open(*dev_path, O_WRONLY); +#endif /* BROKEN_OSS */ } +#ifdef BROKEN_OSS /* Now have to remove the O_NONBLOCK flag if so instructed. */ if (fd > 0 && blocking) { if (fcntl(fd, F_SETFL, 0) < 0) { /* Remove O_NONBLOCK */ @@ -105,6 +115,7 @@ int _open_default_oss_device (char **dev_path, int blocking) fd = -1; } } +#endif /* BROKEN_OSS */ /* Deal with error cases */ if(fd < 0)