Moved all remaining music commands to be handled by sfx thread.

This commit is contained in:
hiker 2015-02-04 17:08:22 +11:00
parent 6aa9ff86a4
commit eb37092643
8 changed files with 207 additions and 89 deletions

View File

@ -76,6 +76,30 @@ private:
// The constructor is private so that the
// static create function must be used.
MusicInformation (const XMLNode *root, const std::string &filename);
// Declare the following functions private, but allow the SFXManager
// and music manager to access them. This makes sure that only the sfx thread calls
// openal/vorbis etc, and so makes it all thread safe.
private:
friend class SFXManager;
friend class MusicManager;
void update(float dt);
void startMusic();
void stopMusic();
void pauseMusic();
void resumeMusic();
void volumeMusic(float gain);
void switchToFastMusic();
void setTemporaryVolume(float gain);
// ------------------------------------------------------------------------
/** Resets a temporary volume change. */
void resetTemporaryVolume() { volumeMusic(m_adjusted_gain); }
// ------------------------------------------------------------------------
/** Sets the music to be waiting, i.e. startMusic still needs to be
* called. Used to pre-load track music during track loading time. */
void setMusicWaiting() { m_music_waiting = true; }
// ------------------------------------------------------------------------
public:
LEAK_CHECK()
@ -85,14 +109,6 @@ public:
~MusicInformation ();
static MusicInformation *create(const std::string &filename);
void addMusicToTracks();
void update(float dt);
void startMusic();
void stopMusic();
void pauseMusic();
void resumeMusic();
void volumeMusic(float gain);
void setTemporaryVolume(float gain);
void switchToFastMusic();
bool isPlaying() const;
// ------------------------------------------------------------------------
@ -109,13 +125,6 @@ public:
const std::string& getFastFilename() const { return m_fast_filename; }
// ------------------------------------------------------------------------
float getMaxPitch() const { return m_max_pitch; }
// ------------------------------------------------------------------------
/** Sets the music to be waiting, i.e. startMusic still needs to be
* called. Used to pre-load track music during track loading time. */
void setMusicWaiting () {m_music_waiting = true;}
// ------------------------------------------------------------------------
/** Resets a temporary volume change. */
void resetTemporaryVolume() { volumeMusic(m_adjusted_gain); }
}; // MusicInformation
#endif

View File

@ -159,6 +159,16 @@ void MusicManager::addMusicToTracks()
}
} // addMusicToTracks
//-----------------------------------------------------------------------------
/** Special shortcut vor overworld (which skips other phases where the music
* would normally be started.
*/
void MusicManager::startMusic()
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_START, m_current_music);
} // startMusic
//-----------------------------------------------------------------------------
/** Schedules the indicated music to be played next.
* \param mi Music information of the music to be played.
@ -182,7 +192,7 @@ void MusicManager::startMusic(MusicInformation* mi, bool start_right_now)
if(!mi || !UserConfigParams::m_music || !m_initialized) return;
mi->volumeMusic(m_masterGain);
mi->volumeMusic(m_master_gain);
SFXManager::get()->queue(start_right_now ? SFXManager::SFX_MUSIC_START
: SFXManager::SFX_MUSIC_WAITING,
mi);
@ -198,6 +208,59 @@ void MusicManager::stopMusic()
} // stopMusic
//-----------------------------------------------------------------------------
/** Insert a command into the sfx queue to pause the current music.
*/
void MusicManager::pauseMusic()
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_PAUSE, m_current_music);
} // pauseMusic
//-----------------------------------------------------------------------------
/** Inserts a resume current music event into the queue.
*/
void MusicManager::resumeMusic()
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_RESUME, m_current_music);
} // resumeMusic
//-----------------------------------------------------------------------------
/** Switches to fast (last lap ) music (if defined for the current music).
*/
void MusicManager::switchToFastMusic()
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_SWITCH_FAST,
m_current_music);
} // switchToFastMusic
//-----------------------------------------------------------------------------
/** Queues a command to temporarily change the volume. This is used to make
* the music a bit quieter while the 'last lap fanfare' is being played.
* \param gain The temporary volume value.
*/
void MusicManager::setTemporaryVolume(float gain)
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_SET_TMP_VOLUME,
m_current_music, gain);
} // setTemporaryVolume
//-----------------------------------------------------------------------------
/** Queues a command for the sfx manager to reset a temporary volume change.
*/
void MusicManager::resetTemporaryVolume()
{
if (m_current_music)
SFXManager::get()->queue(SFXManager::SFX_MUSIC_RESET_TMP_VOLUME,
m_current_music);
} // resetTemporaryVolume
//-----------------------------------------------------------------------------
/** Sets the master music volume.
* \param gain The volume.
*/
void MusicManager::setMasterMusicVolume(float gain)
{
if(gain > 1.0)
@ -205,15 +268,15 @@ void MusicManager::setMasterMusicVolume(float gain)
if(gain < 0.0f)
gain = 0.0f;
m_masterGain = gain;
if(m_current_music) m_current_music->volumeMusic(m_masterGain);
m_master_gain = gain;
if(m_current_music) m_current_music->volumeMusic(m_master_gain);
UserConfigParams::m_music_volume = m_masterGain;
UserConfigParams::m_music_volume = m_master_gain;
} // setMasterMusicVolume
//-----------------------------------------------------------------------------
/**
*/
/** @throw runtime_error if the music file could not be found/opened
*/
MusicInformation* MusicManager::getMusicInformation(const std::string& filename)
{
if(filename=="")
@ -229,7 +292,7 @@ MusicInformation* MusicManager::getMusicInformation(const std::string& filename)
MusicInformation *mi = MusicInformation::create(filename);
if(mi)
{
mi->volumeMusic(m_masterGain);
mi->volumeMusic(m_master_gain);
m_all_music[basename] = mi;
}
return mi;

View File

@ -42,42 +42,44 @@ private:
/** If the sound could not be initialized, e.g. if the player doesn't has
* a sound card, we want to avoid anything sound related so we crash the
* game. */
bool m_initialized;
std::map<std::string, MusicInformation*>
m_all_music;
bool m_initialized;
void loadMusicInformation();
float m_masterGain;
/** Stores all music information files (read from the .music files). */
std::map<std::string, MusicInformation*>
m_all_music;
float m_master_gain;
void loadMusicInformation();
void loadMusicFromOneDir(const std::string& dir);
public:
MusicManager();
virtual ~MusicManager();
MusicManager();
virtual ~MusicManager();
MusicInformation* getMusicInformation(const std::string& filename);
void addMusicToTracks();
void startMusic(MusicInformation* mi,
bool start_right_now=true);
void stopMusic();
bool initialized() const { return m_initialized; }
void pauseMusic() {if(m_current_music)
m_current_music->pauseMusic(); }
void resumeMusic() {if(m_current_music)
m_current_music->resumeMusic(); }
void switchToFastMusic() {if(m_current_music)
m_current_music->switchToFastMusic();}
void setMasterMusicVolume(float gain);
float getMasterMusicVolume() const { return m_masterGain; }
MusicInformation *getCurrentMusic() {return m_current_music; }
/**
* @throw runtime_error if the music file could not be found/opened
*/
MusicInformation *getMusicInformation(const std::string& filename);
void loadMusicFromOneDir(const std::string& dir);
void addMusicToTracks();
void clearCurrentMusic() { m_current_music = NULL; }
void startMusic();
void startMusic(MusicInformation* mi,
bool start_right_now=true);
void stopMusic();
void pauseMusic();
void resumeMusic();
void switchToFastMusic();
void setMasterMusicVolume(float gain);
void resetTemporaryVolume();
void setTemporaryVolume(float gain);
// ------------------------------------------------------------------------
/** Returns the master volume. */
float getMasterMusicVolume() const { return m_master_gain; }
// ------------------------------------------------------------------------
/** Returns if the music system is initialised. */
bool initialized() const { return m_initialized; }
// ------------------------------------------------------------------------
/** Returns the information object of the current music. */
MusicInformation* getCurrentMusic() { return m_current_music; }
// ------------------------------------------------------------------------
/** Stops and removes the current music. */
void clearCurrentMusic() { m_current_music = NULL; }
};
extern MusicManager* music_manager;

View File

@ -202,11 +202,25 @@ void SFXManager::queue(SFXCommands command, SFXBase *sfx, const Vec3 &p)
} // queue (Vec3)
//----------------------------------------------------------------------------
/** Queues a command for the music manager.
* \param mi The music for which the command is.
*/
void SFXManager::queue(SFXCommands command, MusicInformation *mi)
{
SFXCommand *sfx_command = new SFXCommand(command, mi);
queueCommand(sfx_command);
} // queue(MusicInformation)
//----------------------------------------------------------------------------
/** Queues a command for the music manager that takes a floating point value
* (e.g. setTemporaryVolume).
* \param mi The music for which the command is.
* \param f The floating point parameter.
*/
void SFXManager::queue(SFXCommands command, MusicInformation *mi, float f)
{
SFXCommand *sfx_command = new SFXCommand(command, mi, f);
queueCommand(sfx_command);
} // queue(MusicInformation)
//----------------------------------------------------------------------------
/** Enqueues a command to the sfx queue threadsafe. Then signal the
@ -286,40 +300,57 @@ void* SFXManager::mainLoop(void *obj)
break;
}
me->m_sfx_commands.unlock();
switch(current->m_command)
switch (current->m_command)
{
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
case SFX_PLAY: current->m_sfx->reallyPlayNow(); break;
case SFX_STOP: current->m_sfx->reallyStopNow(); break;
case SFX_PAUSE: current->m_sfx->reallyPauseNow(); break;
case SFX_RESUME: current->m_sfx->reallyResumeNow(); break;
case SFX_SPEED: current->m_sfx->reallySetSpeed(
current->m_parameter.getX()); break;
current->m_parameter.getX()); break;
case SFX_POSITION: current->m_sfx->reallySetPosition(
current->m_parameter); break;
current->m_parameter); break;
case SFX_VOLUME: current->m_sfx->reallySetVolume(
current->m_parameter.getX()); break;
case SFX_MASTER_VOLUME:
current->m_sfx->reallySetMasterVolumeNow(
current->m_parameter.getX()); break;
current->m_parameter.getX()); break;
case SFX_MASTER_VOLUME:
current->m_sfx->reallySetMasterVolumeNow(
current->m_parameter.getX()); break;
case SFX_LOOP: current->m_sfx->reallySetLoop(
current->m_parameter.getX()!=0); break;
case SFX_DELETE: {
me->deleteSFX(current->m_sfx); break;
}
case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
case SFX_UPDATE: me->reallyUpdateNow(current); break;
current->m_parameter.getX() != 0); break;
case SFX_DELETE: me->deleteSFX(current->m_sfx); break;
case SFX_PAUSE_ALL: me->reallyPauseAllNow(); break;
case SFX_RESUME_ALL: me->reallyResumeAllNow(); break;
case SFX_LISTENER: me->reallyPositionListenerNow(); break;
case SFX_UPDATE: me->reallyUpdateNow(current); break;
case SFX_MUSIC_START:
current->m_music_information->startMusic(); break;
current->m_music_information->startMusic(); break;
case SFX_MUSIC_STOP:
current->m_music_information->stopMusic(); break;
case SFX_MUSIC_WAITING:
current->m_music_information->setMusicWaiting(); break;
current->m_music_information->stopMusic(); break;
case SFX_MUSIC_PAUSE:
current->m_music_information->pauseMusic(); break;
case SFX_MUSIC_RESUME:
current->m_music_information->resumeMusic(); break;
case SFX_MUSIC_SWITCH_FAST:
current->m_music_information->switchToFastMusic(); break;
case SFX_MUSIC_SET_TMP_VOLUME:
{
MusicInformation *mi = current->m_music_information;
mi->setTemporaryVolume(current->m_parameter.getX()); break;
}
case SFX_MUSIC_RESET_TMP_VOLUME:
{
MusicInformation *mi = current->m_music_information;
mi->resetTemporaryVolume(); break;
}
case SFX_MUSIC_WAITING:
current->m_music_information->setMusicWaiting(); break;
default: assert("Not yet supported.");
}
delete current;
current = NULL;
static SFXCommand *prev = NULL;
delete prev;
prev = current;
//delete current;
//current = NULL;
me->m_sfx_commands.lock();
} // while
@ -622,7 +653,7 @@ void SFXManager::deleteSFXMapping(const std::string &name)
*/
void SFXManager::update(float dt)
{
queue(SFX_UPDATE, NULL, dt);
queue(SFX_UPDATE, (SFXBase*)NULL, dt);
// Wake up the sfx thread to handle all queued up audio commands.
pthread_cond_signal(&m_cond_request);
} // update

View File

@ -79,7 +79,11 @@ public:
SFX_UPDATE,
SFX_MUSIC_START,
SFX_MUSIC_STOP,
SFX_MUSIC_UPDATE,
SFX_MUSIC_PAUSE,
SFX_MUSIC_RESUME,
SFX_MUSIC_SWITCH_FAST,
SFX_MUSIC_SET_TMP_VOLUME,
SFX_MUSIC_RESET_TMP_VOLUME,
SFX_MUSIC_WAITING,
SFX_EXIT,
}; // SFXCommands
@ -135,7 +139,16 @@ private:
{
m_command = command;
m_music_information = mi;
} // SFXCommnd
} // SFXCommnd(MusicInformation*)
// --------------------------------------------------------------------
/** Constructor for music information commands that take a floating
* point parameter (which is stored in the X value of m_parameter). */
SFXCommand(SFXCommands command, MusicInformation *mi, float f)
{
m_command = command;
m_parameter.setX(f);
m_music_information = mi;
} // SFXCommnd(MusicInformation *, float)
// --------------------------------------------------------------------
SFXCommand(SFXCommands command, SFXBase *base, float parameter)
{
@ -205,6 +218,7 @@ public:
void queue(SFXCommands command, SFXBase *sfx, float f);
void queue(SFXCommands command, SFXBase *sfx, const Vec3 &p);
void queue(SFXCommands command, MusicInformation *mi);
void queue(SFXCommands command, MusicInformation *mi, float f);
// ------------------------------------------------------------------------
/** Static function to get the singleton sfx manager. */
static SFXManager *get()

View File

@ -1516,7 +1516,8 @@ static void cleanSuperTuxKart()
SFXManager::destroy();
// Music manager can not be deleted before the sfx thread is stopped
// (since sfx commands can contain music information).
// (since sfx commands can contain music information, which are
// deleted by the music manager).
delete music_manager;
// The addons manager might still be called from a currenty running request

View File

@ -157,8 +157,7 @@ void LinearWorld::update(float dt)
if (m_last_lap_sfx_playing &&
m_last_lap_sfx->getStatus() != SFXBase::SFX_PLAYING)
{
if(music_manager->getCurrentMusic())
music_manager->getCurrentMusic()->resetTemporaryVolume();
music_manager->resetTemporaryVolume();
m_last_lap_sfx_playing = false;
}
@ -288,7 +287,7 @@ void LinearWorld::newLap(unsigned int kart_index)
if(music_manager->getCurrentMusic() &&
music_manager->getMasterMusicVolume() > 0.2f)
{
music_manager->getCurrentMusic()->setTemporaryVolume(0.2f);
music_manager->setTemporaryVolume(0.2f);
}
}
else

View File

@ -114,9 +114,8 @@ void OverWorld::update(float dt)
// so we have to start music 'manually', since we skip all phases.
World::getWorld()->getTrack()->startMusic();
if (music_manager->getCurrentMusic() != NULL &&
UserConfigParams::m_music)
music_manager->getCurrentMusic()->startMusic();
if (UserConfigParams::m_music)
music_manager->startMusic();
m_karts[0]->startEngineSFX();
}
WorldWithRank::update(dt);