Added an SDL2 OpenBSD sndio(7) audio target.

--HG--
extra : rebase_source : 5ad387265cff73c1635ca4f2c3635848ba722614
This commit is contained in:
Ryan C. Gordon 2013-07-07 02:03:07 -04:00
parent fdca15860f
commit bbe065f50f
8 changed files with 460 additions and 0 deletions

View file

@ -203,6 +203,7 @@ dep_option(PULSEAUDIO_SHARED "Dynamically load PulseAudio support" ON "PULSEAU
set_option(ARTS "Support the Analog Real Time Synthesizer" ${UNIX_SYS}) set_option(ARTS "Support the Analog Real Time Synthesizer" ${UNIX_SYS})
dep_option(ARTS_SHARED "Dynamically load aRts audio support" ON "ARTS" OFF) dep_option(ARTS_SHARED "Dynamically load aRts audio support" ON "ARTS" OFF)
set_option(NAS "Support the NAS audio API" ${UNIX_SYS}) set_option(NAS "Support the NAS audio API" ${UNIX_SYS})
set_option(SNDIO "Support the sndio audio API" ${UNIX_SYS})
set_option(RPATH "Use an rpath when linking SDL" ${UNIX_SYS}) set_option(RPATH "Use an rpath when linking SDL" ${UNIX_SYS})
set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" OFF) set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" OFF)
set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS}) set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS})
@ -621,6 +622,7 @@ if(UNIX AND NOT APPLE)
CheckESD() CheckESD()
CheckARTS() CheckARTS()
CheckNAS() CheckNAS()
CheckSNDIO()
CheckFusionSound() CheckFusionSound()
endif(SDL_AUDIO) endif(SDL_AUDIO)

View file

@ -225,6 +225,37 @@ macro(CheckNAS)
endif(NAS) endif(NAS)
endmacro(CheckNAS) endmacro(CheckNAS)
# Requires:
# - n/a
# Optional:
# - SNDIO_SHARED opt
# - HAVE_DLOPEN opt
macro(CheckSNDIO)
if(SNDIO)
# TODO: set include paths properly, so the sndio headers are found
check_include_file(sndio.h HAVE_SNDIO_H)
find_library(D_SNDIO_LIB audio)
if(HAVE_SNDIO_H AND D_SNDIO_LIB)
set(HAVE_SNDIO TRUE)
file(GLOB SNDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/sndio/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${SNDIO_SOURCES})
set(SDL_AUDIO_DRIVER_SNDIO 1)
if(SNDIO_SHARED)
if(NOT HAVE_DLOPEN)
message_warn("You must have SDL_LoadObject() support for dynamic sndio loading")
else()
get_filename_component(F_SNDIO_LIB ${D_SNDIO_LIB} NAME)
set(SDL_AUDIO_DRIVER_SNDIO_DYNAMIC "\"${F_SNDIO_LIB}\"")
set(HAVE_SNDIO_SHARED TRUE)
endif(NOT HAVE_DLOPEN)
else(SNDIO_SHARED)
list(APPEND EXTRA_LIBS ${D_SNDIO_LIB})
endif(SNDIO_SHARED)
set(HAVE_SDL_AUDIO TRUE)
endif(HAVE_SNDIO_H AND D_SNDIO_LIB)
endif(SNDIO)
endmacro(CheckSNDIO)
# Requires: # Requires:
# - PkgCheckModules # - PkgCheckModules
# Optional: # Optional:

View file

@ -910,6 +910,52 @@ AC_HELP_STRING([--enable-nas-shared], [dynamically load NAS audio support [[defa
fi fi
} }
dnl See if the sndio audio interface is supported
CheckSNDIO()
{
AC_ARG_ENABLE(sndio,
AC_HELP_STRING([--enable-sndio], [support the sndio audio API [[default=yes]]]),
, enable_sndio=yes)
if test x$enable_audio = xyes -a x$enable_sndio = xyes; then
AC_CHECK_HEADER(sndio.h, have_sndio_hdr=yes)
AC_CHECK_LIB(sndio, sio_open, have_sndio_lib=yes)
AC_MSG_CHECKING(for sndio audio support)
have_sndio=no
if test x$have_sndio_hdr = xyes -a x$have_sndio_lib = xyes; then
have_sndio=yes
SNDIO_LIBS="-lsndio"
fi
AC_MSG_RESULT($have_sndio)
if test x$have_sndio = xyes; then
AC_ARG_ENABLE(sndio-shared,
AC_HELP_STRING([--enable-sndio-shared], [dynamically load sndio audio support [[default=yes]]]),
, enable_sndio_shared=yes)
sndio_lib=[`find_lib "libsndio.so.*" "$SNDIO_LIBS" | sed 's/.*\/\(.*\)/\1/; q'`]
if test x$have_loadso != xyes && \
test x$enable_sndio_shared = xyes; then
AC_MSG_WARN([You must have SDL_LoadObject() support for dynamic sndio loading])
fi
if test x$have_loadso = xyes && \
test x$enable_sndio_shared = xyes && test x$sndio_lib != x; then
echo "-- dynamic libsndio -> $sndio_lib"
AC_DEFINE_UNQUOTED(SDL_AUDIO_DRIVER_SNDIO_DYNAMIC, "$sndio_lib", [ ])
else
EXTRA_LDFLAGS="$EXTRA_LDFLAGS $SNDIO_LIBS"
fi
AC_DEFINE(SDL_AUDIO_DRIVER_SNDIO, 1, [ ])
SOURCES="$SOURCES $srcdir/src/audio/sndio/*.c"
EXTRA_CFLAGS="$EXTRA_CFLAGS $SNDIO_CFLAGS"
have_audio=yes
fi
fi
}
dnl rcg07142001 See if the user wants the disk writer audio driver... dnl rcg07142001 See if the user wants the disk writer audio driver...
CheckDiskAudio() CheckDiskAudio()
{ {
@ -2262,6 +2308,7 @@ case "$host" in
CheckARTSC CheckARTSC
CheckESD CheckESD
CheckNAS CheckNAS
CheckSNDIO
CheckX11 CheckX11
CheckDirectFB CheckDirectFB
CheckFusionSound CheckFusionSound

View file

@ -195,6 +195,8 @@
#cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_ESD_DYNAMIC @SDL_AUDIO_DRIVER_ESD_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@ #cmakedefine SDL_AUDIO_DRIVER_NAS @SDL_AUDIO_DRIVER_NAS@
#cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@ #cmakedefine SDL_AUDIO_DRIVER_NAS_DYNAMIC @SDL_AUDIO_DRIVER_NAS_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_SNDIO @SDL_AUDIO_DRIVER_SNDIO@
#cmakedefine SDL_AUDIO_DRIVER_SNDIO_DYNAMIC @SDL_AUDIO_DRIVER_SNDIO_DYNAMIC@
#cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@ #cmakedefine SDL_AUDIO_DRIVER_OSS @SDL_AUDIO_DRIVER_OSS@
#cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@ #cmakedefine SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H @SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H@
#cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@ #cmakedefine SDL_AUDIO_DRIVER_PAUDIO @SDL_AUDIO_DRIVER_PAUDIO@

View file

@ -199,6 +199,8 @@
#undef SDL_AUDIO_DRIVER_ESD_DYNAMIC #undef SDL_AUDIO_DRIVER_ESD_DYNAMIC
#undef SDL_AUDIO_DRIVER_NAS #undef SDL_AUDIO_DRIVER_NAS
#undef SDL_AUDIO_DRIVER_NAS_DYNAMIC #undef SDL_AUDIO_DRIVER_NAS_DYNAMIC
#undef SDL_AUDIO_DRIVER_SNDIO
#undef SDL_AUDIO_DRIVER_SNDIO_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_PAUDIO #undef SDL_AUDIO_DRIVER_PAUDIO

View file

@ -67,6 +67,7 @@ extern AudioBootStrap NDSAUD_bootstrap;
extern AudioBootStrap FUSIONSOUND_bootstrap; extern AudioBootStrap FUSIONSOUND_bootstrap;
extern AudioBootStrap ANDROIDAUD_bootstrap; extern AudioBootStrap ANDROIDAUD_bootstrap;
extern AudioBootStrap PSPAUD_bootstrap; extern AudioBootStrap PSPAUD_bootstrap;
extern AudioBootStrap SNDIO_bootstrap;
/* Available audio drivers */ /* Available audio drivers */
static const AudioBootStrap *const bootstrap[] = { static const AudioBootStrap *const bootstrap[] = {
@ -76,6 +77,9 @@ static const AudioBootStrap *const bootstrap[] = {
#if SDL_AUDIO_DRIVER_ALSA #if SDL_AUDIO_DRIVER_ALSA
&ALSA_bootstrap, &ALSA_bootstrap,
#endif #endif
#if SDL_AUDIO_DRIVER_SNDIO
&SNDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_BSD #if SDL_AUDIO_DRIVER_BSD
&BSD_AUDIO_bootstrap, &BSD_AUDIO_bootstrap,
#endif #endif

View file

@ -0,0 +1,327 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#if SDL_AUDIO_DRIVER_SNDIO
/* OpenBSD sndio target */
#if HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include <unistd.h>
#include "SDL_audio.h"
#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_sndioaudio.h"
#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
#include "SDL_loadso.h"
#endif
static struct sio_hdl * (*SNDIO_sio_open)(const char *, unsigned int, int);
static void (*SNDIO_sio_close)(struct sio_hdl *);
static int (*SNDIO_sio_setpar)(struct sio_hdl *, struct sio_par *);
static int (*SNDIO_sio_getpar)(struct sio_hdl *, struct sio_par *);
static int (*SNDIO_sio_start)(struct sio_hdl *);
static int (*SNDIO_sio_stop)(struct sio_hdl *);
static size_t (*SNDIO_sio_read)(struct sio_hdl *, void *, size_t);
static size_t (*SNDIO_sio_write)(struct sio_hdl *, const void *, size_t);
static void (*SNDIO_sio_initpar)(struct sio_par *);
#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
static const char *sndio_library = SDL_AUDIO_DRIVER_SNDIO_DYNAMIC;
static void *sndio_handle = NULL;
static int
load_sndio_sym(const char *fn, void **addr)
{
*addr = SDL_LoadFunction(sndio_handle, fn);
if (*addr == NULL) {
/* Don't call SDL_SetError(): SDL_LoadFunction already did. */
return 0;
}
return 1;
}
/* cast funcs to char* first, to please GCC's strict aliasing rules. */
#define SDL_SNDIO_SYM(x) \
if (!load_sndio_sym(#x, (void **) (char *) &SNDIO_##x)) return -1
#else
#define SDL_SNDIO_SYM(x) SNDIO_##x = x
#endif
static int
load_sndio_syms(void)
{
SDL_SNDIO_SYM(sio_open);
SDL_SNDIO_SYM(sio_close);
SDL_SNDIO_SYM(sio_setpar);
SDL_SNDIO_SYM(sio_getpar);
SDL_SNDIO_SYM(sio_start);
SDL_SNDIO_SYM(sio_stop);
SDL_SNDIO_SYM(sio_read);
SDL_SNDIO_SYM(sio_write);
SDL_SNDIO_SYM(sio_initpar);
return 0;
}
#undef SDL_SNDIO_SYM
#ifdef SDL_AUDIO_DRIVER_SNDIO_DYNAMIC
static void
UnloadSNDIOLibrary(void)
{
if (sndio_handle != NULL) {
SDL_UnloadObject(sndio_handle);
sndio_handle = NULL;
}
}
static int
LoadSNDIOLibrary(void)
{
int retval = 0;
if (sndio_handle == NULL) {
sndio_handle = SDL_LoadObject(sndio_library);
if (sndio_handle == NULL) {
retval = -1;
/* Don't call SDL_SetError(): SDL_LoadObject already did. */
} else {
retval = load_sndio_syms();
if (retval < 0) {
UnloadSNDIOLibrary();
}
}
}
return retval;
}
#else
static void
UnloadSNDIOLibrary(void)
{
}
static int
LoadSNDIOLibrary(void)
{
load_sndio_syms();
return 0;
}
#endif /* SDL_AUDIO_DRIVER_SNDIO_DYNAMIC */
static void
SNDIO_WaitDevice(_THIS)
{
/* no-op; sio_write() blocks if necessary. */
}
static void
SNDIO_PlayDevice(_THIS)
{
const int written = sio_write(this->hidden->dev, this->hidden->mixbuf, this->hidden->mixlen);
/* If we couldn't write, assume fatal error for now */
if ( written == 0 ) {
this->enabled = 0;
}
#ifdef DEBUG_AUDIO
fprintf(stderr, "Wrote %d bytes of audio data\n", written);
#endif
}
static Uint8 *
SNDIO_GetDeviceBuf(_THIS)
{
return this->hidden->mixbuf;
}
static void
SNDIO_WaitDone(_THIS)
{
sio_stop(this->hidden->dev);
}
static void
SNDIO_CloseDevice(_THIS)
{
if (this->hidden != NULL) {
if (this->hidden->mixbuf != NULL) {
SDL_FreeAudioMem(this->hidden->mixbuf);
this->hidden->mixbuf = NULL;
}
if ( this->hidden->dev != NULL ) {
sio_close(this->hidden->dev);
this->hidden->dev = NULL;
}
SDL_free(this->hidden);
this->hidden = NULL;
}
}
static int
SNDIO_OpenDevice(_THIS, const char *devname, int iscapture)
{
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
struct sio_par par;
int status;
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
SDL_memset(this->hidden, 0, sizeof(*this->hidden));
this->hidden->mixlen = this->spec.size;
/* !!! FIXME: SIO_DEVANY can be a specific device... */
if ((this->hidden->dev = sio_open(0 /*SIO_DEVANY*/, SIO_PLAY, 0)) == NULL) {
SNDIO_CloseDevice(this);
return SDL_SetError("sio_open() failed");
}
sio_initpar(&par);
par.rate = this->spec.freq;
par.pchan = this->spec.channels;
par.round = this->spec.samples;
par.appbufsz = par.round * 2;
/* Try for a closest match on audio format */
status = -1;
while (test_format && (status < 0)) {
if (!SDL_AUDIO_ISFLOAT(test_format)) {
par.le = SDL_AUDIO_ISLITTLEENDIAN(test_format) ? 1 : 0;
par.sig = SDL_AUDIO_ISSIGNED(test_format) ? 1 : 0;
par.bits = SDL_AUDIO_BITSIZE(test_format);
if (sio_setpar(this->hidden->dev, &par) == 1) {
status = 0;
break;
}
}
test_format = SDL_NextAudioFormat();
}
if (status < 0) {
SNDIO_CloseDevice(this);
return SDL_SetError("sndio: Couldn't find any hardware audio formats");
}
if (sio_getpar(this->hidden->dev, &par) == 0) {
SNDIO_CloseDevice(this);
return SDL_SetError("sio_getpar() failed");
}
if ((par.bits == 32) && (par.sig) && (par.le))
this->spec.format = AUDIO_S32LSB;
else if ((par.bits == 32) && (par.sig) && (!par.le))
this->spec.format = AUDIO_S32MSB;
else if ((par.bits == 16) && (par.sig) && (par.le))
this->spec.format = AUDIO_S16LSB;
else if ((par.bits == 16) && (par.sig) && (!par.le))
this->spec.format = AUDIO_S16MSB;
else if ((par.bits == 16) && (!par.sig) && (par.le))
this->spec.format = AUDIO_U16LSB;
else if ((par.bits == 16) && (!par.sig) && (!par.le))
this->spec.format = AUDIO_U16MSB;
else if ((par.bits == 8) && (par.sig))
this->spec.format = AUDIO_S8;
else if ((par.bits == 8) && (!par.sig))
this->spec.format = AUDIO_U8;
else {
SNDIO_CloseDevice(this);
return SDL_SetError("sndio: Got unsupported hardware audio format.");
}
this->spec.freq = par.rate;
this->spec.channels = par.pchan;
this->spec.samples = par.round;
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
SNDIO_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
if (!sio_start(this->hidden->dev)) {
return SDL_SetError("sio_start() failed");
}
/* We're ready to rock and roll. :-) */
return 0;
}
static void
SNDIO_Deinitialize(void)
{
UnloadSNDIOLibrary();
}
static int
SNDIO_Init(SDL_AudioDriverImpl * impl)
{
if (LoadSNDIOLibrary() < 0) {
return 0;
}
/* Set the function pointers */
impl->OpenDevice = SNDIO_OpenDevice;
impl->WaitDevice = SNDIO_WaitDevice;
impl->PlayDevice = SNDIO_PlayDevice;
impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
impl->WaitDone = SNDIO_WaitDone;
impl->CloseDevice = SNDIO_CloseDevice;
impl->Deinitialize = SNDIO_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: sndio can handle multiple devices. */
return 1; /* this audio target is available. */
}
AudioBootStrap SNDIO_bootstrap = {
"sndio", "OpenBSD sndio", SNDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_SNDIO */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,45 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_config.h"
#ifndef _SDL_sndioaudio_h
#define _SDL_sndioaudio_h
#include <sndio.h>
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
/* The audio device handle */
struct sio_hdl *dev;
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
};
#endif /* _SDL_sndioaudio_h */
/* vi: set ts=4 sw=4 expandtab: */