aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/wintermute/base/base_game.cpp440
-rw-r--r--engines/wintermute/base/base_game.h19
-rw-r--r--engines/wintermute/base/base_game_music.cpp487
-rw-r--r--engines/wintermute/base/base_game_music.h73
-rw-r--r--engines/wintermute/module.mk1
5 files changed, 572 insertions, 448 deletions
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
index 0d6897ce4f..e5e3472572 100644
--- a/engines/wintermute/base/base_game.cpp
+++ b/engines/wintermute/base/base_game.cpp
@@ -29,6 +29,7 @@
#include "engines/wintermute/dcgf.h"
#include "engines/wintermute/base/base_engine.h"
#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_game_music.h"
#include "engines/wintermute/base/base_fader.h"
#include "engines/wintermute/base/base_file_manager.h"
#include "engines/wintermute/base/font/base_font.h"
@@ -146,10 +147,7 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
_stringTable = new BaseStringTable(this);
- for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
- _music[i] = NULL;
- _musicStartTime[i] = 0;
- }
+ _musicSystem = new BaseGameMusic(this);
_settingsResWidth = 800;
_settingsResHeight = 600;
@@ -200,13 +198,6 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
_savedGameExt = NULL;
BaseUtils::setString(&_savedGameExt, "dsv");
- _musicCrossfadeRunning = false;
- _musicCrossfadeStartTime = 0;
- _musicCrossfadeLength = 0;
- _musicCrossfadeChannel1 = -1;
- _musicCrossfadeChannel2 = -1;
- _musicCrossfadeSwap = false;
-
_localSaveDir = NULL;
BaseUtils::setString(&_localSaveDir, "saves");
_saveDirChecked = false;
@@ -223,7 +214,6 @@ BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gam
_lastCursor = NULL;
-
BasePlatform::setRectEmpty(&_mouseLockRect);
_suppressScriptErrors = false;
@@ -286,6 +276,7 @@ BaseGame::~BaseGame() {
delete _renderer;
delete _stringTable;
+ delete _musicSystem;
_localSaveDir = NULL;
_settingsGameFile = NULL;
@@ -305,6 +296,7 @@ BaseGame::~BaseGame() {
_renderer = NULL;
_stringTable = NULL;
+ _musicSystem = NULL;
DEBUG_DebugDisable();
debugC(kWintermuteDebugLog, "--- shutting down normally ---\n");
@@ -319,11 +311,7 @@ bool BaseGame::cleanup() {
_engineLogCallback = NULL;
_engineLogCallbackData = NULL;
- for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
- delete _music[i];
- _music[i] = NULL;
- _musicStartTime[i] = 0;
- }
+ _musicSystem->cleanup();
unregisterObject(_fader);
_fader = NULL;
@@ -551,7 +539,7 @@ bool BaseGame::initLoop() {
_currentTime = g_system->getMillis();
_renderer->initLoop();
- updateMusicCrossfade();
+ _musicSystem->updateMusicCrossfade();
_surfaceStorage->initLoop();
_fontStorage->initLoop();
@@ -1096,253 +1084,7 @@ bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack
return STATUS_OK;
}
- //////////////////////////////////////////////////////////////////////////
- // PlayMusic / PlayMusicChannel
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PlayMusic") == 0 || strcmp(name, "PlayMusicChannel") == 0) {
- int channel = 0;
- if (strcmp(name, "PlayMusic") == 0) {
- stack->correctParams(3);
- } else {
- stack->correctParams(4);
- channel = stack->pop()->getInt();
- }
-
- const char *filename = stack->pop()->getString();
- ScValue *valLooping = stack->pop();
- bool looping = valLooping->isNULL() ? true : valLooping->getBool();
-
- ScValue *valLoopStart = stack->pop();
- uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt());
-
-
- if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // StopMusic / StopMusicChannel
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) {
- int channel = 0;
-
- if (strcmp(name, "StopMusic") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (DID_FAIL(stopMusic(channel))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // PauseMusic / PauseMusicChannel
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) {
- int channel = 0;
-
- if (strcmp(name, "PauseMusic") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (DID_FAIL(pauseMusic(channel))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // ResumeMusic / ResumeMusicChannel
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ResumeMusic") == 0 || strcmp(name, "ResumeMusicChannel") == 0) {
- int channel = 0;
- if (strcmp(name, "ResumeMusic") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (DID_FAIL(resumeMusic(channel))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetMusic / GetMusicChannel
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetMusic") == 0 || strcmp(name, "GetMusicChannel") == 0) {
- int channel = 0;
- if (strcmp(name, "GetMusic") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
- if (channel < 0 || channel >= NUM_MUSIC_CHANNELS) {
- stack->pushNULL();
- } else {
- if (!_music[channel] || !_music[channel]->getFilename()) {
- stack->pushNULL();
- } else {
- stack->pushString(_music[channel]->getFilename());
- }
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetMusicPosition / SetMusicChannelPosition
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetMusicPosition") == 0 || strcmp(name, "SetMusicChannelPosition") == 0 || strcmp(name, "SetMusicPositionChannel") == 0) {
- int channel = 0;
- if (strcmp(name, "SetMusicPosition") == 0) {
- stack->correctParams(1);
- } else {
- stack->correctParams(2);
- channel = stack->pop()->getInt();
- }
-
- uint32 time = stack->pop()->getInt();
-
- if (DID_FAIL(setMusicStartTime(channel, time))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetMusicPosition / GetMusicChannelPosition
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetMusicPosition") == 0 || strcmp(name, "GetMusicChannelPosition") == 0) {
- int channel = 0;
- if (strcmp(name, "GetMusicPosition") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
- stack->pushInt(0);
- } else {
- stack->pushInt(_music[channel]->getPositionTime());
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // IsMusicPlaying / IsMusicChannelPlaying
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "IsMusicPlaying") == 0 || strcmp(name, "IsMusicChannelPlaying") == 0) {
- int channel = 0;
- if (strcmp(name, "IsMusicPlaying") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
- stack->pushBool(false);
- } else {
- stack->pushBool(_music[channel]->isPlaying());
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // SetMusicVolume / SetMusicChannelVolume
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetMusicVolume") == 0 || strcmp(name, "SetMusicChannelVolume") == 0) {
- int channel = 0;
- if (strcmp(name, "SetMusicVolume") == 0) {
- stack->correctParams(1);
- } else {
- stack->correctParams(2);
- channel = stack->pop()->getInt();
- }
-
- int volume = stack->pop()->getInt();
- if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
- stack->pushBool(false);
- } else {
- if (DID_FAIL(_music[channel]->setVolumePercent(volume))) {
- stack->pushBool(false);
- } else {
- stack->pushBool(true);
- }
- }
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GetMusicVolume / GetMusicChannelVolume
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GetMusicVolume") == 0 || strcmp(name, "GetMusicChannelVolume") == 0) {
- int channel = 0;
- if (strcmp(name, "GetMusicVolume") == 0) {
- stack->correctParams(0);
- } else {
- stack->correctParams(1);
- channel = stack->pop()->getInt();
- }
-
- if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
- stack->pushInt(0);
- } else {
- stack->pushInt(_music[channel]->getVolumePercent());
- }
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // MusicCrossfade
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MusicCrossfade") == 0) {
- stack->correctParams(4);
- int channel1 = stack->pop()->getInt(0);
- int channel2 = stack->pop()->getInt(0);
- uint32 fadeLength = (uint32)stack->pop()->getInt(0);
- bool swap = stack->pop()->getBool(true);
-
- if (_musicCrossfadeRunning) {
- script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress.");
- stack->pushBool(false);
- return STATUS_OK;
- }
-
- _musicCrossfadeStartTime = _liveTimer;
- _musicCrossfadeChannel1 = channel1;
- _musicCrossfadeChannel2 = channel2;
- _musicCrossfadeLength = fadeLength;
- _musicCrossfadeSwap = swap;
-
- _musicCrossfadeRunning = true;
-
- stack->pushBool(true);
+ else if (_musicSystem->scCallMethod(script, stack, thisStack, name) == STATUS_OK) {
return STATUS_OK;
}
@@ -3344,99 +3086,6 @@ bool BaseGame::displayWindows(bool inGame) {
return STATUS_OK;
}
-
-//////////////////////////////////////////////////////////////////////////
-bool BaseGame::playMusic(int channel, const char *filename, bool looping, uint32 loopStart) {
- if (channel >= NUM_MUSIC_CHANNELS) {
- _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
- return STATUS_FAILED;
- }
-
- delete _music[channel];
- _music[channel] = NULL;
-
- _music[channel] = new BaseSound(_gameRef);
- if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
- if (_musicStartTime[channel]) {
- _music[channel]->setPositionTime(_musicStartTime[channel]);
- _musicStartTime[channel] = 0;
- }
- if (loopStart) {
- _music[channel]->setLoopStart(loopStart);
- }
- return _music[channel]->play(looping);
- } else {
- delete _music[channel];
- _music[channel] = NULL;
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool BaseGame::stopMusic(int channel) {
- if (channel >= NUM_MUSIC_CHANNELS) {
- _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
- return STATUS_FAILED;
- }
-
- if (_music[channel]) {
- _music[channel]->stop();
- delete _music[channel];
- _music[channel] = NULL;
- return STATUS_OK;
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool BaseGame::pauseMusic(int channel) {
- if (channel >= NUM_MUSIC_CHANNELS) {
- _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
- return STATUS_FAILED;
- }
-
- if (_music[channel]) {
- return _music[channel]->pause();
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool BaseGame::resumeMusic(int channel) {
- if (channel >= NUM_MUSIC_CHANNELS) {
- _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
- return STATUS_FAILED;
- }
-
- if (_music[channel]) {
- return _music[channel]->resume();
- } else {
- return STATUS_FAILED;
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool BaseGame::setMusicStartTime(int channel, uint32 time) {
- if (channel >= NUM_MUSIC_CHANNELS) {
- _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
- return STATUS_FAILED;
- }
-
- _musicStartTime[channel] = time;
- if (_music[channel] && _music[channel]->isPlaying()) {
- return _music[channel]->setPositionTime(time);
- } else {
- return STATUS_OK;
- }
-}
-
-
//////////////////////////////////////////////////////////////////////////
bool BaseGame::loadSettings(const char *filename) {
TOKEN_TABLE_START(commands)
@@ -3583,10 +3232,7 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_keyboardState));
persistMgr->transfer(TMEMBER(_lastTime));
persistMgr->transfer(TMEMBER(_mainObject));
- for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
- persistMgr->transfer(TMEMBER(_music[i]));
- persistMgr->transfer(TMEMBER(_musicStartTime[i]));
- }
+ _musicSystem->persistChannels(persistMgr);
persistMgr->transfer(TMEMBER(_offsetX));
persistMgr->transfer(TMEMBER(_offsetY));
@@ -3618,12 +3264,7 @@ bool BaseGame::persist(BasePersistenceManager *persistMgr) {
persistMgr->transfer(TMEMBER(_liveTimerDelta));
persistMgr->transfer(TMEMBER(_liveTimerLast));
- persistMgr->transfer(TMEMBER(_musicCrossfadeRunning));
- persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime));
- persistMgr->transfer(TMEMBER(_musicCrossfadeLength));
- persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1));
- persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2));
- persistMgr->transfer(TMEMBER(_musicCrossfadeSwap));
+ _musicSystem->persistCrossfadeSettings(persistMgr);
_renderer->persistSaveLoadImages(persistMgr);
@@ -3978,69 +3619,6 @@ bool BaseGame::displayContentSimple() {
}
//////////////////////////////////////////////////////////////////////////
-bool BaseGame::updateMusicCrossfade() {
- /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */
-
- if (!_musicCrossfadeRunning) {
- return STATUS_OK;
- }
- if (_state == GAME_FROZEN) {
- return STATUS_OK;
- }
-
- if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) {
- _musicCrossfadeRunning = false;
- return STATUS_OK;
- }
- if (_musicCrossfadeChannel2 < 0 || _musicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel2]) {
- _musicCrossfadeRunning = false;
- return STATUS_OK;
- }
-
- if (!_music[_musicCrossfadeChannel1]->isPlaying()) {
- _music[_musicCrossfadeChannel1]->play();
- }
- if (!_music[_musicCrossfadeChannel2]->isPlaying()) {
- _music[_musicCrossfadeChannel2]->play();
- }
-
- uint32 currentTime = _gameRef->_liveTimer - _musicCrossfadeStartTime;
-
- if (currentTime >= _musicCrossfadeLength) {
- _musicCrossfadeRunning = false;
- //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol);
- _music[_musicCrossfadeChannel2]->setVolumePercent(100);
-
- _music[_musicCrossfadeChannel1]->stop();
- //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol);
- _music[_musicCrossfadeChannel1]->setVolumePercent(100);
-
-
- if (_musicCrossfadeSwap) {
- // swap channels
- BaseSound *dummy = _music[_musicCrossfadeChannel1];
- int dummyInt = _musicStartTime[_musicCrossfadeChannel1];
-
- _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2];
- _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2];
-
- _music[_musicCrossfadeChannel2] = dummy;
- _musicStartTime[_musicCrossfadeChannel2] = dummyInt;
- }
- } else {
- //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
- //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
- _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f));
- _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f));
-
- //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume());
- }
-
- return STATUS_OK;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
bool BaseGame::resetContent() {
_scEngine->clearGlobals();
//_timer = 0;
diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h
index d941f9fa6a..9db4381bc6 100644
--- a/engines/wintermute/base/base_game.h
+++ b/engines/wintermute/base/base_game.h
@@ -46,6 +46,7 @@ class BaseFileManager;
class BaseTransitionMgr;
class ScEngine;
class BaseFontStorage;
+class BaseGameMusic;
class BaseStringTable;
class BaseQuickMsg;
class UIWindow;
@@ -59,8 +60,6 @@ class BaseKeyboardState;
class VideoPlayer;
class VideoTheoraPlayer;
-#define NUM_MUSIC_CHANNELS 5
-
class BaseGame: public BaseObject {
public:
DECLARE_PERSISTENT(BaseGame, BaseObject)
@@ -292,31 +291,17 @@ private:
void *_engineLogCallbackData;
bool _videoSubtitles;
- uint32 _musicStartTime[NUM_MUSIC_CHANNELS];
bool _compressedSavegames;
bool _personalizedSave;
void setWindowTitle();
- bool resumeMusic(int channel);
- bool setMusicStartTime(int channel, uint32 time);
- bool pauseMusic(int channel);
- bool stopMusic(int channel);
- bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0);
- BaseSound *_music[NUM_MUSIC_CHANNELS];
- bool _musicCrossfadeRunning;
- bool _musicCrossfadeSwap;
- uint32 _musicCrossfadeStartTime;
- uint32 _musicCrossfadeLength;
- int _musicCrossfadeChannel1;
- int _musicCrossfadeChannel2;
-
BaseSprite *_cursorNoninteractive;
BaseKeyboardState *_keyboardState;
uint32 _fps;
- bool updateMusicCrossfade();
+ BaseGameMusic *_musicSystem;
bool isVideoPlaying();
bool stopVideo();
diff --git a/engines/wintermute/base/base_game_music.cpp b/engines/wintermute/base/base_game_music.cpp
new file mode 100644
index 0000000000..0fd0961ff1
--- /dev/null
+++ b/engines/wintermute/base/base_game_music.cpp
@@ -0,0 +1,487 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_game_music.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+
+namespace Wintermute {
+
+BaseGameMusic::BaseGameMusic(BaseGame *gameRef) : _gameRef(gameRef) {
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ _music[i] = NULL;
+ _musicStartTime[i] = 0;
+ }
+
+ _musicCrossfadeRunning = false;
+ _musicCrossfadeStartTime = 0;
+ _musicCrossfadeLength = 0;
+ _musicCrossfadeChannel1 = -1;
+ _musicCrossfadeChannel2 = -1;
+ _musicCrossfadeSwap = false;
+}
+
+void BaseGameMusic::cleanup() {
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ delete _music[i];
+ _music[i] = NULL;
+ _musicStartTime[i] = 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::playMusic(int channel, const char *filename, bool looping, uint32 loopStart) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ delete _music[channel];
+ _music[channel] = NULL;
+
+ _music[channel] = new BaseSound(_gameRef);
+ if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
+ if (_musicStartTime[channel]) {
+ _music[channel]->setPositionTime(_musicStartTime[channel]);
+ _musicStartTime[channel] = 0;
+ }
+ if (loopStart) {
+ _music[channel]->setLoopStart(loopStart);
+ }
+ return _music[channel]->play(looping);
+ } else {
+ delete _music[channel];
+ _music[channel] = NULL;
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::stopMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ _music[channel]->stop();
+ delete _music[channel];
+ _music[channel] = NULL;
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::pauseMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ return _music[channel]->pause();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::resumeMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ return _music[channel]->resume();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::setMusicStartTime(int channel, uint32 time) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ BaseEngine::LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ _musicStartTime[channel] = time;
+ if (_music[channel] && _music[channel]->isPlaying()) {
+ return _music[channel]->setPositionTime(time);
+ } else {
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGameMusic::updateMusicCrossfade() {
+ /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */
+
+ if (!_musicCrossfadeRunning) {
+ return STATUS_OK;
+ }
+ if (_gameRef->_state == GAME_FROZEN) {
+ return STATUS_OK;
+ }
+
+ if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) {
+ _musicCrossfadeRunning = false;
+ return STATUS_OK;
+ }
+ if (_musicCrossfadeChannel2 < 0 || _musicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel2]) {
+ _musicCrossfadeRunning = false;
+ return STATUS_OK;
+ }
+
+ if (!_music[_musicCrossfadeChannel1]->isPlaying()) {
+ _music[_musicCrossfadeChannel1]->play();
+ }
+ if (!_music[_musicCrossfadeChannel2]->isPlaying()) {
+ _music[_musicCrossfadeChannel2]->play();
+ }
+
+ uint32 currentTime = _gameRef->_liveTimer - _musicCrossfadeStartTime;
+
+ if (currentTime >= _musicCrossfadeLength) {
+ _musicCrossfadeRunning = false;
+ //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol);
+ _music[_musicCrossfadeChannel2]->setVolumePercent(100);
+
+ _music[_musicCrossfadeChannel1]->stop();
+ //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol);
+ _music[_musicCrossfadeChannel1]->setVolumePercent(100);
+
+
+ if (_musicCrossfadeSwap) {
+ // swap channels
+ BaseSound *dummy = _music[_musicCrossfadeChannel1];
+ int dummyInt = _musicStartTime[_musicCrossfadeChannel1];
+
+ _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2];
+ _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2];
+
+ _music[_musicCrossfadeChannel2] = dummy;
+ _musicStartTime[_musicCrossfadeChannel2] = dummyInt;
+ }
+ } else {
+ //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
+ //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
+ _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f));
+ _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f));
+
+ //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume());
+ }
+
+ return STATUS_OK;
+}
+
+bool BaseGameMusic::persistChannels(BasePersistenceManager *persistMgr) {
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ persistMgr->transfer(TMEMBER(_music[i]));
+ persistMgr->transfer(TMEMBER(_musicStartTime[i]));
+ }
+ return true;
+}
+
+bool BaseGameMusic::persistCrossfadeSettings(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_musicCrossfadeRunning));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeLength));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeSwap));
+ return true;
+}
+
+bool BaseGameMusic::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // PlayMusic / PlayMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "PlayMusic") == 0 || strcmp(name, "PlayMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "PlayMusic") == 0) {
+ stack->correctParams(3);
+ } else {
+ stack->correctParams(4);
+ channel = stack->pop()->getInt();
+ }
+
+ const char *filename = stack->pop()->getString();
+ ScValue *valLooping = stack->pop();
+ bool looping = valLooping->isNULL() ? true : valLooping->getBool();
+
+ ScValue *valLoopStart = stack->pop();
+ uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt());
+
+
+ if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // StopMusic / StopMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) {
+ int channel = 0;
+
+ if (strcmp(name, "StopMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(stopMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic / PauseMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) {
+ int channel = 0;
+
+ if (strcmp(name, "PauseMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(pauseMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ResumeMusic / ResumeMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ResumeMusic") == 0 || strcmp(name, "ResumeMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "ResumeMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(resumeMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusic / GetMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusic") == 0 || strcmp(name, "GetMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS) {
+ stack->pushNULL();
+ } else {
+ if (!_music[channel] || !_music[channel]->getFilename()) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_music[channel]->getFilename());
+ }
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetMusicPosition / SetMusicChannelPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMusicPosition") == 0 || strcmp(name, "SetMusicChannelPosition") == 0 || strcmp(name, "SetMusicPositionChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "SetMusicPosition") == 0) {
+ stack->correctParams(1);
+ } else {
+ stack->correctParams(2);
+ channel = stack->pop()->getInt();
+ }
+
+ uint32 time = stack->pop()->getInt();
+
+ if (DID_FAIL(setMusicStartTime(channel, time))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusicPosition / GetMusicChannelPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusicPosition") == 0 || strcmp(name, "GetMusicChannelPosition") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusicPosition") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushInt(0);
+ } else {
+ stack->pushInt(_music[channel]->getPositionTime());
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsMusicPlaying / IsMusicChannelPlaying
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsMusicPlaying") == 0 || strcmp(name, "IsMusicChannelPlaying") == 0) {
+ int channel = 0;
+ if (strcmp(name, "IsMusicPlaying") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(_music[channel]->isPlaying());
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetMusicVolume / SetMusicChannelVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMusicVolume") == 0 || strcmp(name, "SetMusicChannelVolume") == 0) {
+ int channel = 0;
+ if (strcmp(name, "SetMusicVolume") == 0) {
+ stack->correctParams(1);
+ } else {
+ stack->correctParams(2);
+ channel = stack->pop()->getInt();
+ }
+
+ int volume = stack->pop()->getInt();
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushBool(false);
+ } else {
+ if (DID_FAIL(_music[channel]->setVolumePercent(volume))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusicVolume / GetMusicChannelVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusicVolume") == 0 || strcmp(name, "GetMusicChannelVolume") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusicVolume") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushInt(0);
+ } else {
+ stack->pushInt(_music[channel]->getVolumePercent());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MusicCrossfade
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MusicCrossfade") == 0) {
+ stack->correctParams(4);
+ int channel1 = stack->pop()->getInt(0);
+ int channel2 = stack->pop()->getInt(0);
+ uint32 fadeLength = (uint32)stack->pop()->getInt(0);
+ bool swap = stack->pop()->getBool(true);
+
+ if (_musicCrossfadeRunning) {
+ script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress.");
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ _musicCrossfadeStartTime = _gameRef->_liveTimer;
+ _musicCrossfadeChannel1 = channel1;
+ _musicCrossfadeChannel2 = channel2;
+ _musicCrossfadeLength = fadeLength;
+ _musicCrossfadeSwap = swap;
+
+ _musicCrossfadeRunning = true;
+
+ stack->pushBool(true);
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_game_music.h b/engines/wintermute/base/base_game_music.h
new file mode 100644
index 0000000000..058a8cadef
--- /dev/null
+++ b/engines/wintermute/base/base_game_music.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_GAME_MUSIC_H
+#define WINTERMUTE_BASE_GAME_MUSIC_H
+
+#include "common/scummsys.h"
+
+
+namespace Wintermute {
+
+#define NUM_MUSIC_CHANNELS 5
+class BasePersistenceManager;
+class BaseSound;
+class ScStack;
+class ScScript;
+class BaseGame;
+class BaseGameMusic {
+public:
+ BaseGameMusic(BaseGame *gameRef);
+ void cleanup();
+
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+
+ bool resumeMusic(int channel);
+ bool setMusicStartTime(int channel, uint32 time);
+ bool pauseMusic(int channel);
+ bool stopMusic(int channel);
+ bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0);
+ bool updateMusicCrossfade();
+
+ bool persistChannels(BasePersistenceManager *persistMgr);
+ bool persistCrossfadeSettings(BasePersistenceManager *persistMgr);
+private:
+ BaseGame *_gameRef;
+ BaseSound *_music[NUM_MUSIC_CHANNELS];
+ uint32 _musicStartTime[NUM_MUSIC_CHANNELS];
+ bool _musicCrossfadeRunning;
+ bool _musicCrossfadeSwap;
+ uint32 _musicCrossfadeStartTime;
+ uint32 _musicCrossfadeLength;
+ int _musicCrossfadeChannel1;
+ int _musicCrossfadeChannel2;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk
index 7b5b1b1a3a..7c9cdfd0b2 100644
--- a/engines/wintermute/module.mk
+++ b/engines/wintermute/module.mk
@@ -67,6 +67,7 @@ MODULE_OBJS := \
base/base_file_manager.o \
base/base_frame.o \
base/base_game.o \
+ base/base_game_music.o \
base/base_keyboard_state.o \
base/base_named_object.o \
base/base_object.o \