1.1 --- a/src/audio/arts/SDL_artsaudio.c Fri Oct 06 01:13:09 2006 +0000
1.2 +++ b/src/audio/arts/SDL_artsaudio.c Fri Oct 06 02:40:02 2006 +0000
1.3 @@ -40,11 +40,12 @@
1.4 #define ARTS_DRIVER_NAME "arts"
1.5
1.6 /* Audio driver functions */
1.7 -static int ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec);
1.8 -static void ARTS_WaitAudio(_THIS);
1.9 -static void ARTS_PlayAudio(_THIS);
1.10 -static Uint8 *ARTS_GetAudioBuf(_THIS);
1.11 -static void ARTS_CloseAudio(_THIS);
1.12 +static int ARTS_OpenDevice(_THIS, const char *devname, int iscapture);
1.13 +static void ARTS_WaitDevice(_THIS);
1.14 +static void ARTS_PlayDevice(_THIS);
1.15 +static Uint8 *ARTS_GetDeviceBuf(_THIS);
1.16 +static void ARTS_CloseDevice(_THIS);
1.17 +static void ARTS_WaitDone(_THIS);
1.18
1.19 #ifdef SDL_AUDIO_DRIVER_ARTS_DYNAMIC
1.20
1.21 @@ -52,6 +53,7 @@
1.22 static void *arts_handle = NULL;
1.23 static int arts_loaded = 0;
1.24
1.25 +/* !!! FIXME: I hate this SDL_NAME clutter...it makes everything so messy! */
1.26 static int (*SDL_NAME(arts_init)) (void);
1.27 static void (*SDL_NAME(arts_free)) (void);
1.28 static arts_stream_t(*SDL_NAME(arts_play_stream)) (int rate, int bits,
1.29 @@ -64,20 +66,25 @@
1.30 static int (*SDL_NAME(arts_write)) (arts_stream_t s, const void *buffer,
1.31 int count);
1.32 static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
1.33 +static void (*SDL_NAME(arts_close_stream)) (arts_stream_t s);
1.34 +static const char *(*SDL_NAME(arts_error_text)) (int errorcode);
1.35
1.36 +#define SDL_ARTS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
1.37 static struct
1.38 {
1.39 const char *name;
1.40 void **func;
1.41 } arts_functions[] = {
1.42 - {
1.43 - "arts_init", (void **) &SDL_NAME(arts_init)}, {
1.44 - "arts_free", (void **) &SDL_NAME(arts_free)}, {
1.45 - "arts_play_stream", (void **) &SDL_NAME(arts_play_stream)}, {
1.46 - "arts_stream_set", (void **) &SDL_NAME(arts_stream_set)}, {
1.47 - "arts_stream_get", (void **) &SDL_NAME(arts_stream_get)}, {
1.48 - "arts_write", (void **) &SDL_NAME(arts_write)}, {
1.49 -"arts_close_stream", (void **) &SDL_NAME(arts_close_stream)},};
1.50 + SDL_ARTS_SYM(arts_init),
1.51 + SDL_ARTS_SYM(arts_free),
1.52 + SDL_ARTS_SYM(arts_play_stream),
1.53 + SDL_ARTS_SYM(arts_stream_set),
1.54 + SDL_ARTS_SYM(arts_stream_get),
1.55 + SDL_ARTS_SYM(arts_write),
1.56 + SDL_ARTS_SYM(arts_close_stream),
1.57 + SDL_ARTS_SYM(arts_error_text),
1.58 +};
1.59 +#undef SDL_ARTS_SYM
1.60
1.61 static void
1.62 UnloadARTSLibrary()
1.63 @@ -94,20 +101,23 @@
1.64 {
1.65 int i, retval = -1;
1.66
1.67 - arts_handle = SDL_LoadObject(arts_library);
1.68 - if (arts_handle) {
1.69 - arts_loaded = 1;
1.70 - retval = 0;
1.71 - for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
1.72 - *arts_functions[i].func =
1.73 - SDL_LoadFunction(arts_handle, arts_functions[i].name);
1.74 - if (!*arts_functions[i].func) {
1.75 - retval = -1;
1.76 - UnloadARTSLibrary();
1.77 - break;
1.78 + if (!arts_loaded) {
1.79 + arts_handle = SDL_LoadObject(arts_library);
1.80 + if (arts_handle) {
1.81 + arts_loaded = 1;
1.82 + retval = 0;
1.83 + for (i = 0; i < SDL_arraysize(arts_functions); ++i) {
1.84 + *arts_functions[i].func =
1.85 + SDL_LoadFunction(arts_handle, arts_functions[i].name);
1.86 + if (!*arts_functions[i].func) {
1.87 + retval = -1;
1.88 + UnloadARTSLibrary();
1.89 + break;
1.90 + }
1.91 }
1.92 }
1.93 }
1.94 +
1.95 return retval;
1.96 }
1.97
1.98 @@ -130,114 +140,90 @@
1.99 /* Audio driver bootstrap functions */
1.100
1.101 static int
1.102 -Audio_Available(void)
1.103 +ARTS_Available(void)
1.104 {
1.105 int available = 0;
1.106
1.107 - if (LoadARTSLibrary() < 0) {
1.108 - return available;
1.109 - }
1.110 - if (SDL_NAME(arts_init) () == 0) {
1.111 + if (LoadARTSLibrary() == 0) {
1.112 + if (SDL_NAME(arts_init) () == 0) {
1.113 #define ARTS_CRASH_HACK /* Play a stream so aRts doesn't crash */
1.114 #ifdef ARTS_CRASH_HACK
1.115 - arts_stream_t stream2;
1.116 - stream2 = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
1.117 - SDL_NAME(arts_write) (stream2, "", 0);
1.118 - SDL_NAME(arts_close_stream) (stream2);
1.119 + arts_stream_t stream;
1.120 + stream = SDL_NAME(arts_play_stream) (44100, 16, 2, "SDL");
1.121 + SDL_NAME(arts_write) (stream, "", 0);
1.122 + SDL_NAME(arts_close_stream) (stream);
1.123 #endif
1.124 - available = 1;
1.125 - SDL_NAME(arts_free) ();
1.126 + available = 1;
1.127 + SDL_NAME(arts_free) ();
1.128 + }
1.129 + UnloadARTSLibrary();
1.130 }
1.131 - UnloadARTSLibrary();
1.132
1.133 return available;
1.134 }
1.135
1.136 -static void
1.137 -Audio_DeleteDevice(SDL_AudioDevice * device)
1.138 +
1.139 +static int
1.140 +ARTS_Init(SDL_AudioDriverImpl *impl)
1.141 {
1.142 - SDL_free(device->hidden);
1.143 - SDL_free(device);
1.144 - UnloadARTSLibrary();
1.145 + /* Set the function pointers */
1.146 + impl->OpenDevice = ARTS_OpenDevice;
1.147 + impl->PlayDevice = ARTS_PlayDevice;
1.148 + impl->WaitDevice = ARTS_WaitDevice;
1.149 + impl->GetDeviceBuf = ARTS_GetDeviceBuf;
1.150 + impl->CloseDevice = ARTS_CloseDevice;
1.151 + impl->WaitDone = ARTS_WaitDone;
1.152 + impl->OnlyHasDefaultOutputDevice = 1;
1.153 +
1.154 + return 1;
1.155 }
1.156
1.157 -static SDL_AudioDevice *
1.158 -Audio_CreateDevice(int devindex)
1.159 -{
1.160 - SDL_AudioDevice *this;
1.161 -
1.162 - /* Initialize all variables that we clean on shutdown */
1.163 - LoadARTSLibrary();
1.164 - this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
1.165 - if (this) {
1.166 - SDL_memset(this, 0, (sizeof *this));
1.167 - this->hidden = (struct SDL_PrivateAudioData *)
1.168 - SDL_malloc((sizeof *this->hidden));
1.169 - }
1.170 - if ((this == NULL) || (this->hidden == NULL)) {
1.171 - SDL_OutOfMemory();
1.172 - if (this) {
1.173 - SDL_free(this);
1.174 - }
1.175 - return (0);
1.176 - }
1.177 - SDL_memset(this->hidden, 0, (sizeof *this->hidden));
1.178 - stream = 0;
1.179 -
1.180 - /* Set the function pointers */
1.181 - this->OpenAudio = ARTS_OpenAudio;
1.182 - this->WaitAudio = ARTS_WaitAudio;
1.183 - this->PlayAudio = ARTS_PlayAudio;
1.184 - this->GetAudioBuf = ARTS_GetAudioBuf;
1.185 - this->CloseAudio = ARTS_CloseAudio;
1.186 -
1.187 - this->free = Audio_DeleteDevice;
1.188 -
1.189 - return this;
1.190 -}
1.191
1.192 AudioBootStrap ARTS_bootstrap = {
1.193 - ARTS_DRIVER_NAME, "Analog Realtime Synthesizer",
1.194 - Audio_Available, Audio_CreateDevice, 0
1.195 + ARTS_DRIVER_NAME, "Analog RealTime Synthesizer",
1.196 + ARTS_Available, ARTS_Init, 0
1.197 };
1.198
1.199 +
1.200 /* This function waits until it is possible to write a full sound buffer */
1.201 static void
1.202 -ARTS_WaitAudio(_THIS)
1.203 +ARTS_WaitDevice(_THIS)
1.204 {
1.205 Sint32 ticks;
1.206
1.207 /* Check to see if the thread-parent process is still alive */
1.208 {
1.209 static int cnt = 0;
1.210 - /* Note that this only works with thread implementations
1.211 + /* Note that this only works with thread implementations
1.212 that use a different process id for each thread.
1.213 */
1.214 - if (parent && (((++cnt) % 10) == 0)) { /* Check every 10 loops */
1.215 - if (kill(parent, 0) < 0) {
1.216 + /* Check every 10 loops */
1.217 + if (this->hidden->parent && (((++cnt) % 10) == 0)) {
1.218 + if (kill(this->hidden->parent, 0) < 0) {
1.219 this->enabled = 0;
1.220 }
1.221 }
1.222 }
1.223
1.224 /* Use timer for general audio synchronization */
1.225 - ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS;
1.226 + ticks = ((Sint32) (this->hidden->next_frame-SDL_GetTicks())) - FUDGE_TICKS;
1.227 if (ticks > 0) {
1.228 SDL_Delay(ticks);
1.229 }
1.230 }
1.231
1.232 static void
1.233 -ARTS_PlayAudio(_THIS)
1.234 +ARTS_PlayDevice(_THIS)
1.235 {
1.236 - int written;
1.237 -
1.238 /* Write the audio data */
1.239 - written = SDL_NAME(arts_write) (stream, mixbuf, mixlen);
1.240 + int written = SDL_NAME(arts_write) (
1.241 + this->hidden->stream,
1.242 + this->hidden->mixbuf,
1.243 + this->hidden->mixlen);
1.244
1.245 /* If timer synchronization is enabled, set the next write frame */
1.246 - if (frame_ticks) {
1.247 - next_frame += frame_ticks;
1.248 + if (this->hidden->frame_ticks) {
1.249 + this->hidden->next_frame += this->hidden->frame_ticks;
1.250 }
1.251
1.252 /* If we couldn't write, assume fatal error for now */
1.253 @@ -249,41 +235,66 @@
1.254 #endif
1.255 }
1.256
1.257 -static Uint8 *
1.258 -ARTS_GetAudioBuf(_THIS)
1.259 +static void
1.260 +ARTS_WaitDone(_THIS)
1.261 {
1.262 - return (mixbuf);
1.263 + /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
1.264 }
1.265
1.266 +
1.267 +static Uint8 *
1.268 +ARTS_GetDeviceBuf(_THIS)
1.269 +{
1.270 + return (this->hidden->mixbuf);
1.271 +}
1.272 +
1.273 +
1.274 static void
1.275 -ARTS_CloseAudio(_THIS)
1.276 +ARTS_CloseDevice(_THIS)
1.277 {
1.278 - if (mixbuf != NULL) {
1.279 - SDL_FreeAudioMem(mixbuf);
1.280 - mixbuf = NULL;
1.281 + if (this->hidden != NULL) {
1.282 + if (this->hidden->mixbuf != NULL) {
1.283 + SDL_FreeAudioMem(this->hidden->mixbuf);
1.284 + this->hidden->mixbuf = NULL;
1.285 + }
1.286 + if (this->hidden->stream) {
1.287 + SDL_NAME(arts_close_stream) (this->hidden->stream);
1.288 + this->hidden->stream = 0;
1.289 + }
1.290 + SDL_NAME(arts_free) ();
1.291 + SDL_free(this->hidden);
1.292 + this->hidden = NULL;
1.293 }
1.294 - if (stream) {
1.295 - SDL_NAME(arts_close_stream) (stream);
1.296 - stream = 0;
1.297 - }
1.298 - SDL_NAME(arts_free) ();
1.299 + UnloadARTSLibrary();
1.300 }
1.301
1.302 +
1.303 static int
1.304 -ARTS_OpenAudio(_THIS, SDL_AudioSpec * spec)
1.305 +ARTS_OpenDevice(_THIS, const char *devname, int iscapture)
1.306 {
1.307 + int rc = 0;
1.308 int bits, frag_spec;
1.309 SDL_AudioFormat test_format, format;
1.310
1.311 - /* Reset the timer synchronization flag */
1.312 - frame_ticks = 0.0;
1.313 + /* Initialize all variables that we clean on shutdown */
1.314 + this->hidden = (struct SDL_PrivateAudioData *)
1.315 + SDL_malloc((sizeof *this->hidden));
1.316 + if (this->hidden == NULL) {
1.317 + SDL_OutOfMemory();
1.318 + return 0;
1.319 + }
1.320 + SDL_memset(this->hidden, 0, (sizeof *this->hidden));
1.321
1.322 - mixbuf = NULL;
1.323 + if (LoadARTSLibrary() < 0) {
1.324 + ARTS_CloseDevice(this);
1.325 + SDL_SetError("ARTS: failed to load library: %s", SDL_GetError());
1.326 + return 0;
1.327 + }
1.328
1.329 /* Try for a closest match on audio format */
1.330 format = 0;
1.331 bits = 0;
1.332 - for (test_format = SDL_FirstAudioFormat(spec->format);
1.333 + for (test_format = SDL_FirstAudioFormat(this->spec.format);
1.334 !format && test_format;) {
1.335 #ifdef DEBUG_AUDIO
1.336 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
1.337 @@ -306,51 +317,62 @@
1.338 }
1.339 }
1.340 if (format == 0) {
1.341 + ARTS_CloseDevice(this);
1.342 SDL_SetError("Couldn't find any hardware audio formats");
1.343 - return (-1);
1.344 + return 0;
1.345 }
1.346 - spec->format = test_format;
1.347 + this->spec.format = test_format;
1.348
1.349 - if (SDL_NAME(arts_init) () != 0) {
1.350 - SDL_SetError("Unable to initialize ARTS");
1.351 - return (-1);
1.352 + if ((rc = SDL_NAME(arts_init) ()) != 0) {
1.353 + ARTS_CloseDevice(this);
1.354 + SDL_SetError( "Unable to initialize ARTS: %s",
1.355 + SDL_NAME(arts_error_text)(rc) );
1.356 + return 0;
1.357 }
1.358 - stream =
1.359 - SDL_NAME(arts_play_stream) (spec->freq, bits, spec->channels, "SDL");
1.360 + this->hidden->stream = SDL_NAME(arts_play_stream) (
1.361 + this->spec.freq,
1.362 + bits, this->spec.channels,
1.363 + "SDL");
1.364
1.365 /* Calculate the final parameters for this audio specification */
1.366 - SDL_CalculateAudioSpec(spec);
1.367 + SDL_CalculateAudioSpec(&this->spec);
1.368
1.369 /* Determine the power of two of the fragment size */
1.370 - for (frag_spec = 0; (0x01 << frag_spec) < spec->size; ++frag_spec);
1.371 - if ((0x01 << frag_spec) != spec->size) {
1.372 + for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
1.373 + if ((0x01 << frag_spec) != this->spec.size) {
1.374 + ARTS_CloseDevice(this);
1.375 SDL_SetError("Fragment size must be a power of two");
1.376 - return (-1);
1.377 + return 0;
1.378 }
1.379 frag_spec |= 0x00020000; /* two fragments, for low latency */
1.380
1.381 #ifdef ARTS_P_PACKET_SETTINGS
1.382 - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SETTINGS, frag_spec);
1.383 + SDL_NAME(arts_stream_set) (this->hidden->stream,
1.384 + ARTS_P_PACKET_SETTINGS, frag_spec);
1.385 #else
1.386 - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_SIZE,
1.387 + SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_SIZE,
1.388 frag_spec & 0xffff);
1.389 - SDL_NAME(arts_stream_set) (stream, ARTS_P_PACKET_COUNT, frag_spec >> 16);
1.390 + SDL_NAME(arts_stream_set) (this->hidden->stream, ARTS_P_PACKET_COUNT,
1.391 + frag_spec >> 16);
1.392 #endif
1.393 - spec->size = SDL_NAME(arts_stream_get) (stream, ARTS_P_PACKET_SIZE);
1.394 + this->spec.size = SDL_NAME(arts_stream_get) (this->hidden->stream,
1.395 + ARTS_P_PACKET_SIZE);
1.396
1.397 /* Allocate mixing buffer */
1.398 - mixlen = spec->size;
1.399 - mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen);
1.400 - if (mixbuf == NULL) {
1.401 - return (-1);
1.402 + this->hidden->mixlen = this->spec.size;
1.403 + this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
1.404 + if (this->hidden->mixbuf == NULL) {
1.405 + ARTS_CloseDevice(this);
1.406 + SDL_OutOfMemory();
1.407 + return 0;
1.408 }
1.409 - SDL_memset(mixbuf, spec->silence, spec->size);
1.410 + SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
1.411
1.412 /* Get the parent process id (we're the parent of the audio thread) */
1.413 - parent = getpid();
1.414 + this->hidden->parent = getpid();
1.415
1.416 /* We're ready to rock and roll. :-) */
1.417 - return (0);
1.418 + return 1;
1.419 }
1.420
1.421 /* vi: set ts=4 sw=4 expandtab: */