diff --git a/stepmania/src/RageSoundManager.cpp b/stepmania/src/RageSoundManager.cpp index cf8015d8ea..0d91ec21f2 100644 --- a/stepmania/src/RageSoundManager.cpp +++ b/stepmania/src/RageSoundManager.cpp @@ -8,6 +8,8 @@ #include "RageSound.h" #include "RageLog.h" #include "RageTimer.h" +#include "RageSoundReader_Preload.h" +#include "Foreach.h" #include "arch/Sound/RageSoundDriver.h" @@ -97,8 +99,30 @@ void RageSoundManager::Update( float fDeltaTime ) { FlushPosMapQueue(); + /* Scan m_mapPreloadedSounds for sounds that are no longer loaded, and delete them. */ + g_SoundManMutex.Lock(); /* lock for access to m_mapPreloadedSounds, owned_sounds */ + { + map::iterator it, next; + it = m_mapPreloadedSounds.begin(); + + while( it != m_mapPreloadedSounds.end() ) + { + next = it; ++next; + if( it->second->GetReferenceCount() == 1 ) + { + LOG->Trace( "Deleted old sound \"%s\"", it->first.c_str() ); + delete it->second; + m_mapPreloadedSounds.erase( it ); + } + else + LOG->Trace( "Kept sound \"%s\" (%i)", it->first.c_str(), + it->second->GetReferenceCount() ); + + it = next; + } + } + /* Scan the owned_sounds list for sounds that are no longer playing, and delete them. */ - g_SoundManMutex.Lock(); /* lock for access to owned_sounds */ set ToDelete; for( set::iterator it = owned_sounds.begin(); it != owned_sounds.end(); ++it ) { @@ -256,6 +280,41 @@ void RageSoundManager::DeleteSoundWhenFinished( RageSound *pSound ) g_SoundManMutex.Unlock(); /* finished with owned_sounds */ } +/* If the given path is loaded, return a copy; otherwise return NULL. + * It's the caller's responsibility to delete the result. */ +SoundReader *RageSoundManager::GetLoadedSound( const CString &sPath_ ) +{ + LockMut(g_SoundManMutex); /* lock for access to m_mapPreloadedSounds */ + + CString sPath(sPath_); + sPath.MakeLower(); + map::const_iterator it; + it = m_mapPreloadedSounds.find( sPath ); + if( it == m_mapPreloadedSounds.end() ) + return NULL; + + return it->second->Copy(); +} + +/* Add the sound to the set of loaded sounds that can be copied for reuse. + * The sound will be kept in memory as long as there are any other references + * to it; once we hold the last one, we'll release it. */ +void RageSoundManager::AddLoadedSound( const CString &sPath_, RageSoundReader_Preload *pSound ) +{ + LockMut(g_SoundManMutex); /* lock for access to m_mapPreloadedSounds */ + + /* Don't AddLoadedSound a sound that's already registered. It should have been + * used in GetLoadedSound. */ + CString sPath(sPath_); + sPath.MakeLower(); + map::const_iterator it; + it = m_mapPreloadedSounds.find( sPath ); + ASSERT_M( it == m_mapPreloadedSounds.end(), sPath ); + + m_mapPreloadedSounds[sPath] = (RageSoundReader_Preload *) pSound->Copy(); +} + + /* Don't hold the lock when we don't have to. We call this function from other * threads, to avoid stalling the gameplay thread. */ void RageSoundManager::PlayOnce( CString sPath ) diff --git a/stepmania/src/RageSoundManager.h b/stepmania/src/RageSoundManager.h index 8131f03a36..7b5a242e34 100644 --- a/stepmania/src/RageSoundManager.h +++ b/stepmania/src/RageSoundManager.h @@ -11,6 +11,8 @@ class RageSound; class RageSoundBase; class RageSoundDriver; struct RageSoundParams; +class SoundReader; +class RageSoundReader_Preload; class RageSoundManager { @@ -46,6 +48,9 @@ public: void DeleteSound( RageSound *pSound ); void DeleteSoundWhenFinished( RageSound *pSound ); + SoundReader *GetLoadedSound( const CString &sPath ); + void AddLoadedSound( const CString &sPath, RageSoundReader_Preload *pSound ); + void PlayOnce( CString sPath ); RageSound *PlaySound( RageSound &snd, const RageSoundParams *params = NULL ); @@ -60,7 +65,9 @@ private: /* A list of all sounds that currently exist, by ID. */ map all_sounds; - + + map m_mapPreloadedSounds; + RageSoundDriver *m_pDriver; /* Prefs: */