Mercurial > SDL_sound_CoreAudio
comparison SDL_sound.c @ 237:ceadd952319a
Increased ModPlug decoder's priority to be above MikMod. Fixed some coding
conventions. Mutex-protected the current sample list. Fixed sample list
addition code. Decoder selection in NewSample is more efficient now. Other
cleanups and corrections.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 19 Jan 2002 23:31:19 +0000 |
parents | 57e16a6d244f |
children | 6fe6de401b63 |
comparison
equal
deleted
inserted
replaced
236:034b2e56f405 | 237:ceadd952319a |
---|---|
107 { | 107 { |
108 #if (defined SOUND_SUPPORTS_MP3) | 108 #if (defined SOUND_SUPPORTS_MP3) |
109 { 0, &__Sound_DecoderFunctions_MP3 }, | 109 { 0, &__Sound_DecoderFunctions_MP3 }, |
110 #endif | 110 #endif |
111 | 111 |
112 #if (defined SOUND_SUPPORTS_MODPLUG) | |
113 { 0, &__Sound_DecoderFunctions_MODPLUG }, | |
114 #endif | |
115 | |
112 #if (defined SOUND_SUPPORTS_MIKMOD) | 116 #if (defined SOUND_SUPPORTS_MIKMOD) |
113 { 0, &__Sound_DecoderFunctions_MIKMOD }, | 117 { 0, &__Sound_DecoderFunctions_MIKMOD }, |
114 #endif | 118 #endif |
115 | 119 |
116 #if (defined SOUND_SUPPORTS_MODPLUG) | |
117 { 0, &__Sound_DecoderFunctions_MODPLUG }, | |
118 #endif | |
119 | |
120 #if (defined SOUND_SUPPORTS_WAV) | 120 #if (defined SOUND_SUPPORTS_WAV) |
121 { 0, &__Sound_DecoderFunctions_WAV }, | 121 { 0, &__Sound_DecoderFunctions_WAV }, |
122 #endif | 122 #endif |
123 | 123 |
124 #if (defined SOUND_SUPPORTS_AIFF) | 124 #if (defined SOUND_SUPPORTS_AIFF) |
161 /* General SDL_sound state ... */ | 161 /* General SDL_sound state ... */ |
162 | 162 |
163 typedef struct __SOUND_ERRMSGTYPE__ | 163 typedef struct __SOUND_ERRMSGTYPE__ |
164 { | 164 { |
165 Uint32 tid; | 165 Uint32 tid; |
166 int errorAvailable; | 166 int error_available; |
167 char errorString[128]; | 167 char error_string[128]; |
168 struct __SOUND_ERRMSGTYPE__ *next; | 168 struct __SOUND_ERRMSGTYPE__ *next; |
169 } ErrMsg; | 169 } ErrMsg; |
170 | 170 |
171 static ErrMsg *errorMessages = NULL; | 171 static ErrMsg *error_msgs = NULL; |
172 static SDL_mutex *errorlist_mutex = NULL; | 172 static SDL_mutex *errorlist_mutex = NULL; |
173 | 173 |
174 /* !!! FIXME: This needs a mutex. */ | 174 static Sound_Sample *sample_list = NULL; /* this is a linked list. */ |
175 static Sound_Sample *samplesList = NULL; /* this is a linked list. */ | 175 static SDL_mutex *samplelist_mutex = NULL; |
176 | |
176 static const Sound_DecoderInfo **available_decoders = NULL; | 177 static const Sound_DecoderInfo **available_decoders = NULL; |
177 static int initialized = 0; | 178 static int initialized = 0; |
178 | 179 |
179 | 180 |
180 /* functions ... */ | 181 /* functions ... */ |
195 size_t i; | 196 size_t i; |
196 size_t pos = 0; | 197 size_t pos = 0; |
197 size_t total = sizeof (decoders) / sizeof (decoders[0]); | 198 size_t total = sizeof (decoders) / sizeof (decoders[0]); |
198 BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0); | 199 BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0); |
199 | 200 |
200 samplesList = NULL; | 201 sample_list = NULL; |
201 errorMessages = NULL; | 202 error_msgs = NULL; |
202 | 203 |
203 available_decoders = (const Sound_DecoderInfo **) | 204 available_decoders = (const Sound_DecoderInfo **) |
204 malloc((total) * sizeof (Sound_DecoderInfo *)); | 205 malloc((total) * sizeof (Sound_DecoderInfo *)); |
205 BAIL_IF_MACRO(available_decoders == NULL, ERR_OUT_OF_MEMORY, 0); | 206 BAIL_IF_MACRO(available_decoders == NULL, ERR_OUT_OF_MEMORY, 0); |
206 | 207 |
207 SDL_Init(SDL_INIT_AUDIO); | 208 SDL_Init(SDL_INIT_AUDIO); |
209 | |
208 errorlist_mutex = SDL_CreateMutex(); | 210 errorlist_mutex = SDL_CreateMutex(); |
209 | 211 |
210 for (i = 0; decoders[i].funcs != NULL; i++) | 212 for (i = 0; decoders[i].funcs != NULL; i++) |
211 { | 213 { |
212 decoders[i].available = decoders[i].funcs->init(); | 214 decoders[i].available = decoders[i].funcs->init(); |
230 ErrMsg *nexterr = NULL; | 232 ErrMsg *nexterr = NULL; |
231 size_t i; | 233 size_t i; |
232 | 234 |
233 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); | 235 BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0); |
234 | 236 |
235 while (((volatile Sound_Sample *) samplesList) != NULL) | 237 while (((volatile Sound_Sample *) sample_list) != NULL) |
236 Sound_FreeSample(samplesList); | 238 Sound_FreeSample(sample_list); |
237 | 239 |
238 samplesList = NULL; | 240 initialized = 0; |
241 | |
242 SDL_DestroyMutex(samplelist_mutex); | |
243 samplelist_mutex = NULL; | |
244 sample_list = NULL; | |
239 | 245 |
240 for (i = 0; decoders[i].funcs != NULL; i++) | 246 for (i = 0; decoders[i].funcs != NULL; i++) |
241 { | 247 { |
242 if (decoders[i].available) | 248 if (decoders[i].available) |
243 { | 249 { |
250 free((void *) available_decoders); | 256 free((void *) available_decoders); |
251 available_decoders = NULL; | 257 available_decoders = NULL; |
252 | 258 |
253 /* clean up error state for each thread... */ | 259 /* clean up error state for each thread... */ |
254 SDL_LockMutex(errorlist_mutex); | 260 SDL_LockMutex(errorlist_mutex); |
255 for (err = errorMessages; err != NULL; err = nexterr) | 261 for (err = error_msgs; err != NULL; err = nexterr) |
256 { | 262 { |
257 nexterr = err->next; | 263 nexterr = err->next; |
258 free(err); | 264 free(err); |
259 } /* for */ | 265 } /* for */ |
260 errorMessages = NULL; | 266 error_msgs = NULL; |
261 initialized = 0; | |
262 SDL_UnlockMutex(errorlist_mutex); | 267 SDL_UnlockMutex(errorlist_mutex); |
263 SDL_DestroyMutex(errorlist_mutex); | 268 SDL_DestroyMutex(errorlist_mutex); |
264 errorlist_mutex = NULL; | 269 errorlist_mutex = NULL; |
265 | 270 |
266 return(1); | 271 return(1); |
276 static ErrMsg *findErrorForCurrentThread(void) | 281 static ErrMsg *findErrorForCurrentThread(void) |
277 { | 282 { |
278 ErrMsg *i; | 283 ErrMsg *i; |
279 Uint32 tid; | 284 Uint32 tid; |
280 | 285 |
281 if (errorMessages != NULL) | 286 if (error_msgs != NULL) |
282 { | 287 { |
283 tid = SDL_ThreadID(); | 288 tid = SDL_ThreadID(); |
284 | 289 |
285 SDL_LockMutex(errorlist_mutex); | 290 SDL_LockMutex(errorlist_mutex); |
286 for (i = errorMessages; i != NULL; i = i->next) | 291 for (i = error_msgs; i != NULL; i = i->next) |
287 { | 292 { |
288 if (i->tid == tid) | 293 if (i->tid == tid) |
289 { | 294 { |
290 SDL_UnlockMutex(errorlist_mutex); | 295 SDL_UnlockMutex(errorlist_mutex); |
291 return(i); | 296 return(i); |
305 | 310 |
306 if (!initialized) | 311 if (!initialized) |
307 return(ERR_NOT_INITIALIZED); | 312 return(ERR_NOT_INITIALIZED); |
308 | 313 |
309 err = findErrorForCurrentThread(); | 314 err = findErrorForCurrentThread(); |
310 if ((err != NULL) && (err->errorAvailable)) | 315 if ((err != NULL) && (err->error_available)) |
311 { | 316 { |
312 retval = err->errorString; | 317 retval = err->error_string; |
313 err->errorAvailable = 0; | 318 err->error_available = 0; |
314 } /* if */ | 319 } /* if */ |
315 | 320 |
316 return(retval); | 321 return(retval); |
317 } /* Sound_GetError */ | 322 } /* Sound_GetError */ |
318 | 323 |
324 if (!initialized) | 329 if (!initialized) |
325 return; | 330 return; |
326 | 331 |
327 err = findErrorForCurrentThread(); | 332 err = findErrorForCurrentThread(); |
328 if (err != NULL) | 333 if (err != NULL) |
329 err->errorAvailable = 0; | 334 err->error_available = 0; |
330 } /* Sound_ClearError */ | 335 } /* Sound_ClearError */ |
331 | 336 |
332 | 337 |
333 /* | 338 /* |
334 * This is declared in the internal header. | 339 * This is declared in the internal header. |
355 | 360 |
356 memset((void *) err, '\0', sizeof (ErrMsg)); | 361 memset((void *) err, '\0', sizeof (ErrMsg)); |
357 err->tid = SDL_ThreadID(); | 362 err->tid = SDL_ThreadID(); |
358 | 363 |
359 SDL_LockMutex(errorlist_mutex); | 364 SDL_LockMutex(errorlist_mutex); |
360 err->next = errorMessages; | 365 err->next = error_msgs; |
361 errorMessages = err; | 366 error_msgs = err; |
362 SDL_UnlockMutex(errorlist_mutex); | 367 SDL_UnlockMutex(errorlist_mutex); |
363 } /* if */ | 368 } /* if */ |
364 | 369 |
365 err->errorAvailable = 1; | 370 err->error_available = 1; |
366 strncpy(err->errorString, str, sizeof (err->errorString)); | 371 strncpy(err->error_string, str, sizeof (err->error_string)); |
367 err->errorString[sizeof (err->errorString) - 1] = '\0'; | 372 err->error_string[sizeof (err->error_string) - 1] = '\0'; |
368 } /* Sound_SetError */ | 373 } /* Sound_SetError */ |
369 | 374 |
370 | 375 |
371 /* | 376 /* |
372 * -ansi and -pedantic flags prevent use of strcasecmp() on Linux, and | 377 * -ansi and -pedantic flags prevent use of strcasecmp() on Linux, and |
537 memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo)); | 542 memcpy(&sample->desired, &desired, sizeof (Sound_AudioInfo)); |
538 internal->sdlcvt.buf = internal->buffer = sample->buffer; | 543 internal->sdlcvt.buf = internal->buffer = sample->buffer; |
539 internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult; | 544 internal->buffer_size = sample->buffer_size / internal->sdlcvt.len_mult; |
540 internal->sdlcvt.len = internal->buffer_size; | 545 internal->sdlcvt.len = internal->buffer_size; |
541 | 546 |
542 /* Prepend our new Sound_Sample to the samplesList... */ | 547 /* Prepend our new Sound_Sample to the sample_list... */ |
543 if (samplesList != NULL) | 548 SDL_LockMutex(samplelist_mutex); |
544 { | 549 internal->next = sample_list; |
545 internal->next = samplesList; | 550 if (sample_list != NULL) |
546 if (samplesList != NULL) | 551 ((Sound_SampleInternal *) sample_list->opaque)->prev = sample; |
547 internal->prev = sample; | 552 sample_list = sample; |
548 } /* if */ | 553 SDL_UnlockMutex(samplelist_mutex); |
549 samplesList = sample; | |
550 | 554 |
551 SNDDBG(("New sample DESIRED format: %s format, %d rate, %d channels.\n", | 555 SNDDBG(("New sample DESIRED format: %s format, %d rate, %d channels.\n", |
552 fmt_to_str(sample->desired.format), | 556 fmt_to_str(sample->desired.format), |
553 sample->desired.rate, | 557 sample->desired.rate, |
554 sample->desired.channels)); | 558 sample->desired.channels)); |
590 { | 594 { |
591 if (__Sound_strcasecmp(*decoderExt, ext) == 0) | 595 if (__Sound_strcasecmp(*decoderExt, ext) == 0) |
592 { | 596 { |
593 if (init_sample(decoder->funcs, retval, ext, desired)) | 597 if (init_sample(decoder->funcs, retval, ext, desired)) |
594 return(retval); | 598 return(retval); |
599 break; /* done with this decoder either way. */ | |
595 } /* if */ | 600 } /* if */ |
596 decoderExt++; | 601 decoderExt++; |
597 } /* while */ | 602 } /* while */ |
598 } /* if */ | 603 } /* if */ |
599 } /* for */ | 604 } /* for */ |
602 /* no direct extension match? Try everything we've got... */ | 607 /* no direct extension match? Try everything we've got... */ |
603 for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++) | 608 for (decoder = &decoders[0]; decoder->funcs != NULL; decoder++) |
604 { | 609 { |
605 if (decoder->available) | 610 if (decoder->available) |
606 { | 611 { |
607 if (init_sample(decoder->funcs, retval, ext, desired)) | 612 int should_try = 1; |
608 return(retval); | 613 const char **decoderExt = decoder->funcs->info.extensions; |
614 | |
615 /* skip if we would have tried decoder above... */ | |
616 while (*decoderExt) | |
617 { | |
618 if (__Sound_strcasecmp(*decoderExt, ext) == 0) | |
619 { | |
620 should_try = 0; | |
621 break; | |
622 } /* if */ | |
623 decoderExt++; | |
624 } /* while */ | |
625 | |
626 if (should_try) | |
627 { | |
628 if (init_sample(decoder->funcs, retval, ext, desired)) | |
629 return(retval); | |
630 } /* if */ | |
609 } /* if */ | 631 } /* if */ |
610 } /* for */ | 632 } /* for */ |
611 | 633 |
612 /* nothing could handle the sound data... */ | 634 /* nothing could handle the sound data... */ |
613 free(retval->opaque); | 635 free(retval->opaque); |
657 return; | 679 return; |
658 } /* if */ | 680 } /* if */ |
659 | 681 |
660 internal = (Sound_SampleInternal *) sample->opaque; | 682 internal = (Sound_SampleInternal *) sample->opaque; |
661 | 683 |
662 internal->funcs->close(sample); | 684 SDL_LockMutex(samplelist_mutex); |
663 | 685 |
664 /* update the samplesList... */ | 686 /* update the sample_list... */ |
665 if (internal->prev != NULL) | 687 if (internal->prev != NULL) |
666 { | 688 { |
667 Sound_SampleInternal *prevInternal; | 689 Sound_SampleInternal *prevInternal; |
668 prevInternal = (Sound_SampleInternal *) internal->prev->opaque; | 690 prevInternal = (Sound_SampleInternal *) internal->prev->opaque; |
669 prevInternal->next = internal->next; | 691 prevInternal->next = internal->next; |
670 } /* if */ | 692 } /* if */ |
671 else | 693 else |
672 { | 694 { |
673 assert(samplesList == sample); | 695 assert(sample_list == sample); |
674 samplesList = internal->next; | 696 sample_list = internal->next; |
675 } /* else */ | 697 } /* else */ |
676 | 698 |
677 if (internal->next != NULL) | 699 if (internal->next != NULL) |
678 { | 700 { |
679 Sound_SampleInternal *nextInternal; | 701 Sound_SampleInternal *nextInternal; |
680 nextInternal = (Sound_SampleInternal *) internal->next->opaque; | 702 nextInternal = (Sound_SampleInternal *) internal->next->opaque; |
681 nextInternal->prev = internal->prev; | 703 nextInternal->prev = internal->prev; |
682 } /* if */ | 704 } /* if */ |
683 | 705 |
706 SDL_UnlockMutex(samplelist_mutex); | |
707 | |
684 /* nuke it... */ | 708 /* nuke it... */ |
709 internal->funcs->close(sample); | |
710 | |
685 if (internal->rw != NULL) /* this condition is a "just in case" thing. */ | 711 if (internal->rw != NULL) /* this condition is a "just in case" thing. */ |
686 SDL_RWclose(internal->rw); | 712 SDL_RWclose(internal->rw); |
687 | 713 |
688 if ((internal->buffer != NULL) && (internal->buffer != sample->buffer)) | 714 if ((internal->buffer != NULL) && (internal->buffer != sample->buffer)) |
689 free(internal->buffer); | 715 free(internal->buffer); |