LandscapeMusicManager.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <landscape/LandscapeMusicManager.h>
00022 #include <landscapedef/LandscapeTex.h>
00023 #include <landscapedef/LandscapeDefn.h>
00024 #include <landscapemap/LandscapeMaps.h>
00025 #include <graph/OptionsDisplay.h>
00026 #include <client/ScorchedClient.h>
00027 #include <client/ClientState.h>
00028 #include <common/Defines.h>
00029 #include <sound/Sound.h>
00030 #include <XML/XMLFile.h>
00031 
00032 LandscapeMusicManager *LandscapeMusicManager::instance()
00033 {
00034         static LandscapeMusicManager instance_;
00035         return &instance_;
00036 }
00037 
00038 LandscapeMusicManager::LandscapeMusicManager() : 
00039         GameStateI("LandscapeMusicManager")
00040 {
00041         addMusics();
00042 }
00043 
00044 LandscapeMusicManager::~LandscapeMusicManager()
00045 {
00046 }
00047 
00048 void LandscapeMusicManager::addMusics()
00049 {
00050         stateMusic_.clear();
00051         
00052         // Read in the global music defaults
00053         // Do this first so that levels can override the music if required
00054         readGlobalMusicFile();
00055 
00056         // Load in the per level music
00057         LandscapeDefn *defn = 
00058                 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getDefn();
00059         LandscapeTex *tex = 
00060                 ScorchedClient::instance()->getLandscapeMaps().getDefinitions().getTex();
00061 
00062         // Since we initialize before the landscapes are loaded these may be null
00063         if (tex) addMusic(tex->texDefn.includes);
00064         if (defn) addMusic(defn->texDefn.includes);
00065 }
00066 
00067 void LandscapeMusicManager::readGlobalMusicFile()
00068 {
00069         std::string filePath = S3D::getDataFile("data/music.xml");
00070 
00071         // Parse the XML file
00072         XMLFile file;
00073         if (!file.readFile(filePath))
00074         {
00075                 S3D::dialogExit("Scorched3D", S3D::formatStringBuffer(
00076                         "ERROR: Failed to parse music file \"%s\"\n"
00077                         "%s",
00078                         filePath.c_str(),
00079                         file.getParserError()));
00080         }
00081 
00082         // just return for an empty file
00083         if (!file.getRootNode()) return;
00084 
00085         XMLNode *musicNode = 0;
00086         while (file.getRootNode()->getNamedChild("music", musicNode, false))
00087         {
00088                 LandscapeMusicType musicType;
00089                 musicType.playstates.clear();
00090                 if (!musicType.readXML(musicNode))
00091                 {
00092                         S3D::dialogExit("Scorched3D", S3D::formatStringBuffer(
00093                                 "ERROR: Failed to parse music file \"%s\"\n",
00094                                 filePath.c_str()));
00095                 }
00096                 addMusicType(&musicType);
00097         }
00098 }
00099 
00100 void LandscapeMusicManager::addMusic(std::vector<LandscapeInclude *> &musics)
00101 {
00102         std::vector<LandscapeInclude *>::iterator includeitor;
00103         for (includeitor = musics.begin();
00104                 includeitor != musics.end(); 
00105                 includeitor++)
00106         {
00107                 LandscapeInclude *include = (*includeitor);
00108                 addMusicTypes(include->musics);
00109         }
00110 }
00111 
00112 void LandscapeMusicManager::addMusicTypes(std::vector<LandscapeMusicType *> &musics)
00113 {
00114         std::vector<LandscapeMusicType *>::iterator itor;
00115         for (itor = musics.begin();
00116                 itor != musics.end();
00117                 itor++)
00118         {
00119                 LandscapeMusicType *music = (*itor);
00120                 addMusicType(music);
00121         }
00122 }
00123 
00124 void LandscapeMusicManager::addMusicType(LandscapeMusicType *music)
00125 {
00126         std::vector<LandscapeMusicType::PlayState>::iterator stateitor;
00127         for (stateitor = music->playstates.begin();
00128                 stateitor != music->playstates.end();
00129                 stateitor++)
00130         {
00131                 LandscapeMusicType::PlayState playState = (*stateitor);
00132 
00133                 MusicStateEntry stateEntry;
00134                 stateEntry.file = music->file;
00135                 stateEntry.gain = music->gain;
00136                 if (stateMusic_.find(int(playState)) == stateMusic_.end())
00137                 {
00138                         stateMusic_.insert(std::pair<int, MusicStateEntry>(int(playState), stateEntry));
00139                 }
00140                 else
00141                 {
00142                         stateMusic_[int(playState)] = stateEntry;
00143                 }
00144         }
00145 }
00146 
00147 void LandscapeMusicManager::simulate(const unsigned state, float simTime)
00148 {
00149         // Find the playstate that matches the current client state
00150         LandscapeMusicType::PlayState playState = LandscapeMusicType::StateNone;
00151         switch (state)
00152         {
00153         case ClientState::StateOptions:
00154         case ClientState::StateLoadFiles:
00155         case ClientState::StateGetPlayers:
00156         case ClientState::StateLoadPlayers:
00157         case ClientState::StateLoadLevel:
00158         case ClientState::StateConnect:
00159                 playState = LandscapeMusicType::StateLoading;
00160                 break;
00161         case ClientState::StateWait:
00162                 playState = LandscapeMusicType::StateWait;
00163                 break;
00164         case ClientState::StateBuyWeapons:
00165         case ClientState::StateAutoDefense:
00166                 playState = LandscapeMusicType::StateBuying;
00167                 break;
00168         case ClientState::StatePlaying:
00169                 playState = LandscapeMusicType::StatePlaying;
00170                 break;
00171         case ClientState::StateShot:
00172                 playState = LandscapeMusicType::StateShot;
00173                 break;
00174         case ClientState::StateScore:
00175                 playState = LandscapeMusicType::StateScore;
00176                 break;
00177         default:
00178                 // So I can put a breakpoint in!!
00179                 playState = LandscapeMusicType::StateNone;
00180                 break;
00181         }
00182 
00183         // Find which music entry we should be playing in this state
00184         MusicStateEntry *wantedEntry = 0;
00185         if (!OptionsDisplay::instance()->getNoMusic() &&
00186                 OptionsDisplay::instance()->getMusicVolume() > 0)
00187         {
00188                 std::map<int, MusicStateEntry>::iterator findItor =
00189                         stateMusic_.find(int(playState));
00190                 if (findItor != stateMusic_.end())
00191                 {
00192                         wantedEntry = &(*findItor).second;                              
00193                 }
00194         }
00195 
00196         // Find if we are currently playing this music
00197         bool found = false;
00198         std::list<MusicPlayingEntry *> remove;
00199         std::list<MusicPlayingEntry *>::iterator itor;
00200         for (itor = currentMusic_.begin();
00201                 itor != currentMusic_.end();
00202                 itor++)
00203         {
00204                 MusicPlayingEntry *playingEntry = *itor;
00205 
00206                 float wantedGain = 0;
00207                 if (wantedEntry &&
00208                         wantedEntry->file == playingEntry->file)
00209                 {
00210                         found = true;
00211                         wantedGain = 
00212                                 float(OptionsDisplay::instance()->getMusicVolume()) / 128.0f *
00213                                 wantedEntry->gain;
00214                 }
00215                 else
00216                 {
00217                         wantedGain = 0;
00218                         if (playingEntry->currentGain == 0)
00219                         {
00220                                 remove.push_back(playingEntry);
00221                         }
00222                 }
00223 
00224                 if (playingEntry->currentGain < wantedGain)
00225                 {
00226                         playingEntry->currentGain += simTime * 0.2f;
00227                         playingEntry->currentGain = MIN(
00228                                 wantedGain, 
00229                                 playingEntry->currentGain);
00230                         playingEntry->currentSource->setGain(playingEntry->currentGain);
00231                 }
00232                 else if (playingEntry->currentGain > wantedGain)
00233                 {
00234                         playingEntry->currentGain -= simTime * 0.2f;
00235                         playingEntry->currentGain = MAX(
00236                                 wantedGain, 
00237                                 playingEntry->currentGain);
00238                         playingEntry->currentSource->setGain(playingEntry->currentGain);
00239                 }
00240         }
00241 
00242         // Stop the finished playing sound sources (if any)
00243         // Since the source is managed it will be automatically deleted once it has stopped
00244         for (itor = remove.begin();
00245                 itor != remove.end();
00246                 itor++)
00247         {
00248                 MusicPlayingEntry *playingEntry = *itor;
00249                 playingEntry->currentSource->stop();
00250                 delete playingEntry->currentSource;
00251                 currentMusic_.remove(playingEntry);
00252                 delete playingEntry;
00253         }
00254 
00255         // Create the new sounds sources (if any)
00256         if (!found && wantedEntry)
00257         {
00258                 // Play the next set of music
00259                 // Load the next sound buffer
00260                 SoundBuffer *buffer = 
00261                         Sound::instance()->fetchOrCreateBuffer(
00262                                 S3D::getDataFile(wantedEntry->file.c_str()));
00263                 if (buffer)
00264                 {
00265                         // Start a new sound source
00266                         VirtualSoundSource *currentSource = new VirtualSoundSource(
00267                                 VirtualSoundPriority::eMusic, // A high music priority
00268                                 true, // Its a looping sound
00269                                 false); // Its not automatically deleted when finished
00270 
00271                         // Add to currently playing
00272                         MusicPlayingEntry *playingEntry = new MusicPlayingEntry();
00273                         playingEntry->currentGain = 0;
00274                         playingEntry->currentSource = currentSource;
00275                         playingEntry->file = wantedEntry->file;
00276                         currentMusic_.push_back(playingEntry);
00277 
00278                         // Play it
00279                         playingEntry->currentSource->setGain(0);
00280                         playingEntry->currentSource->setRelative();
00281                         playingEntry->currentSource->play(buffer);
00282                 }
00283         }
00284 }

Generated on Mon Feb 16 15:14:47 2009 for Scorched3D by  doxygen 1.5.3