00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "OSDLMusicManager.h"
00028
00029 #include "OSDLAudio.h"
00030
00031
00032 #ifdef OSDL_USES_CONFIG_H
00033 #include "OSDLConfig.h"
00034 #endif // OSDL_USES_CONFIG_H
00035
00036
00037 #if OSDL_ARCH_NINTENDO_DS
00038 #include "OSDLConfigForNintendoDS.h"
00039 #endif // OSDL_ARCH_NINTENDO_DS
00040
00041
00042
00043 #if OSDL_USES_SDL
00044 #include "SDL.h"
00045 #endif // OSDL_USES_SDL
00046
00047 #if OSDL_USES_SDL_MIXER
00048 #include "SDL_mixer.h"
00049 #endif // OSDL_USES_SDL_MIXER
00050
00051
00052 #define OSDL_DEBUG_MUSIC_PLAYBACK 1
00053
00054
00055
00056 #if OSDL_DEBUG_MUSIC_PLAYBACK
00057
00058 #define LOG_DEBUG_AUDIO(message) LogPlug::debug(message)
00059 #define LOG_TRACE_AUDIO(message) LogPlug::trace(message)
00060 #define LOG_WARNING_AUDIO(message) LogPlug::warning(message)
00061
00062 #else // OSDL_DEBUG_MUSIC_PLAYBACK
00063
00064 #define LOG_DEBUG_AUDIO(message)
00065 #define LOG_TRACE_AUDIO(message)
00066 #define LOG_WARNING_AUDIO(message)
00067
00068 #endif // OSDL_DEBUG_MUSIC_PLAYBACK
00069
00070
00071
00072 using std::string ;
00073 using std::list ;
00074
00075
00076 using Ceylan::System::Millisecond ;
00077
00078
00079 using namespace Ceylan::Log ;
00080 using namespace Ceylan::System ;
00081
00082 using namespace OSDL::Audio ;
00083
00084
00085
00086
00095 MusicManagerException::MusicManagerException( const string & reason ) :
00096 AudioException( reason )
00097 {
00098
00099 }
00100
00101
00102
00103 MusicManagerException::~MusicManagerException() throw()
00104 {
00105
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115 MusicPlaybackSetting::MusicPlaybackSetting( Music & music,
00116 PlaybackCount count ) :
00117 _music( & music ),
00118 _count( count ),
00119 _fadeIn( false ),
00120 _fadeOut( false )
00121 {
00122
00123 if ( count == 0 )
00124 throw AudioException( "MusicPlaybackSetting construction failed: "
00125 "null playback count specified" ) ;
00126
00127 if ( count < Audio::Loop )
00128 throw AudioException( "MusicPlaybackSetting construction failed: "
00129 "unexpected playback count specified" ) ;
00130
00131
00132 }
00133
00134
00135
00136 MusicPlaybackSetting::~MusicPlaybackSetting() throw()
00137 {
00138
00139
00140
00141 }
00142
00143
00144
00145 void MusicPlaybackSetting::setFadeInStatus( bool on )
00146 {
00147
00148 _fadeIn = on ;
00149
00150 }
00151
00152
00153
00154 void MusicPlaybackSetting::setFadeOutStatus( bool on )
00155 {
00156
00157 _fadeOut = on ;
00158
00159 }
00160
00161
00162
00163 void MusicPlaybackSetting::startPlayback()
00164 {
00165
00166
00167 if ( _fadeIn )
00168 {
00169
00170
00171
00172 if ( _fadeOut )
00173 {
00174
00175
00176
00177
00178 _music->playWithFadeIn( _count ) ;
00179
00180 }
00181 else
00182 {
00183
00184
00185 _music->playWithFadeIn( _count ) ;
00186
00187 }
00188
00189 }
00190 else
00191 {
00192
00193
00194
00195 if ( _fadeOut )
00196 {
00197
00198
00199
00200
00201 _music->play( _count ) ;
00202
00203 }
00204 else
00205 {
00206
00207
00208 _music->play( _count ) ;
00209
00210 }
00211 }
00212
00213 }
00214
00215
00216
00217 bool MusicPlaybackSetting::onPlaybackEnded()
00218 {
00219
00220
00221
00222
00223
00224
00225
00226 LogPlug::trace( "MusicPlaybackSetting::onPlaybackEnded: "
00227 + toString() ) ;
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 return false ;
00247
00248 }
00249
00250
00251
00252 const string MusicPlaybackSetting::toString( Ceylan::VerbosityLevels level )
00253 const
00254 {
00255
00256 string res = "Music playback setting referencing '"
00257 + _music->toString( level )
00258 + string( "', with " ) + ( _fadeIn ? "a " : "no " )
00259 + string( "fade-in and " ) + ( _fadeOut ? "a " : "no " )
00260 + string( "fade-out, " ) ;
00261
00262 if ( _count == Loop )
00263 return res + "and (infinite) looping requested" ;
00264 else
00265 return res + "with " + Ceylan::toString( _count )
00266 + " planned playbacks" ;
00267
00268 }
00269
00270
00271
00272
00273
00274
00275
00276
00277 MusicManager * MusicManager::_CurrentMusicManager = 0 ;
00278
00279
00280 MusicManager::MusicManager():
00281 _currentMusicPlayback( 0 )
00282 {
00283
00284
00285 ::Mix_HookMusicFinished( HandleMusicPlaybackFinishedCallback ) ;
00286
00287 }
00288
00289
00290
00291 MusicManager::~MusicManager() throw()
00292 {
00293
00294 if ( _currentMusicPlayback != 0 )
00295 stopCurrentMusicPlayback() ;
00296
00297 Ceylan::Uint32 playbackCount = _playList.size() ;
00298
00299 if ( playbackCount != 0 )
00300 {
00301
00302 LogPlug::warning( "MusicManager destructor: still "
00303 + Ceylan::toString( playbackCount )
00304 + " music playback(s) in playlist, removing them." ) ;
00305
00306 for ( list<MusicPlaybackSetting *>::iterator it = _playList.begin();
00307 it != _playList.end(); it++ )
00308 {
00309
00310 delete( *it ) ;
00311
00312 }
00313
00314 }
00315
00316 }
00317
00318
00319
00320 void MusicManager::enqueue( Music & music, PlaybackCount count,
00321 bool fadeIn, bool fadeOut )
00322 {
00323
00324 MusicPlaybackSetting * newSetting = new MusicPlaybackSetting( music,
00325 count ) ;
00326
00327 if ( fadeIn )
00328 newSetting->setFadeInStatus( true ) ;
00329
00330 if ( fadeOut )
00331 newSetting->setFadeOutStatus( true ) ;
00332
00333 _playList.push_back( newSetting ) ;
00334
00335
00336 if ( _currentMusicPlayback == 0 )
00337 startNextMusicPlayback() ;
00338
00339 }
00340
00341
00342
00343 bool MusicManager::isPlaying() const
00344 {
00345
00346 return _currentMusicPlayback != 0 ;
00347
00348 }
00349
00350
00351
00352 const string MusicManager::toString( Ceylan::VerbosityLevels level ) const
00353 {
00354
00355 string res = "Music manager with " ;
00356
00357 if ( _currentMusicPlayback != 0 )
00358 {
00359
00360 res += "following current playback: '"
00361 + _currentMusicPlayback->toString() + "'registered" ;
00362
00363 }
00364 else
00365 {
00366
00367 res = "no current playback registered" ;
00368
00369 }
00370
00371 if ( level == Ceylan::low )
00372 return res + ". Current playlist has "
00373 + Ceylan::toString( _playList.size() ) + " entries" ;
00374
00375 list<string> playbacks ;
00376
00377 for ( list<MusicPlaybackSetting *>::const_iterator it = _playList.begin();
00378 it != _playList.end(); it++ )
00379 {
00380
00381 playbacks.push_back( (*it)->toString( level ) ) ;
00382
00383 }
00384
00385 return res + ". Current playlist is: "
00386 + Ceylan::formatStringList( playbacks ) ;
00387
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 void MusicManager::startNextMusicPlayback()
00402 {
00403
00404 #if OSDL_DEBUG_MUSIC_PLAYBACK
00405
00406 if ( _playList.empty() )
00407 throw MusicManagerException( "MusicManager::startNextMusicPlayback: "
00408 "called with an empty playlist." ) ;
00409
00410 if ( _currentMusicPlayback != 0 )
00411 throw MusicManagerException( "MusicManager::startNextMusicPlayback: "
00412 "called while a music is still being played." ) ;
00413
00414 #endif // OSDL_DEBUG_MUSIC_PLAYBACK
00415
00416 _currentMusicPlayback = _playList.front() ;
00417
00418 _playList.pop_front() ;
00419
00420 _currentMusicPlayback->startPlayback() ;
00421
00422 }
00423
00424
00425
00426 void MusicManager::stopCurrentMusicPlayback()
00427 {
00428
00429 #if OSDL_USES_SDL_MIXER
00430
00431
00432
00433
00434
00435
00436 ::Mix_HaltMusic() ;
00437
00438
00439 #else // OSDL_USES_SDL_MIXER
00440
00441 throw MusicManagerException(
00442 "MusicManager::stopCurrentMusicPlayback failed: "
00443 "no SDL_mixer support available." ) ;
00444
00445 #endif // OSDL_USES_SDL_MIXER
00446
00447 if ( _currentMusicPlayback != 0 )
00448 {
00449
00450 delete _currentMusicPlayback ;
00451 _currentMusicPlayback = 0 ;
00452
00453 }
00454 else
00455 LogPlug::warning( "MusicManager::stopCurrentMusicPlayback: "
00456 "no music was being played." ) ;
00457
00458 }
00459
00460
00461
00462 void MusicManager::onMusicPlaybackFinished()
00463 {
00464
00465 if ( _currentMusicPlayback == 0 )
00466 {
00467
00468 LogPlug::error( "MusicManager::onMusicPlaybackFinished failed: "
00469 "no music was being played." ) ;
00470
00471 return ;
00472
00473 }
00474
00475 if ( _currentMusicPlayback->onPlaybackEnded() == false )
00476 {
00477
00478 delete _currentMusicPlayback ;
00479
00480 _currentMusicPlayback = 0 ;
00481
00482 }
00483
00484 if ( ! _playList.empty() )
00485 startNextMusicPlayback() ;
00486
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 void MusicManager::HandleMusicPlaybackFinishedCallback()
00501 {
00502
00503 OSDL::Audio::getExistingMusicManager().onMusicPlaybackFinished() ;
00504
00505 }
00506
00507
00508
00509
00510
00511
00512
00513 MusicManager & OSDL::Audio::getExistingMusicManager()
00514 {
00515
00516 if ( MusicManager::_CurrentMusicManager == 0 )
00517 throw MusicManagerException( "OSDL::Audio::getExistingMusicManager "
00518 "failed: no manager available." ) ;
00519
00520 return * MusicManager::_CurrentMusicManager ;
00521
00522 }
00523