Here’s the (hopefully) correct patch to fix SDL_mixer’s LockAudio
behaviour.
I’ve also added some comments to SDL_mixer.h about not locking audio in
various effect callbacks, etc.
–ryan.
-------------- next part --------------
diff -u -r1.15 SDL_mixer.h
— SDL_mixer.h 2002/01/14 19:35:45 1.15
+++ SDL_mixer.h 2002/03/31 02:39:42
@@ -141,15 +141,19 @@
extern DECLSPEC void Mix_HookMusic(void (*mix_func)
(void *udata, Uint8 *stream, int len), void *arg);
-/* Add your own callback when the music has finished playing.
-
/
+/ Add your own callback when the music has finished playing. */
extern DECLSPEC void Mix_HookMusicFinished(void (*music_finished)(void));
/* Get a pointer to the user data for the current music hook */
extern DECLSPEC void *Mix_GetMusicHookData(void);
-/* Add your own callback when a channel has finished playing. NULL
-
- to disable callback.
+/*
- to disable callback.
-
- Add your own callback when a channel has finished playing. NULL
-
- to disable callback. The callback may be called from the mixer’s audio
-
- callback or it could be called as a result of Mix_HaltChannel(), etc.
-
- do not call SDL_LockAudio() from this callback; you will either be
-
- inside the audio callback, or SDL_mixer will explicitly lock the audio
-
- before calling your callback.
*/
extern DECLSPEC void Mix_ChannelFinished(void (*channel_finished)(int channel));
- before calling your callback.
@@ -172,6 +176,8 @@
- down the mixing pipeline, through any other effect functions, then finally
- to be mixed with the rest of the channels and music for the final output
- stream.
-
-
- DO NOT EVER call SDL_LockAudio() from your callback function!
*/
typedef void (*Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata);
- DO NOT EVER call SDL_LockAudio() from your callback function!
@@ -181,6 +187,8 @@
- plays out normally, or if you call Mix_HaltChannel(), implicitly stop
- a channel via Mix_AllocateChannels(), or unregister a callback while
- it’s still playing.
-
-
- DO NOT EVER call SDL_LockAudio() from your callback function!
*/
typedef void (*Mix_EffectDone_t)(int chan, void *udata);
- DO NOT EVER call SDL_LockAudio() from your callback function!
@@ -226,11 +234,13 @@
- through Mix_SetPostMix() runs, and then the stream goes to the audio
- device.*
-
- DO NOT EVER call SDL_LockAudio() from your callback function!
-
- returns zero if error (no such channel), nonzero if added.
- Error messages can be retrieved from Mix_GetError().
*/
extern DECLSPEC int Mix_RegisterEffect(int chan, Mix_EffectFunc_t f,
-
Mix_EffectDone_t d, void *arg);
-
Mix_EffectDone_t d, void *arg);
/* You may not need to call this explicitly, unless you need to stop an
diff -u -r1.35 mixer.c
— mixer.c 2002/03/24 02:06:12 1.35
+++ mixer.c 2002/03/31 02:39:44
@@ -40,7 +40,6 @@
#define FORM 0x4d524f46 /* “FORM” */
static int audio_opened = 0;
static SDL_AudioSpec mixer;
static SDL_mutex *mixer_lock;
@@ -101,15 +100,28 @@
return(&linked_mixver);
}
+static int _Mix_remove_all_effects(int channel, effect_info **e);
/* rcg06122001 Cleanup effect callbacks. */
-static void Mix_ChannelDonePlaying(int channel)
+static void _Mix_channel_done_playing(int channel, int lockaudio)
{
- if (lockaudio) {
-
SDL_LockAudio();
- }
- if (channel_done_callback) {
channel_done_callback(channel);
}
- Mix_UnregisterAllEffects(channel);
- /*
-
* Call internal function directly, to avoid locking audio from
-
* inside audio callback.
-
*/
- _Mix_remove_all_effects(channel, &mix_channel[channel].effects);
- if (lockaudio) {
-
SDL_UnlockAudio();
- }
}
@@ -223,7 +235,7 @@
/* rcg06072001 Alert app if channel is done playing. */
if (!mix_channel[i].playing) {
-
Mix_ChannelDonePlaying(i);
-
_Mix_channel_done_playing(i, 0); } } }
@@ -622,7 +634,7 @@
if ( which >= 0 ) {
Uint32 sdl_ticks = SDL_GetTicks();
if (Mix_Playing(which))
-
Mix_ChannelDonePlaying(which);
-
_Mix_channel_done_playing(which, 1); mix_channel[which].samples = chunk->abuf; mix_channel[which].playing = chunk->alen; mix_channel[which].looping = loops;
@@ -688,7 +700,7 @@
if ( which >= 0 ) {
Uint32 sdl_ticks = SDL_GetTicks();
if (Mix_Playing(which))
-
Mix_ChannelDonePlaying(which);
-
_Mix_channel_done_playing(which, 1); mix_channel[which].samples = chunk->abuf; mix_channel[which].playing = chunk->alen; mix_channel[which].looping = loops;
@@ -758,7 +770,7 @@
} else {
SDL_mutexP(mixer_lock);
if (mix_channel[which].playing) {
-
Mix_ChannelDonePlaying(which);
-
_Mix_channel_done_playing(which, 1); mix_channel[which].playing = 0; } mix_channel[which].expire = 0;
@@ -1043,8 +1055,9 @@
- as Mix_SetPanning().
*/
+/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
static int _Mix_register_effect(effect_info **e, Mix_EffectFunc_t f,
-
Mix_EffectDone_t d, void *arg)
-
Mix_EffectDone_t d, void *arg)
{
effect_info *new_e = malloc(sizeof (effect_info));
@@ -1068,8 +1081,6 @@
new_e->udata = arg;
new_e->next = NULL;
-
SDL_LockAudio();
-
/* add new effect to end of linked list… */
if (*e == NULL) {
*e = new_e;
@@ -1084,11 +1095,11 @@
}
} -
SDL_UnlockAudio();
return(1);
}
+/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
static int _Mix_remove_effect(int channel, effect_info **e, Mix_EffectFunc_t f)
{
effect_info *cur;
@@ -1100,7 +1111,6 @@
return(0);
}
-
SDL_LockAudio();
for (cur = *e; cur != NULL; cur = cur->next) {
if (cur->callback == f) {
next = cur->next;
@@ -1114,18 +1124,17 @@
} else {
prev->next = next;
} -
SDL_UnlockAudio(); return(1); } prev = cur;
}
-
SDL_UnlockAudio();
Mix_SetError(“No such effect registered”);
return(0);
}
+/* MAKE SURE you hold the audio lock (SDL_LockAudio()) before calling this! */
static int _Mix_remove_all_effects(int channel, effect_info **e)
{
effect_info *cur;
@@ -1136,7 +1145,6 @@
return(0);
}
-
SDL_LockAudio();
for (cur = *e; cur != NULL; cur = next) {
next = cur->next;
if (cur->done_callback != NULL) {
@@ -1145,16 +1153,16 @@
free(cur);
}
*e = NULL; -
SDL_UnlockAudio();
return(1);
}
int Mix_RegisterEffect(int channel, Mix_EffectFunc_t f,
-
Mix_EffectDone_t d, void *arg)
-
Mix_EffectDone_t d, void *arg)
{
effect_info **e = NULL;
-
int retval;
if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1166,13 +1174,17 @@
e = &mix_channel[channel].effects;
}
- return(_Mix_register_effect(e, f, d, arg));
- SDL_LockAudio();
- retval = _Mix_register_effect(e, f, d, arg);
- SDL_UnlockAudio();
- return(retval);
}
int Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f)
{
effect_info **e = NULL;
-
int retval;
if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1183,13 +1195,18 @@
}
e = &mix_channel[channel].effects;
}
- return(_Mix_remove_effect(channel, e, f));
- SDL_LockAudio();
- retval = _Mix_remove_effect(channel, e, f);
- SDL_UnlockAudio();
- return(retval);
}
int Mix_UnregisterAllEffects(int channel)
{
effect_info **e = NULL;
-
int retval;
if (channel == MIX_CHANNEL_POST) {
e = &posteffects;
@@ -1201,7 +1218,10 @@
e = &mix_channel[channel].effects;
}
- return(_Mix_remove_all_effects(channel, e));
- SDL_LockAudio();
- retval = _Mix_remove_all_effects(channel, e);
- SDL_UnlockAudio();
- return(retval);
}
/* end of mixer.c … */