Commit 0df68f95 authored by Ryan C. Gordon's avatar Ryan C. Gordon

Made NAS target dynamic, so you can safely include it in shipping binaries.

--HG--
branch : SDL-1.2
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/branches/SDL-1.2%403800
parent dfa10287
...@@ -591,30 +591,62 @@ CheckNAS() ...@@ -591,30 +591,62 @@ CheckNAS()
AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]), AC_HELP_STRING([--enable-nas], [support the NAS audio API [[default=yes]]]),
, enable_nas=yes) , enable_nas=yes)
if test x$enable_audio = xyes -a x$enable_nas = xyes; then if test x$enable_audio = xyes -a x$enable_nas = xyes; then
save_LDFLAGS="$LDFLAGS" AC_CHECK_HEADER(audio/audiolib.h, have_nas_hdr=yes)
LDFLAGS="$LDFLAGS -lXt -lm" AC_CHECK_LIB(audio, AuOpenServer, have_nas_lib=yes)
AC_CHECK_HEADER(audio/audiolib.h, have_audio_hdr=yes)
AC_CHECK_LIB(audio, AuOpenServer, have_audio_lib=yes)
AC_CHECK_HEADER(nas/audiolib.h, have_nas_hdr=yes)
AC_CHECK_LIB(nas, AuOpenServer, have_nas_lib=yes)
LDFLAGS="$save_LDFLAGS"
AC_MSG_CHECKING(for NAS audio support) AC_MSG_CHECKING(for NAS audio support)
have_nas=no have_nas=no
if test x$have_audio_hdr = xyes -a x$have_audio_lib = xyes; then
if test x$have_nas_hdr = xyes -a x$have_nas_lib = xyes; then
have_nas=yes
NAS_LIBS="-laudio"
elif test -r /usr/X11R6/include/audio/audiolib.h; then
have_nas=yes have_nas=yes
NAS_LIBS="-laudio -lXt" NAS_CFLAGS="-I/usr/X11R6/include/"
elif test x$have_nas_hdr = xyes -a x$have_nas_lib = xyes; then NAS_LIBS="-L/usr/X11R6/lib -laudio -lXt"
dnl On IRIX, the NAS includes are in a different directory,
dnl and libnas must be explicitly linked in
elif test -r /usr/freeware/include/nas/audiolib.h; then
have_nas=yes have_nas=yes
NAS_LIBS="-lnas -lXt" NAS_LIBS="-lnas -lXt"
fi fi
AC_MSG_RESULT($have_nas) AC_MSG_RESULT($have_nas)
if test x$have_nas = xyes; then if test x$have_nas = xyes; then
AC_ARG_ENABLE(nas-shared,
AC_HELP_STRING([--enable-nas-shared], [dynamically load NAS audio support [[default=yes]]]),
, enable_nas_shared=yes)
if test "x`echo $NAS_LIBS | grep -- -L`" = "x"; then
if test "x`ls /lib/libaudio.so.* 2> /dev/null`" != "x"; then
NAS_LIBS="-L/lib $NAS_LIBS"
elif test "x`ls /usr/lib/libaudio.so.* 2> /dev/null`" != "x"; then
NAS_LIBS="-L/usr/lib $NAS_LIBS"
elif test "x`ls /usr/local/lib/libaudio.so.* 2> /dev/null`" != "x"; then
NAS_LIBS="-L/usr/local/lib $NAS_LIBS"
fi
fi
nas_lib_spec=`echo $NAS_LIBS | sed 's/.*-L\([[^ ]]*\).*/\1\/libaudio.so.*/'`
nas_lib=`ls -- $nas_lib_spec | sed 's/.*\/\(.*\)/\1/; q'`
echo "-- $nas_lib_spec -> $nas_lib"
if test x$have_loadso != xyes && \
test x$enable_nas_shared = xyes; then
AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic NAS loading])
fi
if test x$have_loadso = xyes && \
test x$enable_nas_shared = xyes && test x$nas_lib != x; then
AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_NAS_DYNAMIC, "$nas_lib")
else
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
fi
AC_DEFINE(SDL_AUDIO_DRIVER_NAS) AC_DEFINE(SDL_AUDIO_DRIVER_NAS)
SOURCES="$SOURCES $srcdir/src/audio/nas/*.c" SOURCES="$SOURCES $srcdir/src/audio/nas/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $NAS_CFLAGS" EXTRA_CFLAGS="$EXTRA_CFLAGS $NAS_CFLAGS"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $NAS_LIBS"
have_audio=yes have_audio=yes
fi fi
fi fi
......
...@@ -176,6 +176,7 @@ ...@@ -176,6 +176,7 @@
#undef SDL_AUDIO_DRIVER_MINT #undef SDL_AUDIO_DRIVER_MINT
#undef SDL_AUDIO_DRIVER_MMEAUDIO #undef SDL_AUDIO_DRIVER_MMEAUDIO
#undef SDL_AUDIO_DRIVER_NAS #undef SDL_AUDIO_DRIVER_NAS
#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
#undef SDL_AUDIO_DRIVER_OSS #undef SDL_AUDIO_DRIVER_OSS
#undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
#undef SDL_AUDIO_DRIVER_PAUD #undef SDL_AUDIO_DRIVER_PAUD
......
...@@ -37,11 +37,122 @@ ...@@ -37,11 +37,122 @@
#include "../SDL_audiodev_c.h" #include "../SDL_audiodev_c.h"
#include "SDL_nasaudio.h" #include "SDL_nasaudio.h"
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
#include "SDL_loadso.h"
#endif
/* The tag name used by artsc audio */ /* The tag name used by artsc audio */
#define NAS_DRIVER_NAME "nas" #define NAS_DRIVER_NAME "nas"
static struct SDL_PrivateAudioData *this2 = NULL; static struct SDL_PrivateAudioData *this2 = NULL;
static void (*NAS_AuCloseServer) (AuServer *);
static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
static void (*NAS_AuSetElements)
(AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
static void (*NAS_AuWriteElement)
(AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
static AuServer *(*NAS_AuOpenServer)
(_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
(AuServer *, AuMask, int, AuID, AuEventHandlerCallback, AuPointer);
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
static const char *nas_library = SDL_AUDIO_DRIVER_NAS_DYNAMIC;
static void *nas_handle = NULL;
static int
load_nas_sym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(nas_handle, fn);
if (*addr == NULL) {
return 0;
}
return 1;
}
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_NAS_SYM(x) \
if (!load_nas_sym(#x, (void **) (char *) &NAS_##x)) return -1
#else
#define SDL_NAS_SYM(x) NAS_##x = x
#endif
static int
load_nas_syms(void)
{
SDL_NAS_SYM(AuCloseServer);
SDL_NAS_SYM(AuNextEvent);
SDL_NAS_SYM(AuDispatchEvent);
SDL_NAS_SYM(AuCreateFlow);
SDL_NAS_SYM(AuStartFlow);
SDL_NAS_SYM(AuSetElements);
SDL_NAS_SYM(AuWriteElement);
SDL_NAS_SYM(AuOpenServer);
SDL_NAS_SYM(AuRegisterEventHandler);
return 0;
}
#undef SDL_NAS_SYM
#ifdef SDL_AUDIO_DRIVER_NAS_DYNAMIC
static void
UnloadNASLibrary(void)
{
if (nas_handle != NULL) {
SDL_UnloadObject(nas_handle);
nas_handle = NULL;
}
}
static int
LoadNASLibrary(void)
{
int retval = 0;
if (nas_handle == NULL) {
nas_handle = SDL_LoadObject(nas_library);
if (nas_handle == NULL) {
/* Copy error string so we can use it in a new SDL_SetError(). */
char *origerr = SDL_GetError();
size_t len = SDL_strlen(origerr) + 1;
char *err = (char *) alloca(len);
SDL_strlcpy(err, origerr, len);
retval = -1;
SDL_SetError("NAS: SDL_LoadObject('%s') failed: %s\n",
nas_library, err);
} else {
retval = load_nas_syms();
if (retval < 0) {
UnloadNASLibrary();
}
}
}
return retval;
}
#else
static void
UnloadNASLibrary(void)
{
}
static int
LoadNASLibrary(void)
{
load_nas_syms();
return 0;
}
#endif /* SDL_AUDIO_DRIVER_NAS_DYNAMIC */
/* Audio driver functions */ /* Audio driver functions */
static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec); static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec);
static void NAS_WaitAudio(_THIS); static void NAS_WaitAudio(_THIS);
...@@ -53,15 +164,22 @@ static void NAS_CloseAudio(_THIS); ...@@ -53,15 +164,22 @@ static void NAS_CloseAudio(_THIS);
static int Audio_Available(void) static int Audio_Available(void)
{ {
AuServer *aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); if (LoadNASLibrary() == 0) {
if (!aud) return 0; AuServer *aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (!aud) {
AuCloseServer(aud); UnloadNASLibrary();
return 1; return 0;
}
NAS_AuCloseServer(aud);
UnloadNASLibrary();
return 1;
}
return 0;
} }
static void Audio_DeleteDevice(SDL_AudioDevice *device) static void Audio_DeleteDevice(SDL_AudioDevice *device)
{ {
UnloadNASLibrary();
SDL_free(device->hidden); SDL_free(device->hidden);
SDL_free(device); SDL_free(device);
} }
...@@ -70,6 +188,10 @@ static SDL_AudioDevice *Audio_CreateDevice(int devindex) ...@@ -70,6 +188,10 @@ static SDL_AudioDevice *Audio_CreateDevice(int devindex)
{ {
SDL_AudioDevice *this; SDL_AudioDevice *this;
if (LoadNASLibrary() < 0) {
return NULL;
}
/* Initialize all variables that we clean on shutdown */ /* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
if ( this ) { if ( this ) {
...@@ -82,7 +204,7 @@ static SDL_AudioDevice *Audio_CreateDevice(int devindex) ...@@ -82,7 +204,7 @@ static SDL_AudioDevice *Audio_CreateDevice(int devindex)
if ( this ) { if ( this ) {
SDL_free(this); SDL_free(this);
} }
return(0); return NULL;
} }
SDL_memset(this->hidden, 0, (sizeof *this->hidden)); SDL_memset(this->hidden, 0, (sizeof *this->hidden));
...@@ -108,8 +230,8 @@ static void NAS_WaitAudio(_THIS) ...@@ -108,8 +230,8 @@ static void NAS_WaitAudio(_THIS)
{ {
while ( this->hidden->buf_free < this->hidden->mixlen ) { while ( this->hidden->buf_free < this->hidden->mixlen ) {
AuEvent ev; AuEvent ev;
AuNextEvent(this->hidden->aud, AuTrue, &ev); NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
AuDispatchEvent(this->hidden->aud, &ev); NAS_AuDispatchEvent(this->hidden->aud, &ev);
} }
} }
...@@ -119,13 +241,13 @@ static void NAS_PlayAudio(_THIS) ...@@ -119,13 +241,13 @@ static void NAS_PlayAudio(_THIS)
in the hope that some of them is LowWater events telling us more in the hope that some of them is LowWater events telling us more
of the buffer is free now than what we think. */ of the buffer is free now than what we think. */
AuEvent ev; AuEvent ev;
AuNextEvent(this->hidden->aud, AuTrue, &ev); NAS_AuNextEvent(this->hidden->aud, AuTrue, &ev);
AuDispatchEvent(this->hidden->aud, &ev); NAS_AuDispatchEvent(this->hidden->aud, &ev);
} }
this->hidden->buf_free -= this->hidden->mixlen; this->hidden->buf_free -= this->hidden->mixlen;
/* Write the audio data */ /* Write the audio data */
AuWriteElement(this->hidden->aud, this->hidden->flow, 0, this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL); NAS_AuWriteElement(this->hidden->aud, this->hidden->flow, 0, this->hidden->mixlen, this->hidden->mixbuf, AuFalse, NULL);
this->hidden->written += this->hidden->mixlen; this->hidden->written += this->hidden->mixlen;
...@@ -146,7 +268,7 @@ static void NAS_CloseAudio(_THIS) ...@@ -146,7 +268,7 @@ static void NAS_CloseAudio(_THIS)
this->hidden->mixbuf = NULL; this->hidden->mixbuf = NULL;
} }
if ( this->hidden->aud ) { if ( this->hidden->aud ) {
AuCloseServer(this->hidden->aud); NAS_AuCloseServer(this->hidden->aud);
this->hidden->aud = 0; this->hidden->aud = 0;
} }
} }
...@@ -211,6 +333,7 @@ event_handler(AuServer* aud, AuEvent* ev, AuEventHandlerRec* hnd) ...@@ -211,6 +333,7 @@ event_handler(AuServer* aud, AuEvent* ev, AuEventHandlerRec* hnd)
static AuDeviceID static AuDeviceID
find_device(_THIS, int nch) find_device(_THIS, int nch)
{ {
/* These "Au" things are all macros, not functions... */
int i; int i;
for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) { for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) == if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
...@@ -246,7 +369,7 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -246,7 +369,7 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec)
} }
spec->format = test_format; spec->format = test_format;
this->hidden->aud = AuOpenServer("", 0, NULL, 0, NULL, NULL); this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (this->hidden->aud == 0) if (this->hidden->aud == 0)
{ {
SDL_SetError("Couldn't open connection to NAS server"); SDL_SetError("Couldn't open connection to NAS server");
...@@ -254,8 +377,8 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -254,8 +377,8 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec)
} }
this->hidden->dev = find_device(this, spec->channels); this->hidden->dev = find_device(this, spec->channels);
if ((this->hidden->dev == AuNone) || (!(this->hidden->flow = AuCreateFlow(this->hidden->aud, NULL)))) { if ((this->hidden->dev == AuNone) || (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, NULL)))) {
AuCloseServer(this->hidden->aud); NAS_AuCloseServer(this->hidden->aud);
this->hidden->aud = 0; this->hidden->aud = 0;
SDL_SetError("Couldn't find a fitting playback device on NAS server"); SDL_SetError("Couldn't find a fitting playback device on NAS server");
return (-1); return (-1);
...@@ -273,15 +396,16 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec) ...@@ -273,15 +396,16 @@ static int NAS_OpenAudio(_THIS, SDL_AudioSpec *spec)
this2 = this->hidden; this2 = this->hidden;
/* These "Au" things without a NAS_ prefix are macros, not functions... */
AuMakeElementImportClient(elms, spec->freq, format, spec->channels, AuTrue, AuMakeElementImportClient(elms, spec->freq, format, spec->channels, AuTrue,
buffer_size, buffer_size / 4, 0, NULL); buffer_size, buffer_size / 4, 0, NULL);
AuMakeElementExportDevice(elms+1, 0, this->hidden->dev, spec->freq, AuMakeElementExportDevice(elms+1, 0, this->hidden->dev, spec->freq,
AuUnlimitedSamples, 0, NULL); AuUnlimitedSamples, 0, NULL);
AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL); NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms, NULL);
AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, this->hidden->flow, NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0, this->hidden->flow,
event_handler, (AuPointer) NULL); event_handler, (AuPointer) NULL);
AuStartFlow(this->hidden->aud, this->hidden->flow, NULL); NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
/* Allocate mixing buffer */ /* Allocate mixing buffer */
this->hidden->mixlen = spec->size; this->hidden->mixlen = spec->size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment