1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #1127 from IvanSavenko/resume_music

Fix #985 - resume town & terrain themes
This commit is contained in:
Andrii Danylchenko 2022-11-13 21:18:46 +02:00 committed by GitHub
commit 38f36fa720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 53 additions and 26 deletions

View File

@ -9,6 +9,7 @@
*/
#include "StdInc.h"
#include <SDL_mixer.h>
#include <SDL.h>
#include "CMusicHandler.h"
#include "CGameInfo.h"
@ -410,15 +411,15 @@ void CMusicHandler::release()
CAudioBase::release();
}
void CMusicHandler::playMusic(const std::string & musicURI, bool loop)
void CMusicHandler::playMusic(const std::string & musicURI, bool loop, bool fromStart)
{
if (current && current->isTrack(musicURI))
return;
queueNext(this, "", musicURI, loop);
queueNext(this, "", musicURI, loop, fromStart);
}
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop)
void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop, bool fromStart)
{
auto selectedSet = musicsSet.find(whichSet);
if (selectedSet == musicsSet.end())
@ -431,10 +432,10 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, bool loop)
return;
// in this mode - play random track from set
queueNext(this, whichSet, "", loop);
queueNext(this, whichSet, "", loop, fromStart);
}
void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop)
void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::string & entryID, bool loop, bool fromStart)
{
auto selectedSet = musicsSet.find(whichSet);
if (selectedSet == musicsSet.end())
@ -454,7 +455,7 @@ void CMusicHandler::playMusicFromSet(const std::string & whichSet, const std::st
return;
// in this mode - play specific track from set
queueNext(this, "", selectedEntry->second, loop);
queueNext(this, "", selectedEntry->second, loop, fromStart);
}
void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
@ -473,11 +474,11 @@ void CMusicHandler::queueNext(std::unique_ptr<MusicEntry> queued)
}
}
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped)
void CMusicHandler::queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart)
{
try
{
queueNext(make_unique<MusicEntry>(owner, setName, musicURI, looped));
queueNext(make_unique<MusicEntry>(owner, setName, musicURI, looped, fromStart));
}
catch(std::exception &e)
{
@ -526,10 +527,13 @@ void CMusicHandler::musicFinishedCallback()
}
}
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped):
MusicEntry::MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart):
owner(owner),
music(nullptr),
startTime(uint32_t(-1)),
startPosition(0),
loop(looped ? -1 : 1),
fromStart(fromStart),
setName(std::move(setName))
{
if (!musicURI.empty())
@ -578,11 +582,25 @@ bool MusicEntry::play()
}
logGlobal->trace("Playing music file %s", currentName);
if(Mix_PlayMusic(music, 1) == -1)
if ( !fromStart && owner->trackPositions.count(currentName) > 0 && owner->trackPositions[currentName] > 0)
{
float timeToStart = owner->trackPositions[currentName];
startPosition = std::round(timeToStart * 1000);
if (Mix_FadeInMusicPos(music, 1, 1000, timeToStart) == -1)
{
logGlobal->error("Unable to play music (%s)", Mix_GetError());
return false;
}
}
else if(Mix_PlayMusic(music, 1) == -1)
{
logGlobal->error("Unable to play music (%s)", Mix_GetError());
return false;
}
startTime = SDL_GetTicks();
return true;
}
@ -590,8 +608,13 @@ bool MusicEntry::stop(int fade_ms)
{
if (Mix_PlayingMusic())
{
logGlobal->trace("Stopping music file %s", currentName);
loop = 0;
uint32_t endTime = SDL_GetTicks();
assert(startTime != uint32_t(-1));
float playDuration = (endTime - startTime + startPosition) / 1000.f;
owner->trackPositions[currentName] = playDuration;
logGlobal->info("Stopping music file %s at %f", currentName, playDuration);
Mix_FadeOutMusic(fade_ms);
return true;
}

View File

@ -99,6 +99,9 @@ class MusicEntry
Mix_Music *music;
int loop; // -1 = indefinite
bool fromStart;
uint32_t startTime;
uint32_t startPosition;
//if not null - set from which music will be randomly selected
std::string setName;
std::string currentName;
@ -110,7 +113,7 @@ public:
bool isSet(std::string setName);
bool isTrack(std::string trackName);
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped);
MusicEntry(CMusicHandler *owner, std::string setName, std::string musicURI, bool looped, bool fromStart);
~MusicEntry();
bool play();
@ -128,10 +131,11 @@ private:
std::unique_ptr<MusicEntry> current;
std::unique_ptr<MusicEntry> next;
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped);
void queueNext(CMusicHandler *owner, const std::string & setName, const std::string & musicURI, bool looped, bool fromStart);
void queueNext(std::unique_ptr<MusicEntry> queued);
std::map<std::string, std::map<std::string, std::string>> musicsSet;
std::map<std::string, float> trackPositions;
public:
CMusicHandler();
@ -145,11 +149,11 @@ public:
void setVolume(ui32 percent) override;
/// play track by URI, if loop = true music will be looped
void playMusic(const std::string & musicURI, bool loop);
void playMusic(const std::string & musicURI, bool loop, bool fromStart);
/// play random track from this set
void playMusicFromSet(const std::string & musicSet, bool loop);
void playMusicFromSet(const std::string & musicSet, bool loop, bool fromStart);
/// play specific track from set
void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop);
void playMusicFromSet(const std::string & musicSet, const std::string & entryID, bool loop, bool fromStart);
void stopMusic(int fade_ms=1000);
void musicFinishedCallback();

View File

@ -276,7 +276,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details, bool verbose)
{
updateAmbientSounds();
//We may need to change music - select new track, music handler will change it if needed
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true);
CCS->musich->playMusicFromSet("terrain", LOCPLINT->cb->getTile(hero->visitablePos())->terType->name, true, false);
if(details.result == TryMoveHero::TELEPORTATION)
{

View File

@ -411,7 +411,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
{
if(LOCPLINT->battleInt)
{
CCS->musich->playMusicFromSet("battle", true);
CCS->musich->playMusicFromSet("battle", true, true);
battleActionsStarted = true;
blockUI(settings["session"]["spectate"].Bool());
battleIntroSoundChannel = -1;
@ -457,7 +457,7 @@ CBattleInterface::~CBattleInterface()
if (adventureInt && adventureInt->selection)
{
const auto & terrain = *(LOCPLINT->cb->getTile(adventureInt->selection->visitablePos())->terType);
CCS->musich->playMusicFromSet("terrain", terrain.name, true);
CCS->musich->playMusicFromSet("terrain", terrain.name, true, false);
}
animsAreDisplayed.setn(false);
}

View File

@ -506,7 +506,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa
break;
}
CCS->musich->playMusic("Music/Win Battle", false);
CCS->musich->playMusic("Music/Win Battle", false, true);
CCS->videoh->open("WIN3.BIK");
std::string str = CGI->generaltexth->allTexts[text];
@ -543,7 +543,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa
logGlobal->error("Invalid battle result code %d. Assumed normal.", static_cast<int>(br.result));
break;
}
CCS->musich->playMusic(musicName, false);
CCS->musich->playMusic(musicName, false, true);
CCS->videoh->open(videoName);
labels.push_back(std::make_shared<CLabel>(235, 235, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[text]));

View File

@ -115,7 +115,7 @@ void CMenuScreen::show(SDL_Surface * to)
void CMenuScreen::activate()
{
CCS->musich->playMusic("Music/MainMenu", true);
CCS->musich->playMusic("Music/MainMenu", true, true);
if(!config["video"].isNull())
CCS->videoh->open(config["video"]["name"].String());
CIntObject::activate();

View File

@ -29,7 +29,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog
updateShadow();
CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo));
CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true);
CCS->musich->playMusic("Music/" + CCampaignHandler::prologMusicName(spe.prologMusic), true, true);
// MPTODO: Custom campaign crashing on this?
// voiceSoundHandle = CCS->soundh->playSound(CCampaignHandler::prologVoiceName(spe.prologVideo));

View File

@ -1413,7 +1413,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView)
auto pos = sel->visitablePos();
auto tile = LOCPLINT->cb->getTile(pos);
if(tile)
CCS->musich->playMusicFromSet("terrain", tile->terType->name, true);
CCS->musich->playMusicFromSet("terrain", tile->terType->name, true, false);
}
if(centerView)
centerOn(sel);
@ -1863,7 +1863,7 @@ void CAdvMapInt::aiTurnStarted()
return;
adjustActiveness(true);
CCS->musich->playMusicFromSet("enemy-turn", true);
CCS->musich->playMusicFromSet("enemy-turn", true, false);
adventureInt->minimap.setAIRadar(true);
adventureInt->infoBar.startEnemyTurn(LOCPLINT->cb->getCurrentPlayer());
adventureInt->infoBar.showAll(screen);//force refresh on inactive object

View File

@ -1171,7 +1171,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
townlist->onSelect = std::bind(&CCastleInterface::townChange, this);
recreateIcons();
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true);
CCS->musich->playMusic(town->town->clientInfo.musicTheme, true, false);
}
CCastleInterface::~CCastleInterface()