Added OpenBSD "sndio" audio target. SDL-1.2
authorRyan C. Gordon <icculus@icculus.org>
Sun, 08 Jul 2012 07:20:50 -0400
branchSDL-1.2
changeset 6353dfcbd0d9209c
parent 6347 fdde82eb1ce3
child 6361 173deb250f75
Added OpenBSD "sndio" audio target.

Thanks to Brad Smith and the OpenBSD team for the patch!
configure.in
include/SDL_config.h.in
src/audio/SDL_audio.c
src/audio/SDL_sysaudio.h
src/audio/sndio/SDL_sndioaudio.c
src/audio/sndio/SDL_sndioaudio.h
     1.1 --- a/configure.in	Mon Jul 02 08:29:57 2012 -0400
     1.2 +++ b/configure.in	Sun Jul 08 07:20:50 2012 -0400
     1.3 @@ -486,6 +486,34 @@
     1.4      fi
     1.5  }
     1.6  
     1.7 +dnl Find Sndio
     1.8 +CheckSndio()
     1.9 +{
    1.10 +    AC_ARG_ENABLE(sndio,
    1.11 +AC_HELP_STRING([--enable-sndio], [support the sndio audio API [[default=yes]]]),
    1.12 +                  , enable_sndioaudio=yes)
    1.13 +    if test x$enable_audio = xyes -a x$enable_sndioaudio = xyes; then
    1.14 +        AC_CHECK_HEADER(sndio.h, have_sndio_hdr=yes)
    1.15 +        AC_CHECK_LIB(sndio, sio_open, have_sndio_lib=yes)
    1.16 +
    1.17 +        AC_MSG_CHECKING(for sndio support)
    1.18 +        have_sndio=no
    1.19 +
    1.20 +        if test x$have_sndio_hdr = xyes -a x$have_sndio_lib = xyes; then
    1.21 +            have_sndio=yes
    1.22 +            SNDIO_LIBS="-lsndio"
    1.23 +        fi
    1.24 +
    1.25 +        AC_MSG_RESULT($have_nas)
    1.26 +
    1.27 +        if test x$have_sndio = xyes; then
    1.28 +            AC_DEFINE(SDL_AUDIO_DRIVER_SNDIO)
    1.29 +            SOURCES="$SOURCES $srcdir/src/audio/sndio/*.c"
    1.30 +            EXTRA_LDFLAGS="$EXTRA_LDFLAGS $SNDIO_LIBS"
    1.31 +            have_audio=yes
    1.32 +        fi
    1.33 +}
    1.34 +
    1.35  dnl Find PulseAudio
    1.36  CheckPulseAudio()
    1.37  {
    1.38 @@ -2358,6 +2386,7 @@
    1.39          CheckALSA
    1.40          CheckARTSC
    1.41          CheckESD
    1.42 +        CheckSndio
    1.43          CheckPulseAudio
    1.44          CheckNAS
    1.45          CheckX11
    1.46 @@ -2390,7 +2419,7 @@
    1.47                  SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
    1.48                  have_audio=yes
    1.49              ;;
    1.50 -            netbsd|openbsd)
    1.51 +            netbsd)
    1.52                  AC_DEFINE(SDL_AUDIO_DRIVER_BSD)
    1.53                  SOURCES="$SOURCES $srcdir/src/audio/bsd/*.c"
    1.54                  have_audio=yes
     2.1 --- a/include/SDL_config.h.in	Mon Jul 02 08:29:57 2012 -0400
     2.2 +++ b/include/SDL_config.h.in	Sun Jul 08 07:20:50 2012 -0400
     2.3 @@ -182,6 +182,7 @@
     2.4  #undef SDL_AUDIO_DRIVER_OSS_SOUNDCARD_H
     2.5  #undef SDL_AUDIO_DRIVER_PAUD
     2.6  #undef SDL_AUDIO_DRIVER_QNXNTO
     2.7 +#undef SDL_AUDIO_DRIVER_SNDIO
     2.8  #undef SDL_AUDIO_DRIVER_SNDMGR
     2.9  #undef SDL_AUDIO_DRIVER_SUNAUDIO
    2.10  #undef SDL_AUDIO_DRIVER_WAVEOUT
     3.1 --- a/src/audio/SDL_audio.c	Mon Jul 02 08:29:57 2012 -0400
     3.2 +++ b/src/audio/SDL_audio.c	Sun Jul 08 07:20:50 2012 -0400
     3.3 @@ -42,6 +42,9 @@
     3.4  #if SDL_AUDIO_DRIVER_ALSA
     3.5  	&ALSA_bootstrap,
     3.6  #endif
     3.7 +#if SDL_AUDIO_DRIVER_SNDIO
     3.8 +	&SNDIO_bootstrap,
     3.9 +#endif
    3.10  #if SDL_AUDIO_DRIVER_BSD
    3.11  	&BSD_AUDIO_bootstrap,
    3.12  #endif
     4.1 --- a/src/audio/SDL_sysaudio.h	Mon Jul 02 08:29:57 2012 -0400
     4.2 +++ b/src/audio/SDL_sysaudio.h	Sun Jul 08 07:20:50 2012 -0400
     4.3 @@ -102,6 +102,9 @@
     4.4  	SDL_AudioDevice *(*create)(int devindex);
     4.5  } AudioBootStrap;
     4.6  
     4.7 +#if SDL_AUDIO_DRIVER_SNDIO
     4.8 +extern AudioBootStrap SNDIO_bootstrap;
     4.9 +#endif
    4.10  #if SDL_AUDIO_DRIVER_BSD
    4.11  extern AudioBootStrap BSD_AUDIO_bootstrap;
    4.12  #endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/audio/sndio/SDL_sndioaudio.c	Sun Jul 08 07:20:50 2012 -0400
     5.3 @@ -0,0 +1,286 @@
     5.4 +/*
     5.5 + * Copyright (c) 2008 Jacob Meuser <jakemsr@sdf.lonestar.org>
     5.6 + *
     5.7 + * Permission to use, copy, modify, and distribute this software for any
     5.8 + * purpose with or without fee is hereby granted, provided that the above
     5.9 + * copyright notice and this permission notice appear in all copies.
    5.10 + *
    5.11 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    5.12 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    5.13 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    5.14 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    5.15 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    5.16 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    5.17 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    5.18 + */
    5.19 +
    5.20 +#include "SDL_config.h"
    5.21 +
    5.22 +/* Allow access to a raw mixing buffer */
    5.23 +
    5.24 +#ifdef HAVE_SIGNAL_H
    5.25 +#include <signal.h>
    5.26 +#endif
    5.27 +#include <unistd.h>
    5.28 +
    5.29 +#include "SDL_timer.h"
    5.30 +#include "SDL_audio.h"
    5.31 +#include "../SDL_audiomem.h"
    5.32 +#include "../SDL_audio_c.h"
    5.33 +#include "../SDL_audiodev_c.h"
    5.34 +#include "SDL_sndioaudio.h"
    5.35 +
    5.36 +/* The tag name used by sndio audio */
    5.37 +#define SNDIO_DRIVER_NAME         "sndio"
    5.38 +
    5.39 +/* Audio driver functions */
    5.40 +static int SNDIO_OpenAudio(_THIS, SDL_AudioSpec *spec);
    5.41 +static void SNDIO_WaitAudio(_THIS);
    5.42 +static void SNDIO_PlayAudio(_THIS);
    5.43 +static Uint8 *SNDIO_GetAudioBuf(_THIS);
    5.44 +static void SNDIO_CloseAudio(_THIS);
    5.45 +
    5.46 +/* Audio driver bootstrap functions */
    5.47 +
    5.48 +static int Audio_Available(void)
    5.49 +{
    5.50 +	struct sio_hdl *this_hdl;
    5.51 +	int available = 0;
    5.52 +
    5.53 +	if ( (this_hdl = sio_open(NULL, SIO_PLAY, 0)) != NULL ) {
    5.54 +		sio_close(this_hdl);
    5.55 +		available = 1;
    5.56 +	}
    5.57 +
    5.58 +	return available;
    5.59 +}
    5.60 +
    5.61 +static void Audio_DeleteDevice(SDL_AudioDevice *device)
    5.62 +{
    5.63 +	SDL_free(device->hidden);
    5.64 +	SDL_free(device);
    5.65 +}
    5.66 +
    5.67 +static SDL_AudioDevice *Audio_CreateDevice(int devindex)
    5.68 +{
    5.69 +	SDL_AudioDevice *this;
    5.70 +
    5.71 +	/* Initialize all variables that we clean on shutdown */
    5.72 +	this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice));
    5.73 +	if ( this ) {
    5.74 +		SDL_memset(this, 0, (sizeof *this));
    5.75 +		this->hidden = (struct SDL_PrivateAudioData *)
    5.76 +				SDL_malloc((sizeof *this->hidden));
    5.77 +	}
    5.78 +	if ( (this == NULL) || (this->hidden == NULL) ) {
    5.79 +		SDL_OutOfMemory();
    5.80 +		if ( this ) {
    5.81 +			SDL_free(this);
    5.82 +		}
    5.83 +		return(0);
    5.84 +	}
    5.85 +	SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    5.86 +
    5.87 +	/* Set the function pointers */
    5.88 +	this->OpenAudio = SNDIO_OpenAudio;
    5.89 +	this->WaitAudio = SNDIO_WaitAudio;
    5.90 +	this->PlayAudio = SNDIO_PlayAudio;
    5.91 +	this->GetAudioBuf = SNDIO_GetAudioBuf;
    5.92 +	this->CloseAudio = SNDIO_CloseAudio;
    5.93 +
    5.94 +	this->free = Audio_DeleteDevice;
    5.95 +
    5.96 +	hdl = NULL;
    5.97 +
    5.98 +	return this;
    5.99 +}
   5.100 +
   5.101 +AudioBootStrap SNDIO_bootstrap = {
   5.102 +	SNDIO_DRIVER_NAME, "sndio",
   5.103 +	Audio_Available, Audio_CreateDevice
   5.104 +};
   5.105 +
   5.106 +
   5.107 +
   5.108 +/* This function waits until it is possible to write a full sound buffer */
   5.109 +static void SNDIO_WaitAudio(_THIS)
   5.110 +{
   5.111 +	/* Check to see if the thread-parent process is still alive */
   5.112 +	{ static int cnt = 0;
   5.113 +		/* Note that this only works with thread implementations 
   5.114 +		   that use a different process id for each thread.
   5.115 +		*/
   5.116 +		if (parent && (((++cnt)%10) == 0)) { /* Check every 10 loops */
   5.117 +			if ( kill(parent, 0) < 0 ) {
   5.118 +				this->enabled = 0;
   5.119 +			}
   5.120 +		}
   5.121 +	}
   5.122 +}
   5.123 +
   5.124 +static void SNDIO_PlayAudio(_THIS)
   5.125 +{
   5.126 +	int written;
   5.127 +
   5.128 +	/* Write the audio data */
   5.129 +	written = sio_write(hdl, mixbuf, mixlen);
   5.130 +	
   5.131 +	/* If we couldn't write, assume fatal error for now */
   5.132 +	if ( written == 0 ) {
   5.133 +		this->enabled = 0;
   5.134 +	}
   5.135 +#ifdef DEBUG_AUDIO
   5.136 +	fprintf(stderr, "Wrote %d bytes of audio data\n", written);
   5.137 +#endif
   5.138 +}
   5.139 +
   5.140 +static Uint8 *SNDIO_GetAudioBuf(_THIS)
   5.141 +{
   5.142 +	return(mixbuf);
   5.143 +}
   5.144 +
   5.145 +static void SNDIO_CloseAudio(_THIS)
   5.146 +{
   5.147 +	if ( mixbuf != NULL ) {
   5.148 +		SDL_FreeAudioMem(mixbuf);
   5.149 +		mixbuf = NULL;
   5.150 +	}
   5.151 +	if ( hdl != NULL ) {
   5.152 +		sio_close(hdl);
   5.153 +		hdl = NULL;
   5.154 +	}
   5.155 +}
   5.156 +
   5.157 +static int SNDIO_OpenAudio(_THIS, SDL_AudioSpec *spec)
   5.158 +{
   5.159 +	struct sio_par par, reqpar;
   5.160 +	int newrate;
   5.161 +
   5.162 +	mixbuf = NULL;
   5.163 +
   5.164 +	if ((hdl = sio_open(NULL, SIO_PLAY, 0)) == NULL) {
   5.165 +		SDL_SetError("sio_open() failed");
   5.166 +		return(-1);
   5.167 +	}
   5.168 +
   5.169 +	sio_initpar(&par);
   5.170 +
   5.171 +	switch (spec->format) {
   5.172 +	case AUDIO_S16LSB:
   5.173 +		par.bits = 16;
   5.174 +		par.sig = 1;
   5.175 +		par.le = 1;
   5.176 +		break;
   5.177 +	case AUDIO_S16MSB:
   5.178 +		par.bits = 16;
   5.179 +		par.sig = 1;
   5.180 +		par.le = 0;
   5.181 +		break;
   5.182 +	case AUDIO_S8:
   5.183 +		par.bits = 8;
   5.184 +		par.sig = 1;
   5.185 +		break;
   5.186 +	case AUDIO_U16LSB:
   5.187 +		par.bits = 16;
   5.188 +		par.sig = 0;
   5.189 +		par.le = 1;
   5.190 +		break;
   5.191 +	case AUDIO_U16MSB:
   5.192 +		par.bits = 16;
   5.193 +		par.sig = 0;
   5.194 +		par.le = 0;
   5.195 +		break;
   5.196 +	case AUDIO_U8:
   5.197 +		par.bits = 8;
   5.198 +		par.sig = 0;
   5.199 +		break;
   5.200 +	default:
   5.201 +		SDL_SetError("SNDIO unknown format");
   5.202 +		return(-1);
   5.203 +	}
   5.204 +
   5.205 +	par.rate = spec->freq;
   5.206 +	par.pchan = spec->channels;
   5.207 +	par.round = spec->samples;
   5.208 +	par.appbufsz = par.round * 2;
   5.209 +
   5.210 +	reqpar = par;
   5.211 +
   5.212 +	if (sio_setpar(hdl, &par) == 0) {
   5.213 +		SDL_SetError("sio_setpar() failed");
   5.214 +		return(-1);
   5.215 +	}
   5.216 +
   5.217 +	if (sio_getpar(hdl, &par) == 0) {
   5.218 +		SDL_SetError("sio_getpar() failed");
   5.219 +		return(-1);
   5.220 +	}
   5.221 +
   5.222 +	/* if wanted rate not found, find a multiple/factor */
   5.223 +	if (par.rate != spec->freq) {
   5.224 +		newrate = par.rate;
   5.225 +		if ((newrate > spec->freq && newrate % spec->freq != 0) ||
   5.226 +		     (newrate < spec->freq && spec->freq % newrate != 0)) {
   5.227 +			if ((spec->freq < 44100 && 44100 % spec->freq == 0) ||
   5.228 +			     (spec->freq > 44100 && spec->freq % 44100 == 0)) {
   5.229 +				newrate = 44100;
   5.230 +			}
   5.231 +		}
   5.232 +		/* only change sample rate */
   5.233 +		par = reqpar;
   5.234 +		par.rate = newrate;
   5.235 +		/* keep same latency */
   5.236 +		par.round = spec->samples * par.rate / reqpar.rate;
   5.237 +		par.appbufsz = par.round * 2;
   5.238 +		if (sio_setpar(hdl, &par) == 0) {
   5.239 +			SDL_SetError("sio_setpar() failed");
   5.240 +			return(-1);
   5.241 +		}
   5.242 +	}
   5.243 +
   5.244 +	if (sio_getpar(hdl, &par) == 0) {
   5.245 +		SDL_SetError("sio_getpar() failed");
   5.246 +		return(-1);
   5.247 +	}
   5.248 +
   5.249 +	if (par.bits == 16) {
   5.250 +		if (par.sig && par.le) {
   5.251 +			spec->format = AUDIO_S16LSB;
   5.252 +		} else if (par.sig && !par.le) {
   5.253 +			spec->format = AUDIO_S16MSB;
   5.254 +		} else if (!par.sig && par.le) {
   5.255 +			spec->format = AUDIO_U16LSB;
   5.256 +		} else 
   5.257 +			spec->format = AUDIO_U16MSB;
   5.258 +	} else if (par.bits == 8) {
   5.259 +		spec->format = par.sig ? AUDIO_S8 : AUDIO_U8;
   5.260 +	} else {
   5.261 +		SDL_SetError("SNDIO couldn't configure a suitable format");
   5.262 +		return(-1);
   5.263 +	}
   5.264 +
   5.265 +	spec->freq = par.rate;
   5.266 +	spec->channels = par.pchan;
   5.267 +	spec->samples = par.round;
   5.268 +
   5.269 +	SDL_CalculateAudioSpec(spec);
   5.270 +
   5.271 +	/* Allocate mixing buffer */
   5.272 +	mixlen = spec->size;
   5.273 +	mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen);
   5.274 +	if ( mixbuf == NULL ) {
   5.275 +		return(-1);
   5.276 +	}
   5.277 +	SDL_memset(mixbuf, spec->silence, spec->size);
   5.278 +
   5.279 +	/* Get the parent process id (we're the parent of the audio thread) */
   5.280 +	parent = getpid();
   5.281 +
   5.282 +	if ( sio_start(hdl) == 0 ) {
   5.283 +		SDL_SetError("sio_start() failed");
   5.284 +		return(-1);
   5.285 +	}
   5.286 +
   5.287 +	/* We're ready to rock and roll. :-) */
   5.288 +	return(0);
   5.289 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/audio/sndio/SDL_sndioaudio.h	Sun Jul 08 07:20:50 2012 -0400
     6.3 @@ -0,0 +1,50 @@
     6.4 +/*
     6.5 + * Copyright (c) 2008 Jacob Meuser <jakemsr@sdf.lonestar.org>
     6.6 + *
     6.7 + * Permission to use, copy, modify, and distribute this software for any
     6.8 + * purpose with or without fee is hereby granted, provided that the above
     6.9 + * copyright notice and this permission notice appear in all copies.
    6.10 + *
    6.11 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
    6.12 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    6.13 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
    6.14 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    6.15 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    6.16 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    6.17 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    6.18 + */
    6.19 +
    6.20 +#include "SDL_config.h"
    6.21 +
    6.22 +#ifndef _SDL_sndioaudio_h
    6.23 +#define _SDL_sndioaudio_h
    6.24 +
    6.25 +#include <sndio.h>
    6.26 +
    6.27 +#include "../SDL_sysaudio.h"
    6.28 +
    6.29 +/* Hidden "this" pointer for the video functions */
    6.30 +#define _THIS	SDL_AudioDevice *this
    6.31 +
    6.32 +struct SDL_PrivateAudioData {
    6.33 +	/* The stream descriptor for the audio device */
    6.34 +	struct sio_hdl *hdl;
    6.35 +
    6.36 +	/* The parent process id, to detect when application quits */
    6.37 +	pid_t parent;
    6.38 +
    6.39 +	/* Raw mixing buffer */
    6.40 +	Uint8 *mixbuf;
    6.41 +	int    mixlen;
    6.42 +
    6.43 +};
    6.44 +
    6.45 +/* Old variable names */
    6.46 +#define stream			(this->hidden->stream)
    6.47 +#define parent			(this->hidden->parent)
    6.48 +#define mixbuf			(this->hidden->mixbuf)
    6.49 +#define mixlen			(this->hidden->mixlen)
    6.50 +#define hdl			(this->hidden->hdl)
    6.51 +
    6.52 +#endif /* _SDL_sndioaudio_h */
    6.53 +