From cc12f08b1a05b4b637e4924dd2936a727cc2b82b Mon Sep 17 00:00:00 2001 From: Giel van Schijndel Date: Sun, 9 Dec 2007 22:36:06 +0000 Subject: [PATCH] * Apply patch #879 by Buginator with some heavy modifications by me * Upon removing BASE_OBJECTs loop through the lists of outstanding AUDIO_SAMPLEs to delete all of those that refer to this BASE_OBJECT git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@3023 4a71c877-e1ca-e34f-864e-861f7616d084 --- lib/sound/audio.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++ lib/sound/audio.h | 1 + src/objmem.c | 5 ++++ 3 files changed, 82 insertions(+) diff --git a/lib/sound/audio.c b/lib/sound/audio.c index 553793ba9..79d5cc209 100644 --- a/lib/sound/audio.c +++ b/lib/sound/audio.c @@ -988,3 +988,79 @@ SDWORD audio_GetTrackID( const char *fileName ) return sound_GetTrackID( psTrack ); } + +/** Loop through the list of playing and queued audio samples, and destroy any + * of them that refer to the given object. + * \param psObj pointer to the object for which we must destroy all of its + * outstanding audio samples. + */ +void audio_RemoveObj(const void* psObj) +{ + unsigned int count = 0; + + // loop through queued sounds and check if a sample needs to be removed + AUDIO_SAMPLE *psSample = g_psSampleQueue; + while (psSample != NULL) + { + if (psSample->psObj == psObj) + { + // The current audio sample seems to refer to an object + // that is about to be destroyed. So destroy this + // sample as well. + AUDIO_SAMPLE* toRemove = psSample; + + // Make sure to keep our linked list iterator valid + psSample = psSample->psNext; + + // Perform the actual task of destroying this sample + audio_RemoveSample(&g_psSampleQueue, toRemove); + free(psSample); + + // Increment the deletion count + ++count; + } + else + { + psSample = psSample->psNext; + } + } + + if (count) + debug(LOG_MEMORY, "audio_RemoveObj: BASE_OBJECT* 0x%p was found %u times in the audio sample queue", psObj, count); + + // Reset the deletion count + count = 0; + + // loop through list of currently playing sounds and check if a sample needs to be removed + psSample = g_psSampleList; + while (psSample != NULL) + { + if (psSample->psObj == psObj) + { + // The current audio sample seems to refer to an object + // that is about to be destroyed. So destroy this + // sample as well. + AUDIO_SAMPLE* toRemove = psSample; + + // Make sure to keep our linked list iterator valid + psSample = psSample->psNext; + + // Stop this sound sample + sound_StopTrack(psSample); + + // Perform the actual task of destroying this sample + audio_RemoveSample(&g_psSampleList, toRemove); + free(psSample); + + // Increment the deletion count + ++count; + } + else + { + psSample = psSample->psNext; + } + } + + if (count) + debug(LOG_MEMORY, "audio_RemoveObj: ***Warning! psOBJ %p was found %u times in the list of playing audio samples", psObj, count); +} diff --git a/lib/sound/audio.h b/lib/sound/audio.h index 39cd62875..f8a9e6840 100644 --- a/lib/sound/audio.h +++ b/lib/sound/audio.h @@ -68,6 +68,7 @@ extern void audio_ResumeAll( void ); extern void audio_StopAll( void ); extern SDWORD audio_GetTrackID( const char *fileName ); +extern void audio_RemoveObj(const void* psObj); /***************************************************************************/ diff --git a/src/objmem.c b/src/objmem.c index 84243b0e0..e173e5482 100644 --- a/src/objmem.c +++ b/src/objmem.c @@ -26,6 +26,7 @@ #include #include "lib/framework/frame.h" +#include "lib/sound/audio.h" #include "objects.h" #include "deliverance.h" #include "lib/gamelib/gtime.h" @@ -119,7 +120,11 @@ static void objmemDestroy(BASE_OBJECT *psObj) default: ASSERT(!"unknown object type", "objmemDestroy: unknown object type in destroyed list at 0x%p", psObj); } + // Make sure to get rid of some final references in the sound code to this object first + audio_RemoveObj(psObj); + free(psObj); + debug(LOG_MEMORY, "objmemDestroy: BASE_OBJECT* 0x%p is freed.", psObj); } /* General housekeeping for the object system */