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:
commit
38f36fa720
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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]));
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user