Try to fix missing music after switching

m_current_music assignment should be done in sfx thread if music is on
This commit is contained in:
Benau
2021-08-19 09:50:23 +08:00
parent 7a07b716b8
commit 037efe60fb
5 changed files with 44 additions and 15 deletions

View File

@@ -22,6 +22,7 @@
#include <iostream>
#include "audio/music_dummy.hpp"
#include "audio/music_manager.hpp"
#include "audio/music_ogg.hpp"
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
@@ -143,6 +144,29 @@ void MusicInformation::addMusicToTracks()
}
} // addMusicToTracks
//-----------------------------------------------------------------------------
/** Return false if it should not be started, done in sfx thread.
*/
bool MusicInformation::preStart()
{
MusicInformation* old_mi = music_manager->m_current_music.load();
// If this music is already playing, ignore this call.
if (isPlaying() ||
(old_mi != NULL && old_mi == this && old_mi->isPlaying()))
{
return false;
}
// It is possible here that startMusic() will be called without first
// calling stopMusic(). This would cause a memory leak by overwriting
// m_current_music without first releasing its resources. Guard against
// this here by making sure that stopMusic() is called before starting
// new music.
if (old_mi)
old_mi->stopMusic();
music_manager->m_current_music.store(this);
return true;
} // preStart
//-----------------------------------------------------------------------------
/** Starts the music.
*/

View File

@@ -97,6 +97,8 @@ private:
void switchToFastMusic();
void setTemporaryVolume(float volume);
// ------------------------------------------------------------------------
bool preStart();
// ------------------------------------------------------------------------
/** 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; }

View File

@@ -175,24 +175,22 @@ void MusicManager::startMusic()
*/
void MusicManager::startMusic(MusicInformation* mi, bool start_right_now)
{
if (STKProcess::getType() != PT_MAIN)
if (STKProcess::getType() != PT_MAIN || !m_initialized)
return;
// If this music is already playing, ignore this call.
if (m_current_music != NULL &&
m_current_music == mi &&
m_current_music->isPlaying())
if (!UserConfigParams::m_music)
{
// Save it so it can be turned on later in options menu
m_current_music = mi;
return;
}
// It is possible here that startMusic() will be called without first
// calling stopMusic(). This would cause a memory leak by overwriting
// m_current_music without first releasing its resources. Guard against
// this here by making sure that stopMusic() is called before starting
// new music.
stopMusic();
m_current_music = mi;
if(!mi || !UserConfigParams::m_music || !m_initialized) return;
if (!mi)
{
// NULL music will stop current music
clearCurrentMusic();
return;
}
SFXManager::get()->queue(start_right_now ? SFXManager::SFX_MUSIC_START
: SFXManager::SFX_MUSIC_WAITING,

View File

@@ -24,6 +24,7 @@
#include "audio/music_information.hpp"
#include "utils/no_copy.hpp"
#include <atomic>
#include <map>
#include <string>
#include <vector>
@@ -36,8 +37,9 @@ class Vec3;
*/
class MusicManager : public NoCopy
{
friend class MusicInformation;
private:
MusicInformation *m_current_music;
std::atomic<MusicInformation*> m_current_music;
/** 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

View File

@@ -425,6 +425,8 @@ void SFXManager::mainLoop(void *obj)
case SFX_UPDATE: me->reallyUpdateNow(current); break;
case SFX_MUSIC_START:
{
if (!current->m_music_information->preStart())
break;
current->m_music_information->setDefaultVolume();
current->m_music_information->startMusic(); break;
}
@@ -445,6 +447,7 @@ void SFXManager::mainLoop(void *obj)
mi->setTemporaryVolume(current->m_parameter.getX()); break;
}
case SFX_MUSIC_WAITING:
current->m_music_information->preStart();
current->m_music_information->setMusicWaiting(); break;
case SFX_MUSIC_DEFAULT_VOLUME:
{