[Fix] Possible race condition and improved sound_exit correctness.

This commit is contained in:
Allanis 2013-10-03 01:08:38 +01:00
parent 62f7986459
commit 2cade50bc9

View File

@ -7,6 +7,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <SDL.h> #include <SDL.h>
#include <SDL_thread.h>
#include <SDL/SDL_mixer.h> #include <SDL/SDL_mixer.h>
#include "lephisto.h" #include "lephisto.h"
@ -72,8 +73,9 @@ static alSound* sound_list = NULL; /**< List of available sounds. */
static int sound_nlist = 0; /**< Number of available sounds. */ static int sound_nlist = 0; /**< Number of available sounds. */
/* Voice linked list. */ /* Voice linked list. */
static alVoice* voice_active; /**< Active voices. */ static SDL_mutex* voice_lock = NULL;
static alVoice* voice_pool; /**< Pool of free voices. */ static alVoice* voice_active = NULL; /**< Active voices. */
static alVoice* voice_pool = NULL; /**< Pool of free voices. */
/* General prototypes. */ /* General prototypes. */
static int sound_makeList(void); static int sound_makeList(void);
@ -128,6 +130,9 @@ int sound_init(void) {
/* Init the music. */ /* Init the music. */
music_init(); music_init();
/* Create the voice lock. */
voice_lock = SDL_CreateMutex();
return 0; return 0;
} }
@ -140,6 +145,10 @@ void sound_exit(void) {
int i; int i;
alVoice* v; alVoice* v;
/* Close the audio. */
Mix_CloseAudio();
SDL_DestroyMutex(voice_lock);
/* Free the voices. */ /* Free the voices. */
while(voice_active != NULL) { while(voice_active != NULL) {
v = voice_active; v = voice_active;
@ -198,7 +207,7 @@ int sound_play(int sound) {
if((sound < 0) || (sound > sound_nlist)) if((sound < 0) || (sound > sound_nlist))
return -1; return -1;
v = voice_new(); SDL_mutexP(voice_lock);
v->channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0); v->channel = Mix_PlayChannel(-1, sound_list[sound].buffer, 0);
@ -277,6 +286,8 @@ int sound_updatePos(int voice, double x, double y) {
if(sound_disabled) return 0; if(sound_disabled) return 0;
SDL_mutexP(voice_lock);
v = voice_get(voice); v = voice_get(voice);
if(v != NULL) { if(v != NULL) {
@ -291,9 +302,13 @@ int sound_updatePos(int voice, double x, double y) {
if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) { if(Mix_SetPosition(v->channel, (int)angle, (int)dist/10) < 0) {
WARN("Unable to set sound position: %s", Mix_GetError()); WARN("Unable to set sound position: %s", Mix_GetError());
SDL_mutexV(voice_lock);
return -1; return -1;
} }
} }
SDL_mutexV(voice_lock);
return 0; return 0;
} }
@ -310,6 +325,8 @@ int sound_update(void) {
if(voice_active == NULL) return 0; if(voice_active == NULL) return 0;
SDL_mutexP(voice_lock);
/* The actualy control loop. */ /* The actualy control loop. */
for(v = voice_active; v != NULL; v = v->next) { for(v = voice_active; v != NULL; v = v->next) {
/* Destroy and toss into pool. */ /* Destroy and toss into pool. */
@ -339,6 +356,9 @@ int sound_update(void) {
if(v == NULL) break; if(v == NULL) break;
} }
} }
SDL_mutexV(voice_lock);
return 0; return 0;
} }
@ -353,11 +373,15 @@ void sound_stop(int voice) {
if(sound_disabled) return; if(sound_disabled) return;
SDL_mutexP(voice_lock);
v = voice_get(voice); v = voice_get(voice);
if(v != NULL) { if(v != NULL) {
Mix_HaltChannel(v->channel); Mix_HaltChannel(v->channel);
v->state = VOICE_STOPPED; v->state = VOICE_STOPPED;
} }
SDL_mutexV(voice_lock);
} }
/** /**
@ -592,11 +616,15 @@ void sound_stopGroup(int group) {
static void voice_markStopped(int channel) { static void voice_markStopped(int channel) {
alVoice* v; alVoice* v;
SDL_mutexP(voice_lock);
for(v = voice_active; v != NULL; v = v->next) for(v = voice_active; v != NULL; v = v->next)
if(v->channel == channel) { if(v->channel == channel) {
v->state = VOICE_STOPPED; v->state = VOICE_STOPPED;
return; break;
} }
SDL_mutexV(voice_lock);
} }
/** /**