[Openal-devel] [Fwd: Patch for ALSA, aRts and ESD backends on Linux]
Marco Ziech
mmz@gmx.net
Sat, 29 May 2004 15:18:56 +0200
This is a multi-part message in MIME format.
--------------030005020201010508000606
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit
Somehow the message did not make it to mailing list. Maybe because I
first sent the message and then subscribed to the list.
-------- Original-Nachricht --------
Betreff: Patch for ALSA, aRts and ESD backends on Linux
Datum: Mon, 24 May 2004 00:23:21 +0200
Von: Marco Ziech <mmz@gmx.net>
An: openal-devel@opensource.creative.com
Hey,
I had these changes for the ALSA, aRts and ESD backends laying around on
my disk for some weeks now. As I was (and still am) packed with a lot of
work I did not manage to send them in earlier. So, what have I done:
I have added dlopen support to the aRts and the ESD backend. Basically,
I just ported Ryan Gorden's dlopen implementation from the alsa backend
to these both backends. However, I have partially rewritten the aRts
backend. It has not become faster but at least code looks a bit cleaner
now. I have also added some more error messages to the dlopen
implementation.
There were some bugs in alsa_blitbuffer. As far as I can remember these
even caused some trouble to me concerning clicking noises. In particular
this was because EPIPE was not handled.
Apart from that I made ALSA output non-blocking, so specifying "alsa
native esd arts" for devices leads to a working result even if artsd or
esd are running. Maybe this would be a good default configuration as
OpenAL should always guess the best backend, this way.
-Marco
--------------030005020201010508000606
Content-Type: text/x-patch;
name="openal-backends-mz-20040523.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="openal-backends-mz-20040523.diff"
Index: linux/configure.in
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/configure.in,v
retrieving revision 1.22
diff -u -r1.22 configure.in
--- linux/configure.in 2 Mar 2004 14:10:53 -0000 1.22
+++ linux/configure.in 23 May 2004 21:55:08 -0000
@@ -547,8 +547,12 @@
dnl enable arts sound?
AC_ARG_ENABLE(arts,
-[ --enable-arts enable arts backend [default=no]],
+[ --enable-arts enable aRts backend [default=no]],
, enable_arts=no)
+AC_ARG_ENABLE(arts,
+[ --enable-arts-dlopen dlopen aRts lib at runtime [default=no]],
+ , enable_arts_dlopen=no)
+
if test x$enable_arts = xyes; then
AC_PATH_PROG(HAVEARTS, artsc-config, , $PATH)
if test ! -z "$HAVEARTS"; then
@@ -557,9 +561,14 @@
AC_DEFINE(ARTS_SUPPORT, 1, [undocumented])
CFLAGS="$CFLAGS $ARTS_CFLAGS"
- LIBS="$LIBS $ARTS_LIBS"
OS_OBJS="$OS_OBJS \$(ARTS_OBJS)"
+ if test x$enable_arts_dlopen = xyes; then
+ AC_DEFINE(OPENAL_DLOPEN_ARTS, 1, [undocumented])
+ else
+ AC_DEFINE(OPENAL_DLOPEN_ARTS, 0, [undocumented])
+ LIBS="$LIBS $ARTS_LIBS"
+ fi
else
AC_MSG_WARN([*** artsc-config not found. No support compiled in.])
fi
@@ -570,6 +579,10 @@
AC_ARG_ENABLE(esd,
[ --enable-esd enable esd backend [default=no]],
, enable_esd=no)
+AC_ARG_ENABLE(esd,
+[ --enable-esd-dlopen dlopen esd lib at runtime [default=no]],
+ , enable_esd_dlopen=no)
+
if test x$enable_esd = xyes; then
AC_PATH_PROG(HAVEESD, esd-config, , $PATH)
if test ! -z "$HAVEESD"; then
@@ -578,12 +591,18 @@
AC_DEFINE(ESD_SUPPORT, 1, [undocumented])
CFLAGS="$CFLAGS $ESD_CFLAGS"
- LIBS="$LIBS $ESD_LIBS"
OS_OBJS="$OS_OBJS \$(ESD_OBJS)"
# bad audiofile.h! bad!
SHADOW_WARN=no
+
+ if test x$enable_esd_dlopen = xyes; then
+ AC_DEFINE(OPENAL_DLOPEN_ESD, 1, [undocumented])
+ else
+ AC_DEFINE(OPENAL_DLOPEN_ESD, 0, [undocumented])
+ LIBS="$LIBS $ESD_LIBS"
+ fi
else
AC_MSG_WARN([*** esd-config not found. No support compiled in.])
fi
Index: linux/src/arch/alsa/alsa.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/arch/alsa/alsa.c,v
retrieving revision 1.10
diff -u -r1.10 alsa.c
--- linux/src/arch/alsa/alsa.c 2 Apr 2004 04:24:03 -0000 1.10
+++ linux/src/arch/alsa/alsa.c 23 May 2004 21:55:08 -0000
@@ -76,14 +76,25 @@
static int openal_load_alsa_library(void)
{
+ char * error = NULL;
+
if (alsa_lib_handle != NULL)
return 1; /* already loaded. */
#if OPENAL_DLOPEN_ALSA
- #define OPENAL_LOAD_ALSA_SYMBOL(x) if ((p##x = dlsym(alsa_lib_handle, #x)) == NULL) { return 0; }
+ #define OPENAL_LOAD_ALSA_SYMBOL(x) p##x = dlsym(alsa_lib_handle, #x); \
+ error = dlerror(); \
+ if (p##x == NULL) { \
+ fprintf(stderr,"Could not resolve ALSA symbol %s: %s\n", #x, ((error!=NULL)?(error):("(null)"))); \
+ dlclose(alsa_lib_handle); alsa_lib_handle = NULL; \
+ return 0; }
+ dlerror(); /* clear error state */
alsa_lib_handle = dlopen("libasound.so.2", RTLD_LAZY | RTLD_GLOBAL);
- if (alsa_lib_handle == NULL)
+ error = dlerror();
+ if (alsa_lib_handle == NULL) {
+ fprintf(stderr,"Could not open ALSA library: %s\n",((error!=NULL)?(error):("(null)")));
return 0;
+ }
#else
#define OPENAL_LOAD_ALSA_SYMBOL(x) p##x = x;
alsa_lib_handle = (void *) 0xF00DF00D;
@@ -260,7 +271,7 @@
get_out_device_name(card_name, 256);
- err = psnd_pcm_open(&handle, card_name, SND_PCM_STREAM_PLAYBACK, 0);
+ err = psnd_pcm_open(&handle, card_name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
if(err < 0)
{
const char *serr = psnd_strerror(err);
@@ -647,9 +658,17 @@
err = psnd_pcm_resume(phandle);
} while ( err == -EAGAIN );
break;
+ case -EPIPE:
+ break;
default:
+ if (err<0) {
+ fprintf(stderr,"alsa_blitbuffer: Could not write audio data to sound device: %s\n",
+ strerror(-err));
+ break;
+ }
pdata += err * ai->framesize;
data_len -= err* ai->framesize;
+ frames -= err;
break;
}
if(err < 0)
Index: linux/src/arch/arts/arts.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/arch/arts/arts.c,v
retrieving revision 1.3
diff -u -r1.3 arts.c
--- linux/src/arch/arts/arts.c 23 May 2004 15:19:15 -0000 1.3
+++ linux/src/arch/arts/arts.c 23 May 2004 21:55:09 -0000
@@ -18,6 +18,10 @@
#include <sys/types.h>
#include <unistd.h>
+#if OPENAL_DLOPEN_ARTS
+#include <dlfcn.h>
+#endif
+
#include "al_main.h"
#include "al_debug.h"
@@ -29,58 +33,154 @@
#define DEF_SPEED _ALC_CANON_SPEED
#define DEF_SIZE _AL_DEF_BUFSIZ
#define DEF_SAMPLES (DEF_SIZE / 2)
+#define DEF_BITS 16
#define DEF_CHANNELS 2
-static struct {
+static int openal_arts_ref_count = 0;
+
+typedef struct {
arts_stream_t stream;
-} arts_info;
+} t_arts_handle;
static const char *genartskey(void);
+static int openal_load_arts_library(void);
+
+/*
+ * aRts library functions.
+ */
+static int (*parts_init)(void);
+static void (*parts_free)(void);
+static int (*parts_suspend)(void);
+static int (*parts_suspended)(void);
+static const char *(*parts_error_text)(int errorcode);
+static arts_stream_t (*parts_play_stream)(int rate, int bits, int channels, const char *name);
+static arts_stream_t (*parts_record_stream)(int rate, int bits, int channels, const char *name);
+static void (*parts_close_stream)(arts_stream_t stream);
+static int (*parts_read)(arts_stream_t stream, void *buffer, int count);
+static int (*parts_write)(arts_stream_t stream, const void *buffer, int count);
+static int (*parts_stream_set)(arts_stream_t stream, arts_parameter_t param, int value);
+static int (*parts_stream_get)(arts_stream_t stream, arts_parameter_t param);
+
+/*
+ * aRts library handle.
+ */
+static void * arts_lib_handle = NULL;
+
+static int openal_load_arts_library(void)
+{
+ char * error = NULL;
+
+ if (arts_lib_handle != NULL)
+ return 1; /* already loaded. */
+
+ #if OPENAL_DLOPEN_ARTS
+ #define OPENAL_LOAD_ARTS_SYMBOL(x) p##x = dlsym(arts_lib_handle, #x); \
+ error = dlerror(); \
+ if (p##x == NULL) { \
+ fprintf(stderr,"Could not resolve aRts symbol %s: %s\n", #x, ((error!=NULL)?(error):("(null)"))); \
+ dlclose(arts_lib_handle); arts_lib_handle = NULL; \
+ return 0; }
+ dlerror(); /* clear error state */
+ arts_lib_handle = dlopen("libartsc.so", RTLD_LAZY | RTLD_GLOBAL);
+ error = dlerror();
+ if (arts_lib_handle == NULL) {
+ fprintf(stderr,"Could not open aRts library: %s\n",((error!=NULL)?(error):("(null)")));
+ return 0;
+ }
+ #else
+ #define OPENAL_LOAD_ARTS_SYMBOL(x) p##x = x;
+ arts_lib_handle = (void *) 0xF00DF00D;
+ #endif
+
+ OPENAL_LOAD_ARTS_SYMBOL(arts_init);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_free);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_suspend);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_suspended);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_error_text);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_play_stream);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_record_stream);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_close_stream);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_read);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_write);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_stream_set);
+ OPENAL_LOAD_ARTS_SYMBOL(arts_stream_get);
+
+ return 1;
+}
void *grab_read_arts(void) {
return NULL;
}
void *grab_write_arts(void) {
- int err = arts_init();
+ int err;
+ t_arts_handle * ahandle;
- if(err < 0) {
- fprintf(stderr, "aRTs init failed: %s\n",
- arts_error_text(err));
- return NULL;
- }
+ if (!openal_load_arts_library()) {
+ return NULL;
+ }
+
+ if (!(ahandle=malloc(sizeof(t_arts_handle))))
+ return NULL;
+
+ if (openal_arts_ref_count==0) {
+ err = parts_init();
+
+ if(err < 0) {
+ fprintf(stderr, "aRTs init failed: %s\n",
+ parts_error_text(err));
+ free(ahandle);
+ return NULL;
+ }
+ }
+ openal_arts_ref_count++;
+
_alBlitBuffer = arts_blitbuffer;
+#if 1
+ ahandle->stream = NULL;
+#else
+ ahandle->stream = parts_play_stream(DEF_SPEED,
+ DEF_BITS,
+ DEF_CHANNELS,
+ genartskey());
+#endif
+
fprintf(stderr, "arts grab audio ok\n");
_alDebug(ALD_CONTEXT, __FILE__, __LINE__,
"arts grab audio ok");
- return &arts_info.stream;
+ return ahandle;
}
void arts_blitbuffer(void *handle, void *data, int bytes) {
- arts_stream_t *ap = (arts_stream_t *) handle;
+ t_arts_handle * ahandle = (t_arts_handle *) handle;
- if(handle == NULL) {
+ if ((ahandle == NULL)||(ahandle->stream == NULL)) {
return;
}
- arts_write(*ap, data, bytes);
+ parts_write(ahandle->stream, data, bytes);
return;
}
void release_arts(void *handle) {
- arts_stream_t *ap = (arts_stream_t *) handle;
+ t_arts_handle * ahandle = (t_arts_handle *) handle;
- if(handle == NULL) {
+ if ((ahandle == NULL)||(ahandle->stream == NULL)) {
return;
}
- arts_close_stream(*ap);
- arts_free();
+ openal_arts_ref_count--;
+
+ parts_close_stream(ahandle->stream);
+ free(ahandle);
+
+ if (openal_arts_ref_count==0)
+ parts_free();
return;
}
@@ -93,25 +193,43 @@
return retval;
}
-ALboolean set_write_arts(UNUSED(void *handle),
+ALboolean set_write_arts(void *handle,
ALuint *bufsiz,
ALenum *fmt,
ALuint *speed) {
- ALuint chans = _al_ALCHANNELS(*fmt);
+ t_arts_handle * ahandle = (t_arts_handle *) handle;
- arts_stream_set(arts_info.stream, ARTS_P_BUFFER_SIZE, *bufsiz);
+ if (ahandle == NULL) {
+ return AL_FALSE;
+ }
+#if 0
fprintf(stderr, "set_arts forcing speed from %d to 44100\n", *speed);
+ /* @@@ FIXME: What was this good for?! */
*speed = 44100;
+#endif
+
+ if (ahandle->stream != NULL)
+ parts_close_stream(ahandle->stream);
- /* FIXME: how do we know if this failed? */
- arts_info.stream = arts_play_stream(*speed,
+ /* According to the aRtsC library source, this function
+ * returns 0 if it fails.
+ */
+ ahandle->stream = parts_play_stream(*speed,
_al_formatbits(*fmt),
- chans,
- genartskey());
+ _al_ALCHANNELS(*fmt),
+ genartskey());
+
+ if (ahandle->stream == 0) {
+ ahandle->stream = NULL;
+ return AL_FALSE;
+ }
+
+ parts_stream_set(ahandle->stream, ARTS_P_BUFFER_SIZE, *bufsiz);
+ parts_stream_set(ahandle->stream, ARTS_P_BLOCKING, 1);
- *bufsiz = arts_stream_get(arts_info.stream, ARTS_P_BUFFER_SIZE);
+ *bufsiz = parts_stream_get(ahandle->stream, ARTS_P_BUFFER_SIZE);
return AL_TRUE;
}
Index: linux/src/arch/esd/esd.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/arch/esd/esd.c,v
retrieving revision 1.3
diff -u -r1.3 esd.c
--- linux/src/arch/esd/esd.c 20 Jun 2003 19:23:07 -0000 1.3
+++ linux/src/arch/esd/esd.c 23 May 2004 21:55:09 -0000
@@ -27,6 +27,10 @@
#include <sys/types.h>
#include <unistd.h>
+#if OPENAL_DLOPEN_ESD
+#include <dlfcn.h>
+#endif
+
#include <esd.h>
#define DEF_SPEED _ALC_CANON_SPEED
@@ -39,6 +43,58 @@
#define ESD_NAMELEN 1024
static const char *genesdkey(void);
+static int openal_load_esd_library(void);
+
+
+/*
+ * ESD library functions.
+ */
+static int (*pesd_open_sound)( const char *host );
+static int (*pesd_play_stream)( esd_format_t format, int rate,
+ const char *host, const char *name );
+static int (*pesd_standby)( int esd );
+static int (*pesd_resume)( int esd );
+static int (*pesd_close)( int esd );
+
+/*
+ * ESD library handle.
+ */
+static void * esd_lib_handle = NULL;
+
+static int openal_load_esd_library(void)
+{
+ char * error = NULL;
+
+ if (esd_lib_handle != NULL)
+ return 1; /* already loaded. */
+
+ #if OPENAL_DLOPEN_ESD
+ #define OPENAL_LOAD_ESD_SYMBOL(x) p##x = dlsym(esd_lib_handle, #x); \
+ error = dlerror(); \
+ if (p##x == NULL) { \
+ fprintf(stderr,"Could not resolve ESoundD symbol %s: %s\n", #x, ((error!=NULL)?(error):("(null)"))); \
+ dlclose(esd_lib_handle); esd_lib_handle = NULL; \
+ return 0; }
+ dlerror(); /* clear error state */
+ esd_lib_handle = dlopen("libesd.so", RTLD_LAZY | RTLD_GLOBAL);
+ error = dlerror();
+ if (esd_lib_handle == NULL) {
+ fprintf(stderr,"Could not open ESoundD library: %s\n",((error!=NULL)?(error):("(null)")));
+ return 0;
+ }
+ #else
+ #define OPENAL_LOAD_ESD_SYMBOL(x) p##x = x;
+ esd_lib_handle = (void *) 0xF00DF00D;
+ #endif
+
+ OPENAL_LOAD_ESD_SYMBOL(esd_open_sound);
+ OPENAL_LOAD_ESD_SYMBOL(esd_standby);
+ OPENAL_LOAD_ESD_SYMBOL(esd_resume);
+ OPENAL_LOAD_ESD_SYMBOL(esd_play_stream);
+ OPENAL_LOAD_ESD_SYMBOL(esd_close);
+
+ return 1;
+}
static fd_set esd_fd_set;
@@ -62,7 +118,11 @@
const char *espeaker = getenv("ESPEAKER");
int esd;
- esd = esd_open_sound(espeaker);
+ if (!openal_load_esd_library()) {
+ return NULL;
+ }
+
+ esd = pesd_open_sound(espeaker);
if(esd < 0) {
fprintf(stderr, "esd open sound failed.\n");
return NULL;
@@ -82,7 +142,7 @@
default: break;
}
- socket = esd_play_stream(fmt, DEF_SPEED, espeaker, esdkey);
+ socket = pesd_play_stream(fmt, DEF_SPEED, espeaker, esdkey);
if(socket < 0) {
fprintf(stderr, "esd play stream failed.\n");
@@ -178,7 +238,7 @@
eh = (esd_openal_info_t *) handle;
- esd_close(eh->esdhandle);
+ pesd_close(eh->esdhandle);
return;
}
@@ -201,7 +261,7 @@
eh = (esd_openal_info_t *) handle;
eh->paused = AL_TRUE;
- esd_standby(eh->esdhandle);
+ pesd_standby(eh->esdhandle);
return;
}
@@ -216,7 +276,7 @@
eh = (esd_openal_info_t *) handle;
eh->paused = AL_FALSE;
- esd_resume(eh->esdhandle);
+ pesd_resume(eh->esdhandle);
return;
}
@@ -253,7 +313,7 @@
eh->speed = *speed;
- socket = esd_play_stream(eh->fmt,
+ socket = pesd_play_stream(eh->fmt,
eh->speed,
eh->espeaker,
eh->name);
--------------030005020201010508000606--