summaryrefslogtreecommitdiff
path: root/src/soundmanager.cpp
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2012-12-03 17:10:39 +0300
committerAndrei Karas <akaras@inbox.ru>2012-12-03 17:10:39 +0300
commit494ac0ccdf545e8055c83c22b8b2fbf9e045b32a (patch)
tree29dd8c4740fa8a43ebf82037c2e4091b1700a4e4 /src/soundmanager.cpp
parentaa1e8a7a7236d49d91501eac2da81bdb96f0bba5 (diff)
downloadmanaplus-494ac0ccdf545e8055c83c22b8b2fbf9e045b32a.tar.gz
manaplus-494ac0ccdf545e8055c83c22b8b2fbf9e045b32a.tar.bz2
manaplus-494ac0ccdf545e8055c83c22b8b2fbf9e045b32a.tar.xz
manaplus-494ac0ccdf545e8055c83c22b8b2fbf9e045b32a.zip
Rename sound.cpp/h to soundmanager.
Diffstat (limited to 'src/soundmanager.cpp')
-rw-r--r--src/soundmanager.cpp417
1 files changed, 417 insertions, 0 deletions
diff --git a/src/soundmanager.cpp b/src/soundmanager.cpp
new file mode 100644
index 000000000..9a3bc3185
--- /dev/null
+++ b/src/soundmanager.cpp
@@ -0,0 +1,417 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2012 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "soundmanager.h"
+
+#include "configuration.h"
+#include "localplayer.h"
+
+#include "resources/sdlmusic.h"
+#include "resources/resourcemanager.h"
+#include "resources/soundeffect.h"
+
+#include <SDL.h>
+
+#include "debug.h"
+
+/**
+ * This will be set to true, when a music can be freed after a fade out
+ * Currently used by fadeOutCallBack()
+ */
+static bool sFadingOutEnded = false;
+
+/**
+ * Callback used at end of fadeout.
+ * It is called by Mix_MusicFadeFinished().
+ */
+static void fadeOutCallBack()
+{
+ sFadingOutEnded = true;
+}
+
+SoundManager::SoundManager():
+ mInstalled(false),
+ mSfxVolume(100),
+ mMusicVolume(60),
+ mMusic(nullptr),
+ mPlayBattle(false),
+ mPlayGui(false),
+ mPlayMusic(false),
+ mGuiChannel(-1)
+{
+ // This set up our callback function used to
+ // handle fade outs endings.
+ sFadingOutEnded = false;
+ Mix_HookMusicFinished(fadeOutCallBack);
+}
+
+SoundManager::~SoundManager()
+{
+ config.removeListeners(this);
+
+ // Unlink the callback function.
+ Mix_HookMusicFinished(nullptr);
+}
+
+void SoundManager::optionChanged(const std::string &value)
+{
+ if (value == "playBattleSound")
+ mPlayBattle = config.getBoolValue("playBattleSound");
+ else if (value == "playGuiSound")
+ mPlayGui = config.getBoolValue("playGuiSound");
+ else if (value == "playMusic")
+ mPlayMusic = config.getBoolValue("playMusic");
+ else if (value == "sfxVolume")
+ setSfxVolume(config.getIntValue("sfxVolume"));
+ else if (value == "musicVolume")
+ setMusicVolume(config.getIntValue("musicVolume"));
+}
+
+void SoundManager::init()
+{
+ // Don't initialize sound engine twice
+ if (mInstalled)
+ return;
+
+ logger->log1("SoundManager::init() Initializing sound...");
+
+ mPlayBattle = config.getBoolValue("playBattleSound");
+ mPlayGui = config.getBoolValue("playGuiSound");
+ mPlayMusic = config.getBoolValue("playMusic");
+ config.addListener("playBattleSound", this);
+ config.addListener("playGuiSound", this);
+ config.addListener("playMusic", this);
+ config.addListener("sfxVolume", this);
+ config.addListener("musicVolume", this);
+
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1)
+ {
+ logger->log1("SoundManager::init() Failed to initialize audio subsystem");
+ return;
+ }
+
+ const size_t audioBuffer = 4096;
+ int channels = config.getIntValue("audioChannels");
+ switch (channels)
+ {
+ case 3:
+ channels = 4;
+ break;
+ case 4:
+ channels = 6;
+ break;
+ default:
+ break;
+ }
+
+ const int res = Mix_OpenAudio(config.getIntValue("audioFrequency"),
+ MIX_DEFAULT_FORMAT, channels, audioBuffer);
+
+ if (res < 0)
+ {
+ logger->log("SoundManager::init Could not initialize audio: %s",
+ Mix_GetError());
+ if (Mix_OpenAudio(22010, MIX_DEFAULT_FORMAT, 2, audioBuffer) < 0)
+ return;
+ logger->log("Fallback to stereo audio");
+ }
+
+ Mix_AllocateChannels(16);
+ Mix_VolumeMusic(mMusicVolume);
+ Mix_Volume(-1, mSfxVolume);
+
+ info();
+
+ mInstalled = true;
+
+ if (!mCurrentMusicFile.empty() && mPlayMusic)
+ playMusic(mCurrentMusicFile);
+}
+
+void SoundManager::info() const
+{
+ SDL_version compiledVersion;
+ const SDL_version *linkedVersion;
+ char driver[40] = "Unknown";
+ const char *format = "Unknown";
+ int rate = 0;
+ uint16_t audioFormat = 0;
+ int channels = 0;
+
+ MIX_VERSION(&compiledVersion);
+ linkedVersion = Mix_Linked_Version();
+
+ SDL_AudioDriverName(driver, 40);
+
+ Mix_QuerySpec(&rate, &audioFormat, &channels);
+ switch (audioFormat)
+ {
+ case AUDIO_U8: format = "U8"; break;
+ case AUDIO_S8: format = "S8"; break;
+ case AUDIO_U16LSB: format = "U16LSB"; break;
+ case AUDIO_S16LSB: format = "S16LSB"; break;
+ case AUDIO_U16MSB: format = "U16MSB"; break;
+ case AUDIO_S16MSB: format = "S16MSB"; break;
+ default: break;
+ }
+
+ logger->log("SoundManager::info() SDL_mixer: %i.%i.%i (compiled)",
+ compiledVersion.major,
+ compiledVersion.minor,
+ compiledVersion.patch);
+ if (linkedVersion)
+ {
+ logger->log("SoundManager::info() SDL_mixer: %i.%i.%i (linked)",
+ linkedVersion->major,
+ linkedVersion->minor,
+ linkedVersion->patch);
+ }
+ else
+ {
+ logger->log1("SoundManager::info() SDL_mixer: unknown");
+ }
+ logger->log("SoundManager::info() Driver: %s", driver);
+ logger->log("SoundManager::info() Format: %s", format);
+ logger->log("SoundManager::info() Rate: %i", rate);
+ logger->log("SoundManager::info() Channels: %i", channels);
+}
+
+void SoundManager::setMusicVolume(const int volume)
+{
+ mMusicVolume = volume;
+
+ if (mInstalled)
+ Mix_VolumeMusic(mMusicVolume);
+}
+
+void SoundManager::setSfxVolume(const int volume)
+{
+ mSfxVolume = volume;
+
+ if (mInstalled)
+ Mix_Volume(-1, mSfxVolume);
+}
+
+static SDLMusic *loadMusic(const std::string &fileName)
+{
+ ResourceManager *const resman = ResourceManager::getInstance();
+ return resman->getMusic(paths.getStringValue("music") + fileName);
+}
+
+void SoundManager::playMusic(const std::string &fileName)
+{
+ mCurrentMusicFile = fileName;
+
+ if (!mInstalled || !mPlayMusic)
+ return;
+
+ haltMusic();
+
+ if (!fileName.empty())
+ {
+ mMusic = loadMusic(fileName);
+ if (mMusic)
+ mMusic->play();
+ }
+}
+
+void SoundManager::stopMusic()
+{
+ haltMusic();
+}
+
+void SoundManager::fadeInMusic(const std::string &fileName, const int ms)
+{
+ mCurrentMusicFile = fileName;
+
+ if (!mInstalled || !mPlayMusic)
+ return;
+
+ haltMusic();
+
+ if (!fileName.empty())
+ {
+ mMusic = loadMusic(fileName);
+ if (mMusic)
+ mMusic->play(-1, ms);
+ }
+}
+
+void SoundManager::fadeOutMusic(const int ms)
+{
+ mCurrentMusicFile.clear();
+
+ if (!mInstalled)
+ return;
+
+ logger->log("SoundManager::fadeOutMusic() Fading-out (%i ms)", ms);
+
+ if (mMusic)
+ {
+ Mix_FadeOutMusic(ms);
+ // Note: The fadeOutCallBack handler will take care about freeing
+ // the music file at fade out ending.
+ }
+ else
+ {
+ sFadingOutEnded = true;
+ }
+}
+
+void SoundManager::fadeOutAndPlayMusic(const std::string &fileName, const int ms)
+{
+ mNextMusicFile = fileName;
+ fadeOutMusic(ms);
+}
+
+void SoundManager::logic()
+{
+ BLOCK_START("SoundManager::logic")
+ if (sFadingOutEnded)
+ {
+ if (mMusic)
+ {
+ mMusic->decRef();
+ mMusic = nullptr;
+ }
+ sFadingOutEnded = false;
+
+ if (!mNextMusicFile.empty())
+ {
+ playMusic(mNextMusicFile);
+ mNextMusicFile.clear();
+ }
+ }
+ BLOCK_END("SoundManager::logic")
+}
+
+void SoundManager::playSfx(const std::string &path, const int x, const int y) const
+{
+ if (!mInstalled || path.empty() || !mPlayBattle)
+ return;
+
+ std::string tmpPath;
+ if (!path.compare(0, 4, "sfx/"))
+ tmpPath = path;
+ else
+ tmpPath = paths.getValue("sfx", "sfx/") + path;
+ ResourceManager *const resman = ResourceManager::getInstance();
+ SoundEffect *const sample = resman->getSoundEffect(tmpPath);
+ if (sample)
+ {
+ logger->log("SoundManager::playSfx() Playing: %s", path.c_str());
+ int vol = 120;
+ if (player_node && (x > 0 || y > 0))
+ {
+ int dx = player_node->getTileX() - x;
+ int dy = player_node->getTileY() - y;
+ if (dx < 0)
+ dx = -dx;
+ if (dy < 0)
+ dy = -dy;
+ const int dist = dx > dy ? dx : dy;
+ if (dist * 8 > vol)
+ return;
+
+ vol -= dist * 8;
+ }
+ sample->play(0, vol);
+ }
+}
+
+void SoundManager::playGuiSound(const std::string &name)
+{
+ playGuiSfx(branding.getStringValue("systemsounds")
+ + config.getStringValue(name) + ".ogg");
+}
+
+void SoundManager::playGuiSfx(const std::string &path)
+{
+ if (!mInstalled || path.empty() || !mPlayGui)
+ return;
+
+ std::string tmpPath;
+ if (!path.compare(0, 4, "sfx/"))
+ tmpPath = path;
+ else
+ tmpPath = paths.getValue("sfx", "sfx/") + path;
+ ResourceManager *const resman = ResourceManager::getInstance();
+ SoundEffect *const sample = resman->getSoundEffect(tmpPath);
+ if (sample)
+ {
+ logger->log("SoundManager::playGuiSfx() Playing: %s", path.c_str());
+ const int ret = sample->play(0, 120, mGuiChannel);
+ if (ret != -1)
+ mGuiChannel = ret;
+ }
+}
+
+void SoundManager::close()
+{
+ if (!mInstalled)
+ return;
+
+ haltMusic();
+ logger->log1("SoundManager::close() Shutting down sound...");
+ Mix_CloseAudio();
+
+ mInstalled = false;
+}
+
+void SoundManager::haltMusic()
+{
+ if (!mMusic)
+ return;
+
+ Mix_HaltMusic();
+ if (mMusic)
+ {
+ mMusic->decRef();
+ mMusic = nullptr;
+ }
+}
+
+void SoundManager::changeAudio()
+{
+ if (mInstalled)
+ close();
+ else
+ init();
+}
+
+void SoundManager::volumeOff() const
+{
+ if (mInstalled)
+ {
+ Mix_VolumeMusic(0);
+ Mix_Volume(-1, 0);
+ }
+}
+
+void SoundManager::volumeRestore()
+{
+ if (mInstalled)
+ {
+ Mix_VolumeMusic(mMusicVolume);
+ Mix_Volume(-1, mSfxVolume);
+ }
+}