Back to index

supertuxkart  0.5+dfsg1
music_information.cpp
Go to the documentation of this file.
00001 //  $Id: music_information.cpp 1610 2008-03-01 03:18:53Z hikerstk $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2008 Joerg Henrichs
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program 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 this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 
00021 #include <stdexcept>
00022 
00023 #include "music_information.hpp"
00024 #include "lisp/lisp.hpp"
00025 #include "lisp/parser.hpp"
00026 #include "string_utils.hpp"
00027 #include "track_manager.hpp"
00028 #include "track.hpp"
00029 #include "translation.hpp"
00030 #include "user_config.hpp"
00031 #include "music_ogg.hpp"
00032 
00033 #if defined(WIN32) && !defined(__CYGWIN__)
00034 #  define snprintf _snprintf
00035 #endif
00036 
00037 MusicInformation::MusicInformation(const std::string& filename)
00038 {
00039     m_title           = "";
00040     m_composer        = "";
00041     m_numLoops        = LOOP_FOREVER;
00042     m_normal_filename = "";
00043     m_fast_filename   = "";
00044     m_normal_music    = NULL;
00045     m_fast_music      = NULL;
00046     m_faster_time     = 1.0f;
00047     m_max_pitch       = 0.1f;
00048 
00049     if(StringUtils::extension(filename)!="music")
00050     {
00051         // Create information just from ogg file
00052         // -------------------------------------
00053         m_title           = StringUtils::without_extension(StringUtils::basename(filename));
00054         m_normal_filename = filename;
00055         return;
00056     }
00057    
00058 
00059     // Otherwise read config file
00060     // --------------------------
00061     lisp::Parser parser;
00062     const lisp::Lisp* const ROOT = parser.parse(filename);
00063 
00064     const lisp::Lisp* const LISP = ROOT->getLisp("music-information");
00065     if(!LISP)
00066     {
00067         delete ROOT;
00068         char msg[MAX_ERROR_MESSAGE_LENGTH];
00069         snprintf(msg, sizeof(msg), 
00070                  "Couldn't load music information '%s': no music-information node.",
00071                  filename.c_str());
00072         throw std::runtime_error(msg);
00073     }
00074     LISP->get      ("title",       m_title          );
00075     LISP->get      ("composer",    m_composer       );
00076     LISP->get      ("loop",        m_numLoops       );
00077     LISP->get      ("music",       m_normal_filename);
00078     LISP->get      ("fast-music",  m_fast_filename  );
00079     // m_faster_time is used for twice: either as time to fade in faster music
00080     // (if available), or the time to increase the pitch (if no faster music 
00081     // is available). We allow each .music file to use any of the two names. 
00082     // LISP->get doesn't change the value if the item is not found.
00083     LISP->get      ("fade-time",   m_faster_time    );
00084     LISP->get      ("faster-time", m_faster_time    );
00085     LISP->get      ("max-pitch",   m_max_pitch      );
00086     LISP->getVector("tracks",      m_all_tracks     );
00087 
00088     // Get the path from the filename and add it to the ogg filename
00089     std::string path=StringUtils::path(filename);
00090     m_normal_filename=path+"/"+m_normal_filename;
00091 
00092     // Get the path from the filename and add it to the ogg filename
00093     if(m_fast_filename!="")
00094     {
00095         m_fast_filename=path+"/"+m_fast_filename;
00096     }
00097 
00098     delete ROOT;
00099 
00100 }   // MusicInformation
00101 
00102 //-----------------------------------------------------------------------------
00103 void MusicInformation::addMusicToTracks()
00104 {
00105     for(int i=0; i<(int)m_all_tracks.size(); i++)
00106     {
00107         Track* track=track_manager->getTrack(m_all_tracks[i]);
00108         if(track) track->addMusic(this);
00109     }
00110 }   // addMusicToTracks
00111 
00112 //-----------------------------------------------------------------------------
00113 void MusicInformation::startMusic()
00114 {
00115     m_time_since_faster  = 0.0f;
00116     m_mode               = SOUND_NORMAL;
00117 
00118     if (m_normal_filename== "") return;
00119 
00120     // First load the 'normal' music
00121     // -----------------------------
00122     if(StringUtils::extension(m_normal_filename)!="ogg")
00123     {
00124         fprintf(stderr, "WARNING: music file %s format not recognized.\n", 
00125                 m_normal_filename.c_str());
00126         return;
00127     }
00128     m_normal_music = new MusicOggStream();
00129 
00130     if((m_normal_music->load(m_normal_filename)) == false)
00131     {
00132         delete m_normal_music;
00133         m_normal_music=0;
00134            fprintf(stderr, "WARNING: Unabled to load music %s, not supported or not found.\n", 
00135                 m_normal_filename.c_str());
00136         return;
00137     }
00138     m_normal_music->playMusic();
00139 
00140     // Then (if available) load the music for the last track
00141     // -----------------------------------------------------
00142     if(m_fast_filename=="") 
00143     {
00144         m_fast_music = NULL;
00145         return;   // no fast music
00146     }
00147 
00148     if(StringUtils::extension(m_fast_filename)!="ogg")
00149     {
00150         fprintf(stderr, 
00151                 "WARNING: music file %s format not recognized, fast music is ignored\n", 
00152                 m_fast_filename.c_str());
00153         return;
00154     }
00155     m_fast_music= new MusicOggStream();
00156 
00157     if((m_fast_music->load(m_fast_filename)) == false)
00158     {
00159         delete m_fast_music;
00160         m_fast_music=0;
00161            fprintf(stderr, "WARNING: Unabled to load fast music %s, not supported or not found.\n", 
00162                 m_fast_filename.c_str());
00163         return;
00164     }
00165 }   // startMusic
00166 
00167 //-----------------------------------------------------------------------------
00168 void MusicInformation::update(float dt)
00169 {
00170     switch(m_mode)
00171     {
00172     case SOUND_FADING: {
00173         if ( m_normal_music == NULL || m_fast_music == NULL ) break;
00174 
00175         m_time_since_faster +=dt;
00176         if(m_time_since_faster>=m_faster_time)
00177         {
00178             m_mode=SOUND_FAST;
00179             m_normal_music->stopMusic();
00180             m_fast_music->update();
00181             return;
00182         }
00183         float fraction=m_time_since_faster/m_faster_time;
00184         m_normal_music->updateFading(1-fraction);
00185         m_fast_music->updateFading(fraction);
00186         break;
00187                        }
00188     case SOUND_FASTER: {
00189         if ( m_normal_music == NULL ) break;
00190 
00191         m_time_since_faster +=dt;
00192         if(m_time_since_faster>=m_faster_time)
00193         {
00194             // Once the pitch is adjusted, just switch back to normal
00195             // mode. We can't switch to fast music mode, since this would
00196             // play m_fast_music, which isn't available.
00197             m_mode=SOUND_NORMAL;
00198             return;
00199         }
00200         float fraction=m_time_since_faster/m_faster_time;
00201         m_normal_music->updateFaster(fraction, m_max_pitch);
00202 
00203         break;
00204                        }
00205     case SOUND_NORMAL:
00206         if ( m_normal_music == NULL ) break;
00207 
00208         m_normal_music->update();
00209         break;
00210     case SOUND_FAST:
00211         if ( m_fast_music == NULL ) break;
00212 
00213         m_fast_music->update();
00214         break;
00215     }   // switch
00216 
00217 }   // update
00218 
00219 //-----------------------------------------------------------------------------
00220 void MusicInformation::stopMusic()
00221 {
00222     if (m_normal_music != NULL)  
00223     {
00224         m_normal_music->stopMusic();
00225         m_normal_music = NULL;
00226     }
00227     if (m_fast_music   != NULL)
00228     {
00229         m_fast_music->stopMusic();
00230         m_fast_music=NULL;
00231     }
00232 }   // stopMusic
00233 
00234 //-----------------------------------------------------------------------------
00235 void MusicInformation::pauseMusic()
00236 {
00237     if (m_normal_music != NULL) m_normal_music->pauseMusic();
00238     if (m_fast_music   != NULL) m_fast_music->pauseMusic();
00239 }   // pauseMusic
00240 //-----------------------------------------------------------------------------
00241 void MusicInformation::resumeMusic()
00242 {
00243     if (m_normal_music != NULL) m_normal_music->resumeMusic();
00244     if (m_fast_music   != NULL) m_fast_music->resumeMusic();
00245 }   // resumeMusic
00246 
00247 //-----------------------------------------------------------------------------
00248 void MusicInformation::switchToFastMusic()
00249 {    
00250     m_time_since_faster = 0.0f;
00251     if(m_fast_music)
00252     {
00253         m_mode = SOUND_FADING;
00254         m_fast_music->playMusic();
00255     }
00256     else
00257     {
00258         // FIXME: for now this music is too annoying, 
00259         m_mode = SOUND_FASTER;
00260     }
00261 }   // switchToFastMusic
00262 
00263 //-----------------------------------------------------------------------------