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 void MusicPlaybackSetting::stopPlayback()
00218 {
00219
00220 _music->stop() ;
00221
00222 }
00223
00224
00225
00226 bool MusicPlaybackSetting::onPlaybackEnded()
00227 {
00228
00229
00230
00231
00232
00233
00234
00235 LogPlug::trace( "MusicPlaybackSetting::onPlaybackEnded: "
00236 + toString() ) ;
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 return false ;
00256
00257 }
00258
00259
00260
00261 const string MusicPlaybackSetting::toString( Ceylan::VerbosityLevels level )
00262 const
00263 {
00264
00265 string res = "Music playback setting referencing '"
00266 + _music->toString( level )
00267 + string( "', with " ) + ( _fadeIn ? "a " : "no " )
00268 + string( "fade-in and " ) + ( _fadeOut ? "a " : "no " )
00269 + string( "fade-out, " ) ;
00270
00271 if ( _count == Loop )
00272 return res + "and (infinite) looping requested" ;
00273 else
00274 return res + "with " + Ceylan::toString( _count )
00275 + " planned playbacks" ;
00276
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286 MusicManager * MusicManager::_CurrentMusicManager = 0 ;
00287
00288
00289 MusicManager::MusicManager():
00290 _currentMusicPlayback( 0 )
00291 {
00292
00293
00294 ::Mix_HookMusicFinished( HandleMusicPlaybackFinishedCallback ) ;
00295
00296 }
00297
00298
00299
00300 MusicManager::~MusicManager() throw()
00301 {
00302
00303 Ceylan::checkpoint( "MusicManager destructor." ) ;
00304
00305 send( "Deleting music manager, whose state was: " + toString() ) ;
00306
00307
00308
00309
00310
00311
00312
00313
00314 Ceylan::Uint32 playbackCount = _playList.size() ;
00315
00316 if ( playbackCount != 0 )
00317 {
00318
00319 LogPlug::warning( "MusicManager destructor: still "
00320 + Ceylan::toString( playbackCount )
00321 + " music playback(s) in playlist, removing them." ) ;
00322
00323 for ( list<MusicPlaybackSetting *>::iterator it = _playList.begin();
00324 it != _playList.end(); it++ )
00325 {
00326
00327 delete( *it ) ;
00328
00329 }
00330
00331 }
00332
00333 stopCurrentMusicPlayback() ;
00334
00335 }
00336
00337
00338
00339 void MusicManager::enqueue( Music & music, PlaybackCount count,
00340 bool fadeIn, bool fadeOut )
00341 {
00342
00343 MusicPlaybackSetting * newSetting = new MusicPlaybackSetting( music,
00344 count ) ;
00345
00346 if ( fadeIn )
00347 newSetting->setFadeInStatus( true ) ;
00348
00349 if ( fadeOut )
00350 newSetting->setFadeOutStatus( true ) ;
00351
00352 _playList.push_back( newSetting ) ;
00353
00354
00355 if ( _currentMusicPlayback == 0 )
00356 startNextMusicPlayback() ;
00357
00358 }
00359
00360
00361
00362 bool MusicManager::isPlaying() const
00363 {
00364
00365 return _currentMusicPlayback != 0 ;
00366
00367 }
00368
00369
00370
00371 const string MusicManager::toString( Ceylan::VerbosityLevels level ) const
00372 {
00373
00374 string res = "Music manager with " ;
00375
00376 if ( _currentMusicPlayback != 0 )
00377 {
00378
00379 res += "following current playback: '"
00380 + _currentMusicPlayback->toString() + "'registered" ;
00381
00382 }
00383 else
00384 {
00385
00386 res = "no current playback registered" ;
00387
00388 }
00389
00390 if ( level == Ceylan::low )
00391 return res + ". Current playlist has "
00392 + Ceylan::toString( _playList.size() ) + " entries" ;
00393
00394 list<string> playbacks ;
00395
00396 for ( list<MusicPlaybackSetting *>::const_iterator it = _playList.begin();
00397 it != _playList.end(); it++ )
00398 {
00399
00400 playbacks.push_back( (*it)->toString( level ) ) ;
00401
00402 }
00403
00404 if ( playbacks.empty() )
00405 return res + ". Current playlist is empty" ;
00406 else
00407 return res + ". Current playlist is: "
00408 + Ceylan::formatStringList( playbacks ) ;
00409
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 void MusicManager::startNextMusicPlayback()
00424 {
00425
00426 #if OSDL_DEBUG_MUSIC_PLAYBACK
00427
00428 if ( _playList.empty() )
00429 throw MusicManagerException( "MusicManager::startNextMusicPlayback: "
00430 "called with an empty playlist." ) ;
00431
00432 if ( _currentMusicPlayback != 0 )
00433 throw MusicManagerException( "MusicManager::startNextMusicPlayback: "
00434 "called while a music is still being played." ) ;
00435
00436 #endif // OSDL_DEBUG_MUSIC_PLAYBACK
00437
00438 _currentMusicPlayback = _playList.front() ;
00439
00440 _playList.pop_front() ;
00441
00442 _currentMusicPlayback->startPlayback() ;
00443
00444 }
00445
00446
00447
00448 void MusicManager::stopCurrentMusicPlayback()
00449 {
00450
00451 Ceylan::checkpoint( "MusicManager::stopCurrentMusicPlayback." ) ;
00452
00453 if ( _currentMusicPlayback != 0 )
00454 {
00455
00456 _currentMusicPlayback->stopPlayback() ;
00457
00458 }
00459
00460 #if OSDL_USES_SDL_MIXER
00461
00462 LogPlug::trace( "MusicManager::stopCurrentMusicPlayback" ) ;
00463
00464
00465
00466
00467
00468
00469 ::Mix_HaltMusic() ;
00470
00471 #else // OSDL_USES_SDL_MIXER
00472
00473 throw MusicManagerException(
00474 "MusicManager::stopCurrentMusicPlayback failed: "
00475 "no SDL_mixer support available." ) ;
00476
00477 #endif // OSDL_USES_SDL_MIXER
00478
00479 if ( _currentMusicPlayback != 0 )
00480 {
00481
00482 delete _currentMusicPlayback ;
00483 _currentMusicPlayback = 0 ;
00484
00485 }
00486 else
00487 {
00488
00489 LogPlug::warning( "MusicManager::stopCurrentMusicPlayback: "
00490 "no music was being played." ) ;
00491
00492 }
00493
00494 }
00495
00496
00497
00498 void MusicManager::onMusicPlaybackFinished()
00499 {
00500
00501 Ceylan::checkpoint( "MusicManager::onMusicPlaybackFinished." ) ;
00502
00503 if ( _currentMusicPlayback == 0 )
00504 {
00505
00506 LogPlug::debug( "MusicManager::onMusicPlaybackFinished failed: "
00507 "no music was being played. Supposing the music playback was "
00508 "triggered directly on the music, rather than thanks to "
00509 "this music manager." ) ;
00510
00511 return ;
00512
00513 }
00514
00515 if ( _currentMusicPlayback->onPlaybackEnded() == false )
00516 {
00517
00518 delete _currentMusicPlayback ;
00519
00520 _currentMusicPlayback = 0 ;
00521
00522 }
00523
00524 if ( ! _playList.empty() )
00525 startNextMusicPlayback() ;
00526
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 void MusicManager::HandleMusicPlaybackFinishedCallback()
00542 {
00543
00544 OSDL::Audio::getExistingMusicManager().onMusicPlaybackFinished() ;
00545
00546 }
00547
00548
00549
00550
00551
00552
00553
00554 MusicManager & OSDL::Audio::getExistingMusicManager()
00555 {
00556
00557 if ( MusicManager::_CurrentMusicManager == 0 )
00558 throw MusicManagerException( "OSDL::Audio::getExistingMusicManager "
00559 "failed: no manager available." ) ;
00560
00561 return * MusicManager::_CurrentMusicManager ;
00562
00563 }
00564