diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index 314a8b8770c..3871e6efff6 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -321,6 +321,10 @@ class MilesAudioManager : public AudioManager UnsignedInt m_num3DSamples; UnsignedInt m_numStreams; + // Mutex to protect access to m_playingSounds, m_playing3DSounds, m_playingStreams from + // concurrent access by the Miles Audio callback thread and the main game thread + HANDLE m_playingAudioMutex; + #if defined(RTS_DEBUG) typedef std::set SetAsciiString; typedef SetAsciiString::iterator SetAsciiStringIt; diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 973669ed6b4..1d3eb6e5337 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -92,9 +92,11 @@ MilesAudioManager::MilesAudioManager() : m_delayFilter(NULL), m_binkHandle(NULL), m_pref3DProvider(AsciiString::TheEmptyString), - m_prefSpeaker(AsciiString::TheEmptyString) + m_prefSpeaker(AsciiString::TheEmptyString), + m_playingAudioMutex(NULL) { m_audioCache = NEW AudioFileCache; + m_playingAudioMutex = CreateMutex(NULL, FALSE, NULL); } //------------------------------------------------------------------------------------------------- @@ -105,6 +107,11 @@ MilesAudioManager::~MilesAudioManager() closeDevice(); delete m_audioCache; + if (m_playingAudioMutex) { + CloseHandle(m_playingAudioMutex); + m_playingAudioMutex = NULL; + } + DEBUG_ASSERTCRASH(this == TheAudio, ("Umm...")); TheAudio = NULL; } @@ -496,6 +503,7 @@ void MilesAudioManager::stopAudio( AudioAffect which ) // 3) Set the status to stopped, so that when we next process the playing list, we will // correctly clean up the sample. + ScopedMutex lock(m_playingAudioMutex); std::list::iterator it; @@ -546,6 +554,8 @@ void MilesAudioManager::stopAudio( AudioAffect which ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::pauseAudio( AudioAffect which ) { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing = NULL; @@ -607,6 +617,8 @@ void MilesAudioManager::pauseAudio( AudioAffect which ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::resumeAudio( AudioAffect which ) { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing = NULL; @@ -901,6 +913,8 @@ void MilesAudioManager::stopAudioEvent( AudioHandle handle ) DEBUG_LOG(("MILES (%d) - Processing stop request: %d", TheGameLogic->getFrame(), handle)); #endif + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; if ( handle == AHSV_StopTheMusic || handle == AHSV_StopTheMusicFade ) { // for music, just find the currently playing music stream and kill it. @@ -985,6 +999,8 @@ void MilesAudioManager::killAudioEventImmediately( AudioHandle audioEvent ) } } + ScopedMutex lock(m_playingAudioMutex); + //Look for matching 3D sound to kill std::list::iterator it; for( it = m_playing3DSounds.begin(); it != m_playing3DSounds.end(); it++ ) @@ -1129,6 +1145,8 @@ void MilesAudioManager::releasePlayingAudio( PlayingAudio *release ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::stopAllAudioImmediately( void ) { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing; @@ -1333,12 +1351,15 @@ void MilesAudioManager::initFilters3D( H3DSAMPLE sample, const AudioEventRTS *ev void MilesAudioManager::nextMusicTrack( void ) { AsciiString trackName; - std::list::iterator it; - PlayingAudio *playing; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - trackName = playing->m_audioEventRTS->getEventName(); + { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; + PlayingAudio *playing; + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + trackName = playing->m_audioEventRTS->getEventName(); + } } } @@ -1354,12 +1375,15 @@ void MilesAudioManager::nextMusicTrack( void ) void MilesAudioManager::prevMusicTrack( void ) { AsciiString trackName; - std::list::iterator it; - PlayingAudio *playing; - for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { - playing = *it; - if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { - trackName = playing->m_audioEventRTS->getEventName(); + { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; + PlayingAudio *playing; + for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { + playing = *it; + if (playing && playing->m_audioEventRTS->getAudioEventInfo()->m_soundType == AT_Music) { + trackName = playing->m_audioEventRTS->getEventName(); + } } } @@ -1374,6 +1398,8 @@ void MilesAudioManager::prevMusicTrack( void ) //------------------------------------------------------------------------------------------------- Bool MilesAudioManager::isMusicPlaying( void ) const { + ScopedMutex lock(m_playingAudioMutex); + std::list::const_iterator it; PlayingAudio *playing; for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { @@ -1389,6 +1415,8 @@ Bool MilesAudioManager::isMusicPlaying( void ) const //------------------------------------------------------------------------------------------------- Bool MilesAudioManager::hasMusicTrackCompleted( const AsciiString& trackName, Int numberOfTimes ) const { + ScopedMutex lock(m_playingAudioMutex); + std::list::const_iterator it; PlayingAudio *playing; for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { @@ -1424,6 +1452,8 @@ AsciiString MilesAudioManager::getMusicTrackName( void ) const } } + ScopedMutex lock(m_playingAudioMutex); + std::list::const_iterator it; PlayingAudio *playing; for (it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) { @@ -1486,6 +1516,8 @@ void MilesAudioManager::closeDevice( void ) //------------------------------------------------------------------------------------------------- Bool MilesAudioManager::isCurrentlyPlaying( AudioHandle handle ) { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing; @@ -1526,6 +1558,9 @@ Bool MilesAudioManager::isCurrentlyPlaying( AudioHandle handle ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::notifyOfAudioCompletion( UnsignedInt audioCompleted, UnsignedInt flags ) { + // Protect access to playing audio lists from concurrent modification by main thread + ScopedMutex lock(m_playingAudioMutex); + PlayingAudio *playing = findPlayingAudioFrom(audioCompleted, flags); if (!playing) { DEBUG_CRASH(("Audio has completed playing, but we can't seem to find it. - jkmcd")); @@ -2098,6 +2133,8 @@ Bool MilesAudioManager::killLowestPrioritySoundImmediately( AudioEventRTS *event //------------------------------------------------------------------------------------------------- void MilesAudioManager::adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) { + ScopedMutex lock(m_playingAudioMutex); + Real pan; std::list::iterator it; @@ -2139,6 +2176,8 @@ void MilesAudioManager::adjustVolumeOfPlayingAudio(AsciiString eventName, Real n //------------------------------------------------------------------------------------------------- void MilesAudioManager::removePlayingAudio( AsciiString eventName ) { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing = NULL; @@ -2188,6 +2227,8 @@ void MilesAudioManager::removePlayingAudio( AsciiString eventName ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::removeAllDisabledAudio() { + ScopedMutex lock(m_playingAudioMutex); + std::list::iterator it; PlayingAudio *playing = NULL; @@ -2261,6 +2302,9 @@ void MilesAudioManager::processRequestList( void ) //------------------------------------------------------------------------------------------------- void MilesAudioManager::processPlayingList( void ) { + // Protect access to playing audio lists from concurrent modification by callback thread + ScopedMutex lock(m_playingAudioMutex); + // There are two types of processing we have to do here. // 1. Move the item to the stopped list if it has become stopped. // 2. Update the position of the audio if it is positional @@ -2400,6 +2444,8 @@ void MilesAudioManager::processPlayingList( void ) Bool MilesAudioManager::has3DSensitiveStreamsPlaying( void ) const { + ScopedMutex lock(m_playingAudioMutex); + if ( m_playingStreams.empty() ) return FALSE;