Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

audiomanagersdl.cpp

00001 /***************************************************************************
00002                           audiomanagersdl.cpp  -  description
00003     $Id: audiomanagersdl.cpp 3 2006-06-11 08:16:14Z neoneurone $
00004                              -------------------
00005     begin                : ven déc 26 2003
00006     copyright            : (C) 2003-2005 by Duong-Khang NGUYEN
00007     email                : neoneurone @ users sourceforge net
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   any later version.                                                    *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #include "audiomanagersdl.h"
00020 
00021 #include <fstream>
00022 
00023 
00024    /*====================================================================*/
00025 AudioManager::AudioManager():
00026 boolAudioDeviceInitialized( false ),
00027 boolMusicEnabled( true ),
00028 boolSoundEnabled( true ),
00029 boolRandomMusic( true ),
00030 uiNumberSound( 0 ),
00031 uiNumberMusic( 0 ),
00032 uiCurrentMusic( 0 ),
00033 boolShuffleMusic( false ),
00034 pMusicData( NULL )
00035 {
00036     OPENCITY_DEBUG("ctor");
00037 
00038    // if the audio system is not init. then init. it
00039     if (SDL_WasInit(SDL_INIT_AUDIO) == 0) {
00040         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
00041             OPENCITY_DEBUG( "Audio ERROR" );
00042         }
00043     }
00044 }
00045 
00046 
00047    /*====================================================================*/
00048 AudioManager::~AudioManager()
00049 {
00050     OPENCITY_DEBUG("dtor");
00051 
00052    // clear the music filename list
00053     this->vectorMusicFilename.clear();
00054     this->uiNumberMusic = 0;
00055     this->uiCurrentMusic = 0;
00056 
00057    // if there's a playing music, stop it
00058    // and free the music loaded
00059     if (pMusicData != NULL) {
00060         if (PlayingMusic())
00061             StopMusic();
00062         Mix_FreeMusic( pMusicData );
00063         pMusicData = NULL; // safe
00064     }
00065 
00066    // clear the sound filename list
00067     this->vectorSoundFilename.clear();
00068     this->uiNumberSound = 0;
00069 
00070    // now free all chunks
00071     uint uiVectorSize;
00072     uiVectorSize = vectorpSoundChunk.size();
00073     for (uint i = 0; i < uiVectorSize; i++) {
00074         Mix_FreeChunk( vectorpSoundChunk[i] );
00075     }
00076     this->vectorpSoundChunk.clear();
00077 
00078   // quit the audio device
00079     SDL_QuitSubSystem( SDL_INIT_AUDIO );
00080 }
00081 
00082 
00083    /*====================================================================*/
00084 OPENCITY_ERR_CODE
00085 AudioManager::OpenAudio(void)
00086 {
00087     if ( Mix_OpenAudio( OC_AUDIO_FREQUENCY,
00088                  OC_AUDIO_FORMAT,
00089                  OC_AUDIO_CHANNELS,
00090                  OC_AUDIO_CHUNK_SIZE ) < 0) {
00091         OPENCITY_DEBUG( "Audio opening error" );
00092         return OC_ERR_SOMETHING;
00093     }
00094     else {
00095        // reserve channels for panning effects
00096         if (Mix_ReserveChannels(OC_AUDIO_RESERVED_CHANNELS)
00097                     !=  OC_AUDIO_RESERVED_CHANNELS) {
00098             OPENCITY_DEBUG( "Audio reserving channels error" );
00099             return OC_ERR_SOMETHING;
00100         }
00101 
00102        // register the sounds effects, this doesn't perform test
00103         Mix_SetPanning( AUDIO_LEFT_CHANNEL, 254, 1 );
00104         Mix_SetPanning( AUDIO_LEFT_HALF_CHANNEL, 254, 127 );
00105         Mix_SetPanning( AUDIO_RIGHT_CHANNEL, 1, 254 );
00106         Mix_SetPanning( AUDIO_RIGHT_HALF_CHANNEL, 127, 254 );
00107 
00108        // initialize music / sound volume
00109         VolumeMusic( OC_AUDIO_VOLUME_MAX * 70 / 100 );
00110         VolumeSound( OC_AUDIO_VOLUME_MAX );
00111 
00112         boolAudioDeviceInitialized = true;
00113         return OC_ERR_FREE;
00114     }
00115 }
00116 
00117 
00118    /*====================================================================*/
00119 OPENCITY_ERR_CODE
00120 AudioManager::CloseAudio(void)
00121 {
00122    // warning: we are going to close the audio device
00123     boolAudioDeviceInitialized = false;
00124 
00125    // unregister all sound effects
00126     Mix_UnregisterAllEffects( AUDIO_LEFT_CHANNEL );
00127     Mix_UnregisterAllEffects( AUDIO_LEFT_HALF_CHANNEL );
00128     Mix_UnregisterAllEffects( AUDIO_RIGHT_CHANNEL );
00129     Mix_UnregisterAllEffects( AUDIO_RIGHT_HALF_CHANNEL );
00130 
00131    // unreserve all previously reversed channels for panning
00132     Mix_ReserveChannels( 0 );
00133 
00134    // close the audio device
00135     Mix_CloseAudio();
00136 
00137     return OC_ERR_FREE;
00138 }
00139 
00140 
00141    /*====================================================================*/
00142 OPENCITY_ERR_CODE
00143 AudioManager::LoadMusicList(
00144     const string & csrFilename,
00145     const string& csrPrefix )
00146 {
00147 // Return immediatetly if the audio device is not yet initialized
00148     if (boolAudioDeviceInitialized == false) {
00149         return OC_ERR_SOMETHING;
00150     }
00151 
00152 // Set the current music index to 0
00153     this->uiCurrentMusic = 0;
00154     this->strMusicList = csrFilename;
00155 
00156 // Now parse the music M3U file liste
00157     if (ParseM3UList(csrFilename, this->vectorMusicFilename, this->uiNumberMusic )
00158         != OC_ERR_FREE)
00159         return OC_ERR_SOMETHING;
00160 
00161 // Add the prefix
00162     uint uiVectorSize = vectorMusicFilename.size();
00163     for (uint i = 0; i < uiVectorSize; i++) {
00164         this->vectorMusicFilename[i] = csrPrefix + this->vectorMusicFilename[i];
00165     } // for
00166 
00167     return OC_ERR_FREE;
00168 }
00169 
00170 
00171    /*====================================================================*/
00172 const uint &
00173 AudioManager::GetNumberMusic(void) const
00174 {
00175     return this->uiNumberMusic;
00176 }
00177 
00178 
00179    /*====================================================================*/
00180 bool
00181 AudioManager::PlayingMusic(void) const
00182 {
00183     return Mix_PlayingMusic();
00184 }
00185 
00186 
00187    /*====================================================================*/
00188 OPENCITY_ERR_CODE
00189 AudioManager::PlayMusic(
00190     const uint & rcuiMusicIndex,
00191     const int & rciLoops )
00192 {
00193    // return immediatetly if the audio device is not yet initialized
00194     if (boolAudioDeviceInitialized == false) {
00195         return OC_ERR_SOMETHING;
00196     }
00197 
00198    // if the music is disabled then we return
00199     if (boolMusicEnabled == false) {
00200         return OC_ERR_SOMETHING;
00201     }
00202 
00203     if (rcuiMusicIndex >= this->uiNumberMusic) {
00204         OPENCITY_DEBUG( "Audio play music error" );
00205         return OC_ERR_SOMETHING;
00206     }
00207     else {
00208        // if there's a playing music, stop it
00209        // and free the music loaded
00210         if (pMusicData != NULL) {
00211             if (PlayingMusic())
00212                 StopMusic();
00213 //WARNING: this is buggy
00214             Mix_FreeMusic( pMusicData );
00215             pMusicData = NULL; // safe
00216         }
00217 
00218        // load the new music
00219         OPENCITY_DEBUG( vectorMusicFilename[ rcuiMusicIndex ].c_str() );
00220         pMusicData = Mix_LoadMUS(
00221             this->vectorMusicFilename[ rcuiMusicIndex ].c_str() );
00222         if (pMusicData == NULL) {
00223             return OC_ERR_SOMETHING;
00224         }
00225         OPENCITY_DEBUG("Music succesfully loaded ");
00226 
00227         if (Mix_PlayMusic( pMusicData, rciLoops ) < 0) {
00228             return OC_ERR_SOMETHING;
00229         }
00230         else {
00231            // set the current music to rcuiMusicIndex
00232            // in case this function is called directly
00233            // by the user with a music file index
00234             this->uiCurrentMusic = rcuiMusicIndex;
00235         }
00236     } // rcuiMusicIndex OK
00237 
00238     OPENCITY_DEBUG("Start playing music");
00239     return OC_ERR_FREE;
00240 }
00241 
00242 
00243    /*====================================================================*/
00244 OPENCITY_ERR_CODE
00245 AudioManager::PlayNextMusic(
00246     const int & rciLoops )
00247 {
00248     if ( uiNumberMusic > 0 ) {
00249        // is random function activated ?
00250         if ( boolRandomMusic == true ) {
00251             uiCurrentMusic = rand() % uiNumberMusic;
00252         }
00253         else {
00254             if ( this->uiCurrentMusic < this->uiNumberMusic-1 ) {
00255                 uiCurrentMusic++;
00256             }
00257             else {
00258                 uiCurrentMusic = 0;
00259             }
00260         }
00261 
00262         return PlayMusic( uiCurrentMusic, rciLoops );
00263     }
00264 
00265     return OC_ERR_SOMETHING;
00266 }
00267 
00268 
00269    /*====================================================================*/
00270 OPENCITY_ERR_CODE
00271 AudioManager::PlayPreviousMusic(
00272     const int & rciLoops )
00273 {
00274     if ( uiNumberMusic > 0 ) {
00275        // is random function activated ?
00276         if ( boolRandomMusic == true ) {
00277             uiCurrentMusic = rand() % uiNumberMusic;
00278         }
00279         else {
00280             if (this->uiCurrentMusic > 0) {
00281                 uiCurrentMusic--;
00282             }
00283             else {
00284                 uiCurrentMusic = uiNumberMusic-1;
00285             }
00286         }
00287 
00288         return PlayMusic( uiCurrentMusic, rciLoops );
00289     }
00290 
00291     return OC_ERR_SOMETHING;
00292 }
00293 
00294 
00295    /*====================================================================*/
00296 void
00297 AudioManager::StopMusic(void) const
00298 {
00299     Mix_HaltMusic();
00300 }
00301 
00302 
00303    /*====================================================================*/
00304 void
00305 AudioManager::ToggleRandomMusic(void)
00306 {
00307     boolRandomMusic = !boolRandomMusic;
00308 }
00309 
00310 
00311    /*====================================================================*/
00312 void
00313 AudioManager::ToggleMusic(void)
00314 {
00315     boolMusicEnabled = !boolMusicEnabled;
00316 
00317     if (boolMusicEnabled == false) {
00318         if (this->PlayingMusic() == true)
00319             this->StopMusic();
00320     }
00321     else {
00322         if (this->PlayingMusic() == false)
00323             this->PlayMusic( uiCurrentMusic, 1 );
00324     }
00325 }
00326 
00327 
00328    /*====================================================================*/
00329 void
00330 AudioManager::VolumeMusic(
00331     const int & rciVol ) const
00332 {
00333    // set the volume of the music channel to rciVol
00334     Mix_VolumeMusic( rciVol );
00335 }
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344    /*====================================================================*/
00345 OPENCITY_ERR_CODE
00346 AudioManager::LoadSoundList(
00347     const string& csrFilename,
00348     const string& csrPrefix )
00349 {
00350 // Return immediatetly if the audio device is not yet initialized
00351     if (boolAudioDeviceInitialized == false) {
00352         return OC_ERR_SOMETHING;
00353     }
00354 
00355 // Save the filename of the list
00356     this->strSoundList = csrFilename;
00357 
00358 // Now parse the list
00359     if (ParseM3UList( 
00360             csrFilename, this->vectorSoundFilename, this->uiNumberSound )
00361      == OC_ERR_SOMETHING) {
00362        // list parsing error
00363         return OC_ERR_SOMETHING;
00364     }
00365 
00366 // Free any old vector of sounds loaded
00367     if (!this->vectorpSoundChunk.empty()) {
00368         uint uiVectorSize = vectorpSoundChunk.size();
00369         for (uint i = 0; i < uiVectorSize; i++) {
00370             if (vectorpSoundChunk[i] != NULL) {
00371                 Mix_FreeChunk(vectorpSoundChunk[i]);
00372             }
00373         } // for
00374        // free the vector itself
00375         vectorpSoundChunk.clear();
00376     } // if 
00377 
00378 // Then load all the new sounds
00379     for (uint i = 0; i < this->uiNumberSound; i++) {
00380        // store all pointer's values even if that's NULL;
00381 //debug     cout << i << " : " << vectorSoundFilename[i] << endl;
00382         vectorpSoundChunk.push_back( new (Mix_Chunk) );
00383         vectorpSoundChunk[i] = Mix_LoadWAV(
00384             (csrPrefix+this->vectorSoundFilename[i]).c_str());
00385 //debug     cout << i << " : " << vectorpSoundChunk[i] << endl;
00386     }
00387 
00388 // Even if some sound files don't exist
00389     return OC_ERR_FREE;
00390 }
00391 
00392 
00393    /*====================================================================*/
00394 const uint &
00395 AudioManager::GetNumberSound(void) const
00396 {
00397     return this->uiNumberSound;
00398 }
00399 
00400 
00401    /*====================================================================*/
00402 OPENCITY_ERR_CODE
00403 AudioManager::PlaySound(
00404     const uint & rcuiSoundIndex,
00405     const AUDIO_CHANNEL & enumChannel )
00406 {
00407    // return immediatetly if the audio device is not yet initialized
00408     if (boolAudioDeviceInitialized == false) {
00409         return OC_ERR_SOMETHING;
00410     }
00411 
00412    // if sound is disabled then we return
00413     if (boolSoundEnabled == false) {
00414         return OC_ERR_SOMETHING;
00415     }
00416 
00417     if (rcuiSoundIndex >= this->uiNumberSound) {
00418         OPENCITY_DEBUG( "Audio play sound error" );
00419         return OC_ERR_SOMETHING;
00420     }
00421     else {
00422         if (this->vectorpSoundChunk[ rcuiSoundIndex ] == NULL) {
00423             OPENCITY_DEBUG( "Audio play sound error" );
00424             return OC_ERR_SOMETHING;
00425         }
00426         else {
00427            // play the sound once
00428             if (Mix_PlayChannel( enumChannel,
00429                 vectorpSoundChunk[ rcuiSoundIndex ], 0 ) == -1) {
00430                 return OC_ERR_SOMETHING;
00431             }
00432             else {
00433                // re-register effects for next use
00434             switch ( enumChannel ) {
00435             case AUDIO_LEFT_CHANNEL:
00436                 Mix_SetPanning( enumChannel, 254, 1 );
00437                 break;
00438             case AUDIO_LEFT_HALF_CHANNEL:
00439                 Mix_SetPanning( enumChannel, 254, 127 );
00440                 break;
00441             case AUDIO_RIGHT_CHANNEL:
00442                 Mix_SetPanning( enumChannel, 1, 254 );
00443                 break;
00444             case AUDIO_RIGHT_HALF_CHANNEL:
00445                 Mix_SetPanning( enumChannel, 127, 254 );
00446                 break;
00447             default:
00448                 break;
00449             }
00450             return OC_ERR_FREE;
00451             }
00452         }
00453     } // if rcuiSoundIndex
00454 }
00455 
00456 
00457    /*====================================================================*/
00458 void
00459 AudioManager::ToggleSound(void)
00460 {
00461     boolSoundEnabled = !boolSoundEnabled;
00462 }
00463 
00464 
00465    /*====================================================================*/
00466 void
00467 AudioManager::VolumeSound(
00468     const int & rciVol ) const
00469 {
00470    // set the volume of all channels to rciVol
00471     Mix_Volume( -1, rciVol );
00472 }
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480    /*====================================================================*/
00481 OPENCITY_ERR_CODE
00482 AudioManager::ParseM3UList(
00483     const string & csrFilename,
00484     vector<string> & vectorFilename,
00485     uint & uiNumberFiles )
00486 {
00487 //debug cout << (string)ccaFilename << endl;
00488    // if there's already an old list, free it
00489     if (!vectorFilename.empty()) {
00490         vectorFilename.clear();
00491         uiNumberFiles = 0;
00492     }
00493 
00494    // if we are here, uiNumberFiles must be 0
00495 
00496    // open the ifstream for reading
00497     ifstream listFile( csrFilename.c_str() );
00498     if (listFile == NULL) {
00499         OPENCITY_DEBUG( "Audio file list open error" );
00500         return OC_ERR_SOMETHING;
00501     }
00502 
00503     OC_CHAR tempStr [OC_MAX_FILENAME_LENGTH];
00504 
00505    // read the first line
00506     listFile.getline( tempStr, OC_MAX_FILENAME_LENGTH );
00507     if (listFile.eof()) {
00508         listFile.close();
00509         OPENCITY_DEBUG( "Audio file list error" );
00510         return OC_ERR_SOMETHING;
00511     }
00512 
00513     while (!listFile.eof()) {
00514         if ((strlen(tempStr) != 0)
00515          && (tempStr[0] != '#')) {
00516            // implicite conversion from OC_CHAR* to string
00517             vectorFilename.push_back( tempStr );
00518             uiNumberFiles++;
00519 //debug cout << tempStr << endl;
00520         }
00521        // read the next info line
00522         listFile.getline( tempStr, OC_MAX_FILENAME_LENGTH );
00523     }
00524 
00525     listFile.close();
00526     return OC_ERR_FREE;
00527 
00528 }
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 

Generated on Sat Nov 11 10:21:09 2006 for OpenCity by  doxygen 1.4.2