diff options
author | Andrei Karas <akaras@inbox.ru> | 2011-01-02 01:48:38 +0200 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2011-01-02 02:41:24 +0200 |
commit | 3eeae12c498d1a4dbe969462d2ba841f77ee3ccb (patch) | |
tree | ff8eab35e732bc0749fc11677c8873a7b3a58704 /src/sound.cpp | |
download | manaplus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.gz manaplus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.bz2 manaplus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.tar.xz manaplus-3eeae12c498d1a4dbe969462d2ba841f77ee3ccb.zip |
Initial commit.
This code based on mana client http://www.gitorious.org/mana/mana
and my private repository.
Diffstat (limited to 'src/sound.cpp')
-rw-r--r-- | src/sound.cpp | 344 |
1 files changed, 344 insertions, 0 deletions
diff --git a/src/sound.cpp b/src/sound.cpp new file mode 100644 index 000000000..8742ce361 --- /dev/null +++ b/src/sound.cpp @@ -0,0 +1,344 @@ +/* + * The Mana Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * + * This file is part of The Mana 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 <SDL.h> + +#include "configuration.h" +#include "log.h" +#include "sound.h" + +#include "resources/resourcemanager.h" +#include "resources/soundeffect.h" + +#include "configuration.h" + +Sound::Sound(): + mInstalled(false), + mSfxVolume(100), + mMusicVolume(60), + mMusic(0), + mPlayBattle(false), + mPlayGui(false), + mPlayMusic(false) +{ +} + +Sound::~Sound() +{ + config.removeListener("playBattleSound", this); + config.removeListener("playGuiSound", this); + config.removeListener("playMusic", this); +} + +void Sound::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"); +} + +void Sound::init() +{ + // Don't initialize sound engine twice + if (mInstalled) + return; + + logger->log1("Sound::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); + + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) + { + logger->log1("Sound::init() Failed to initialize audio subsystem"); + return; + } + + const size_t audioBuffer = 4096; + + const int res = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, + MIX_DEFAULT_CHANNELS, audioBuffer); + if (res < 0) + { + logger->log("Sound::init Could not initialize audio: %s", + Mix_GetError()); + return; + } + + Mix_AllocateChannels(16); + Mix_VolumeMusic(mMusicVolume); + Mix_Volume(-1, mSfxVolume); + + info(); + + mInstalled = true; + + if (!mCurrentMusicFile.empty() && mPlayMusic) + playMusic(mCurrentMusicFile); +} + +void Sound::info() +{ + SDL_version compiledVersion; + const SDL_version *linkedVersion; + char driver[40] = "Unknown"; + const char *format = "Unknown"; + int rate = 0; + Uint16 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("Sound::info() SDL_mixer: %i.%i.%i (compiled)", + compiledVersion.major, + compiledVersion.minor, + compiledVersion.patch); + logger->log("Sound::info() SDL_mixer: %i.%i.%i (linked)", + linkedVersion->major, + linkedVersion->minor, + linkedVersion->patch); + logger->log("Sound::info() Driver: %s", driver); + logger->log("Sound::info() Format: %s", format); + logger->log("Sound::info() Rate: %i", rate); + logger->log("Sound::info() Channels: %i", channels); +} + +int Sound::getMaxVolume() const +{ + return MIX_MAX_VOLUME; +} + +void Sound::setMusicVolume(int volume) +{ + mMusicVolume = volume; + + if (mInstalled) + Mix_VolumeMusic(mMusicVolume); +} + +void Sound::setSfxVolume(int volume) +{ + mSfxVolume = volume; + + if (mInstalled) + Mix_Volume(-1, mSfxVolume); +} + +static Mix_Music *loadMusic(const std::string &filename) +{ + ResourceManager *resman = ResourceManager::getInstance(); + std::string path = resman->getPath( + paths.getStringValue("music") + filename); + + if (path.find(".zip/") != std::string::npos || + path.find(".zip\\") != std::string::npos) + { + // Music file is a virtual file inside a zip archive - we have to copy + // it to a temporary physical file so that SDL_mixer can stream it. + logger->log("Loading music \"%s\" from temporary file tempMusic.ogg", + path.c_str()); + bool success = resman->copyFile(paths.getStringValue("music") + + filename, "tempMusic.ogg"); + if (success) + path = resman->getPath("tempMusic.ogg"); + else + return NULL; + } + else + { + logger->log("Loading music \"%s\"", path.c_str()); + } + + if (path.empty()) + return 0; + + Mix_Music *music = Mix_LoadMUS(path.c_str()); + + if (!music) + { + logger->log("Mix_LoadMUS() Error loading '%s': %s", path.c_str(), + Mix_GetError()); + } + + return music; +} + +void Sound::playMusic(const std::string &filename) +{ + mCurrentMusicFile = filename; + + if (!mInstalled || !mPlayMusic) + return; + + haltMusic(); + + if ((mMusic = loadMusic(filename))) + Mix_PlayMusic(mMusic, -1); // Loop forever +} + +void Sound::stopMusic() +{ + if (!mInstalled) + return; + + logger->log1("Sound::stopMusic()"); + + if (mMusic) + { + Mix_HaltMusic(); + Mix_FreeMusic(mMusic); + mMusic = NULL; + } +} + +void Sound::fadeInMusic(const std::string &path, int ms) +{ + mCurrentMusicFile = path; + + if (!mInstalled || !mPlayMusic) + return; + + haltMusic(); + + if ((mMusic = loadMusic(path.c_str()))) + Mix_FadeInMusic(mMusic, -1, ms); // Loop forever +} + +void Sound::fadeOutMusic(int ms) +{ + mCurrentMusicFile.clear(); + + if (!mInstalled) + return; + + logger->log("Sound::fadeOutMusic() Fading-out (%i ms)", ms); + + if (mMusic) + { + Mix_FadeOutMusic(ms); + Mix_FreeMusic(mMusic); + mMusic = NULL; + } +} + +void Sound::playSfx(const std::string &path) +{ + if (!mInstalled || path.empty() || !mPlayBattle) + return; + + std::string tmpPath; + if (!path.find("sfx/")) + tmpPath = path; + else + tmpPath = paths.getValue("sfx", "sfx/") + path; + ResourceManager *resman = ResourceManager::getInstance(); + SoundEffect *sample = resman->getSoundEffect(tmpPath); + if (sample) + { + logger->log("Sound::playSfx() Playing: %s", path.c_str()); + sample->play(0, 120); + } +} + +void Sound::playGuiSfx(const std::string &path) +{ + if (!mInstalled || path.empty() || !mPlayGui) + return; + + ResourceManager *resman = ResourceManager::getInstance(); + SoundEffect *sample = resman->getSoundEffect( + paths.getStringValue("sfx") + path); + if (sample) + { + logger->log("Sound::playSfx() Playing: %s", path.c_str()); + sample->play(0, 120); + } +} + +void Sound::close() +{ + if (!mInstalled) + return; + + haltMusic(); + logger->log1("Sound::close() Shutting down sound..."); + Mix_CloseAudio(); + + mInstalled = false; +} + +void Sound::haltMusic() +{ + if (!mMusic) + return; + + Mix_HaltMusic(); + Mix_FreeMusic(mMusic); + mMusic = NULL; +} + +void Sound::changeAudio() +{ + if (mInstalled) + close(); + else + init(); +} + +void Sound::volumeOff() +{ + if (mInstalled) + { + Mix_VolumeMusic(0); + Mix_Volume(-1, 0); + } +} + +void Sound::volumeRestore() +{ + if (mInstalled) + { + Mix_VolumeMusic(mMusicVolume); + Mix_Volume(-1, mSfxVolume); + } +} |