1 // Copyright (C) 2006 Ulf Lorenz
2 // Copyright (C) 2006 Andrea Paternesi
3 // Copyright (C) 2006, 2007, 2008 Ben Asselstine
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Library General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include <sigc++/functors/mem_fun.h>
28 #include "Configuration.h"
31 #define debug(x) {std::cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<std::endl<<std::flush;}
35 Sound* Sound::s_instance = 0;
38 // used for fading in a music piece after another faded out
39 Mix_Music* _my_toplay = 0;
41 // used for removing a music piece (we only need to have 1 removed at a time
42 Mix_Music* _my_toremove = 0;
44 // how often the music piece is played
51 Mix_FadeInMusic(_my_toplay, loopcount, 1500);
55 if (_my_toremove != 0)
57 Mix_FreeMusic(_my_toremove);
61 Sound::getInstance()->nextPiece();
65 Sound* Sound::getInstance()
68 s_instance = new Sound();
73 void Sound::deleteInstance()
83 :d_broken(false), d_background(false), d_block(false)
85 debug("Sound constructor")
89 if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024) == -1)
91 std::cerr << "Couldn't initialize SDL-mixer\n";
92 std::cerr <<Mix_GetError() <<std::endl;
97 XML_Helper helper(File::getMusicFile("music.xml"), std::ios::in, false);
98 helper.registerTag("piece", sigc::mem_fun(this, &Sound::loadMusic));
102 std::cerr<< "Error loading music descriptions; disable music\n";
108 Mix_HookMusicFinished(_startNext);
110 debug("Music list contains " <<d_musicMap.size() <<" entries.")
111 debug("background list has " <<d_bgMap.size() <<" entries.")
116 debug("Sound destructor")
119 disableBackground(false);
121 // remove all music pieces
122 std::map<std::string, MusicItem*>::iterator it;
123 for (it = d_musicMap.begin(); it != d_musicMap.end(); it++)
128 Mix_FreeMusic(d_music);
137 bool Sound::setMusic(bool enable, int volume)
139 if (volume < 0 || volume > 128)
142 Configuration::s_musicenable = enable;
143 Configuration::s_musicvolume = volume;
145 Mix_VolumeMusic(volume);
151 bool Sound::isMusicEnabled()
153 return Configuration::s_musicenable;
156 int Sound::getMusicVolume()
158 return Configuration::s_musicvolume;
161 bool Sound::playMusic(std::string piece, int nloops, bool fade)
163 debug("playing Music")
165 if (d_broken || !Configuration::s_musicenable)
168 // first, load the music piece
169 if (d_musicMap[piece] == 0)
172 if (Mix_PlayingMusic() || Mix_FadingMusic())
175 Mix_Music* music = Mix_LoadMUS(File::getMusicFile(d_musicMap[piece]->file).c_str());
178 //try to load an alternative
179 std::string alias = d_musicMap[piece]->alias;
180 music = Mix_LoadMUS(File::getMusicFile(d_musicMap[alias]->file).c_str());
185 // now start to block playing music (well, a mutex/synchronization
186 // would propably be a good idea here)
189 // then end other music pieces and/or start ours.
190 if (Mix_PlayingMusic() || Mix_FadingMusic())
192 _my_toremove = d_music;
198 Mix_FadeOutMusic(1500);
204 // no other music playing => start ours.
205 Mix_FadeInMusic(music, nloops, 1500);
210 bool Sound::haltMusic(bool fade)
212 debug("stopping music")
216 if (Mix_PlayingMusic() || Mix_FadingMusic())
218 _my_toremove = d_music;
222 Mix_FadeOutMusic(1500);
228 // no music is playing => call nextPiece manually
234 void Sound::enableBackground()
236 debug("enabling background music")
241 void Sound::disableBackground(bool fade)
243 debug("disabling background music")
244 d_background = false;
250 if (Mix_PlayingMusic() || Mix_FadingMusic())
252 _my_toremove = d_music;
256 Mix_FadeOutMusic(1500);
263 void Sound::nextPiece()
265 debug("Sound::nextPiece")
266 if (d_block || !d_background || !isMusicEnabled())
270 if (Mix_PlayingMusic() || Mix_FadingMusic())
273 // remove the old music
276 Mix_FreeMusic(d_music);
280 // select a random music piece from the list of background pieces
281 while (!d_music && !d_bgMap.empty())
283 int select = rand() % d_bgMap.size();
284 d_music = Mix_LoadMUS(File::getMusicFile(d_musicMap[d_bgMap[select]]->file).c_str());
287 // file does not exist. Remove this entry from the list
288 d_bgMap[select] = d_bgMap[0];
289 d_bgMap.erase(d_bgMap.begin());
294 // well, no background music without sound files...
297 Mix_FadeInMusic(d_music, 1, 1500);
301 bool Sound::loadMusic(std::string tag, XML_Helper* helper)
305 std::cerr <<"Loading music: Wrong tag name\n";
310 MusicItem* item = new MusicItem();
313 retval &= helper->getData(tagname, "name");
314 retval &= helper->getData(item->file, "filename");
315 retval &= helper->getData(item->background, "background");
316 retval &= helper->getData(item->alias, "alias");
320 d_musicMap[tagname] = item;
321 if (item->background)
322 d_bgMap.push_back(tagname);