From: havoc Date: Sun, 2 Mar 2008 12:06:55 +0000 (+0000) Subject: added a parameter to S_StopChannel to trigger a mutex lock, this fixes X-Git-Tag: xonotic-v0.1.0preview~2348 X-Git-Url: http://git.xonotic.org/?a=commitdiff_plain;h=0cf2622e2b4e005dfc7b33e56889736234dbdae5;p=xonotic%2Fdarkplaces.git added a parameter to S_StopChannel to trigger a mutex lock, this fixes crashes in the SDL audio callback when S_StopChannel clears fields while they are being used in the mixer (this mostly crashed on level changes), the mutex lock itself is done simply by calling SndSys_LockRenderBuffer git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8176 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cd_shared.c b/cd_shared.c index 5eeadaed..0f5a3ade 100644 --- a/cd_shared.c +++ b/cd_shared.c @@ -171,7 +171,7 @@ void CDAudio_Play_byName (const char *trackname, qboolean looping) Con_Print("Could not load BGM track.\n"); return; } - + if (!cdValid) { CDAudio_GetAudioDiskInfo(); @@ -214,7 +214,7 @@ void CDAudio_Stop (void) if (faketrack != -1) { - S_StopChannel (faketrack); + S_StopChannel (faketrack, true); faketrack = -1; } else if (cdPlaying && (CDAudio_SysStop() == -1)) diff --git a/dpvsimpledecode.c b/dpvsimpledecode.c index 7519c3f6..6cbc44ea 100644 --- a/dpvsimpledecode.c +++ b/dpvsimpledecode.c @@ -369,7 +369,7 @@ void *dpvsimpledecode_open(char *filename, char **errorstring) if (s->videopixels != NULL) { size_t namelen; - + namelen = strlen(filename) + 10; wavename = (char *)Z_Malloc(namelen); if (wavename) @@ -424,7 +424,7 @@ void dpvsimpledecode_close(void *stream) if (s->videopixels) Z_Free(s->videopixels); if (s->sndchan != -1) - S_StopChannel (s->sndchan); + S_StopChannel (s->sndchan, true); if (s->framedatablocks) hz_bitstream_read_blocks_free(s->framedatablocks); if (s->bitstream) diff --git a/snd_main.c b/snd_main.c index 84e2469e..251a8590 100644 --- a/snd_main.c +++ b/snd_main.c @@ -896,7 +896,7 @@ void S_FreeSfx (sfx_t *sfx, qboolean force) // Stop all channels using this sfx for (i = 0; i < total_channels; i++) if (channels[i].sfx == sfx) - S_StopChannel (i); + S_StopChannel (i, true); // Free it if (sfx->fetcher != NULL && sfx->fetcher->free != NULL) @@ -1082,7 +1082,7 @@ channel_t *SND_PickChannel(int entnum, int entchannel) if (ch->entnum == entnum && (ch->entchannel == entchannel || entchannel == -1) ) { // always override sound from same entity - S_StopChannel (ch_idx); + S_StopChannel (ch_idx, true); return &channels[ch_idx]; } } @@ -1196,9 +1196,10 @@ void SND_Spatialize(channel_t *ch, qboolean isstatic) void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, vec3_t origin, float fvol, float attenuation, qboolean isstatic) { // Initialize the channel + // We MUST set sfx LAST because otherwise we could crash a threaded mixer + // (otherwise we'd have to call SndSys_LockRenderBuffer here) memset (target_chan, 0, sizeof (*target_chan)); VectorCopy (origin, target_chan->origin); - target_chan->sfx = sfx; target_chan->flags = flags; target_chan->pos = 0; // start of the sound @@ -1215,7 +1216,12 @@ void S_PlaySfxOnChannel (sfx_t *sfx, channel_t *target_chan, unsigned int flags, // Lock the SFX during play S_LockSfx (sfx); - // and finally, apply the volume + // finally, set the sfx pointer, so the channel becomes valid for playback + // and will be noticed by the mixer + target_chan->sfx = sfx; + + // we have to set the channel volume AFTER the sfx because the function + // needs it for replaygain support S_SetChannelVolume(target_chan - channels, fvol); } @@ -1260,7 +1266,7 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f return (target_chan - channels); } -void S_StopChannel (unsigned int channel_ind) +void S_StopChannel (unsigned int channel_ind, qboolean lockmutex) { channel_t *ch; @@ -1272,6 +1278,12 @@ void S_StopChannel (unsigned int channel_ind) { sfx_t *sfx = ch->sfx; + // we have to lock an audio mutex to prevent crashes if an audio mixer + // thread is currently mixing this channel + // the SndSys_LockRenderBuffer function uses such a mutex in + // threaded sound backends + if (lockmutex) + SndSys_LockRenderBuffer(); if (sfx->fetcher != NULL) { snd_fetcher_endsb_t fetcher_endsb = sfx->fetcher->endsb; @@ -1284,6 +1296,8 @@ void S_StopChannel (unsigned int channel_ind) ch->fetcher_data = NULL; ch->sfx = NULL; + if (lockmutex) + SndSys_UnlockRenderBuffer(); } } @@ -1313,7 +1327,7 @@ void S_StopSound(int entnum, int entchannel) for (i = 0; i < MAX_DYNAMIC_CHANNELS; i++) if (channels[i].entnum == entnum && channels[i].entchannel == entchannel) { - S_StopChannel (i); + S_StopChannel (i, true); return; } } @@ -1331,7 +1345,7 @@ void S_StopAllSounds (void) CDAudio_Stop(); for (i = 0; i < total_channels; i++) - S_StopChannel (i); + S_StopChannel (i, true); total_channels = MAX_DYNAMIC_CHANNELS + NUM_AMBIENTS; // no statics memset(channels, 0, MAX_CHANNELS * sizeof(channel_t)); diff --git a/snd_mix.c b/snd_mix.c index d7a62553..2fa5878e 100644 --- a/snd_mix.c +++ b/snd_mix.c @@ -513,7 +513,7 @@ void S_MixToBuffer(void *stream, unsigned int bufferframes) ch->pos = 0; else { - S_StopChannel (ch - channels); + S_StopChannel (ch - channels, false); break; } } diff --git a/snd_null.c b/snd_null.c index 22a606da..1ed1cc81 100755 --- a/snd_null.c +++ b/snd_null.c @@ -62,7 +62,7 @@ int S_StartSound (int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f return -1; } -void S_StopChannel (unsigned int channel_ind) +void S_StopChannel (unsigned int channel_ind, qboolean lockmutex) { } diff --git a/sound.h b/sound.h index 1889b87d..24961705 100644 --- a/sound.h +++ b/sound.h @@ -79,7 +79,7 @@ void S_StopSound (int entnum, int entchannel); void S_StopAllSounds (void); void S_PauseGameSounds (qboolean toggle); -void S_StopChannel (unsigned int channel_ind); +void S_StopChannel (unsigned int channel_ind, qboolean lockmutex); qboolean S_SetChannelFlag (unsigned int ch_ind, unsigned int flag, qboolean value); void S_SetChannelVolume (unsigned int ch_ind, float fvol);