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 "OSDLCDROMDrive.h"
00028
00029
00030 #include "OSDLUtils.h"
00031
00032
00033 #include "OSDLEmbeddedFileSystemManager.h"
00034
00035
00036
00037 #ifdef OSDL_USES_CONFIG_H
00038 #include "OSDLConfig.h"
00039 #endif // OSDL_USES_CONFIG_H
00040
00041 #if OSDL_ARCH_NINTENDO_DS
00042 #include "OSDLConfigForNintendoDS.h"
00043 #endif // OSDL_ARCH_NINTENDO_DS
00044
00045
00046 #if OSDL_USES_PHYSICSFS
00047 #include "physfs.h"
00048 #endif // OSDL_USES_PHYSICSFS
00049
00050
00051 #include <list>
00052
00053
00054 using std::list ;
00055 using std::string ;
00056
00057
00058 using namespace OSDL ;
00059
00060
00061 #if ! defined(OSDL_USES_SDL) || OSDL_USES_SDL
00062
00063 #include "SDL.h"
00064
00065 #endif // OSDL_USES_SDL
00066
00067
00068
00088
00089
00090
00091 CDTrack::CDTrack( const LowLevelCDROMTrack & track ) :
00092 _trackData( & track )
00093 {
00094
00095 #if ! OSDL_USES_SDL
00096
00097 throw CDROMDriveException( "CDTrack constructor failed: "
00098 "no SDL support available" ) ;
00099
00100 #endif // OSDL_USES_SDL
00101
00102 }
00103
00104
00105
00106 CDTrack::~CDTrack() throw()
00107 {
00108
00109
00110
00111 }
00112
00113
00114
00115 TrackNumber CDTrack::getTrackNumber() const
00116 {
00117
00118 #if OSDL_USES_SDL
00119
00120 return _trackData->id ;
00121
00122 #else // OSDL_USES_SDL
00123
00124 return 0 ;
00125
00126 #endif // OSDL_USES_SDL
00127
00128 }
00129
00130
00131
00132 TrackType CDTrack::getTrackType() const
00133 {
00134
00135 #if OSDL_USES_SDL
00136
00137 switch( _trackData->type )
00138 {
00139
00140 case SDL_AUDIO_TRACK:
00141 return audioTrack ;
00142 break ;
00143
00144 case SDL_DATA_TRACK:
00145 return dataTrack ;
00146 break ;
00147
00148 default:
00149 throw CDROMDriveException( "CDTrack::getTrackType failed: "
00150 "unexpected type (abnormal)." ) ;
00151 break ;
00152
00153 }
00154
00155 #else // OSDL_USES_SDL
00156
00157 throw CDROMDriveException( "CDTrack::getTrackType failed: "
00158 "no SDL support available" ) ;
00159
00160 #endif // OSDL_USES_SDL
00161
00162 }
00163
00164
00165
00166 FrameCount CDTrack::getLength() const
00167 {
00168
00169 #if OSDL_USES_SDL
00170
00171 return _trackData->length ;
00172
00173 #else // OSDL_USES_SDL
00174
00175 return 0 ;
00176
00177 #endif // OSDL_USES_SDL
00178
00179 }
00180
00181
00182
00183 FrameCount CDTrack::getFrameOffset() const
00184 {
00185
00186 #if OSDL_USES_SDL
00187
00188 return _trackData->offset ;
00189
00190 #else // OSDL_USES_SDL
00191
00192 return 0 ;
00193
00194 #endif // OSDL_USES_SDL
00195
00196 }
00197
00198
00199
00200 const string CDTrack::toString( Ceylan::VerbosityLevels level ) const
00201 {
00202
00203 #if OSDL_USES_SDL
00204
00205 string res = "Track #" + Ceylan::toString( getTrackNumber() )
00206 + ": this is " ;
00207
00208 switch( getTrackType() )
00209 {
00210
00211 case audioTrack:
00212 res += "an audio track, its length is "
00213 + Ceylan::toString( getLength() )
00214 + " frames (about "
00215 + Ceylan::toString(
00216 CDROMDrive::ConvertFrameCountToTime( getLength() ) )
00217 + " seconds)" ;
00218 break ;
00219
00220 case dataTrack:
00221 res += "a data track, its length is "
00222 + Ceylan::toString( getLength() )
00223 + " frames" ;
00224 break ;
00225
00226 default:
00227 res += "unexpected track type" ;
00228 break ;
00229
00230 }
00231
00232 res += ". Current frame offset is " + Ceylan::toString( getFrameOffset() ) ;
00233
00234 return res ;
00235
00236 #else // OSDL_USES_SDL
00237
00238 return "" ;
00239
00240 #endif // OSDL_USES_SDL
00241
00242 }
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 #if OSDL_USES_SDL
00253
00254 const FrameCount CDROMDrive::FramesPerSecond = CD_FPS ;
00255
00256 #else // OSDL_USES_SDL
00257
00258 const FrameCount CDROMDrive::FramesPerSecond = 75 ;
00259
00260 #endif // OSDL_USES_SDL
00261
00262
00263
00264
00265 CDROMDrive::CDROMDrive( CDROMDriveNumber driveNumber ) :
00266 Object(),
00267 _driveNumber( driveNumber ),
00268 _statusUpdated( false ),
00269 _driveStatus( 0 )
00270 {
00271
00272 #if ! OSDL_USES_SDL
00273
00274 throw CDROMDriveException( "CDROMDrive constructor failed: "
00275 "no SDL support available" ) ;
00276
00277 #endif // OSDL_USES_SDL
00278
00279 }
00280
00281
00282
00283 CDROMDrive::~CDROMDrive() throw()
00284 {
00285
00286 if ( _driveStatus != 0 )
00287 close() ;
00288
00289 }
00290
00291
00292
00293 void CDROMDrive::open()
00294 {
00295
00296 #if OSDL_USES_SDL
00297
00298 if ( _driveStatus != 0 )
00299 throw CDROMDriveException(
00300 "CDROMDrive::open: drive already opened." ) ;
00301
00302 _driveStatus = SDL_CDOpen( _driveNumber ) ;
00303
00304 if ( _driveStatus == 0 )
00305 throw CDROMDriveException( "CDROMDrive::open: open failed: "
00306 + Utils::getBackendLastError() ) ;
00307
00308 #endif // OSDL_USES_SDL
00309
00310 }
00311
00312
00313
00314 void CDROMDrive::close()
00315 {
00316
00317 #if OSDL_USES_SDL
00318
00319 if ( _driveStatus == 0 )
00320 throw CDROMDriveException(
00321 "CDROMDrive::close: drive was not already opened." ) ;
00322
00323 SDL_CDClose( _driveStatus ) ;
00324
00325
00326 _driveStatus = 0 ;
00327
00328 #endif // OSDL_USES_SDL
00329
00330 }
00331
00332
00333
00334 void CDROMDrive::eject() const
00335 {
00336
00337 #if OSDL_USES_SDL
00338 if ( _driveStatus == 0 )
00339 throw CDROMDriveException(
00340 "CDROMDrive::eject: drive was not already opened." ) ;
00341
00342 if ( SDL_CDEject( _driveStatus ) != 0 )
00343 throw CDROMDriveException(
00344 "CDROMDrive::eject: " + Utils::getBackendLastError() ) ;
00345
00346 #endif // OSDL_USES_SDL
00347
00348 }
00349
00350
00351
00352 CDROMDrive::Status CDROMDrive::getStatus()
00353 {
00354
00355 Status status = getConstStatus() ;
00356
00357 _statusUpdated = true ;
00358
00359 return status ;
00360
00361 }
00362
00363
00364
00365 CDROMDrive::Status CDROMDrive::getConstStatus() const
00366 {
00367
00368 #if OSDL_USES_SDL
00369
00370 if ( _driveStatus == 0 )
00371 throw CDROMDriveException(
00372 "CDROMDrive::getConstStatus: drive was not already opened." ) ;
00373
00374
00375 switch( SDL_CDStatus( _driveStatus ) )
00376 {
00377
00378 case CD_TRAYEMPTY:
00379 return TrayEmpty ;
00380 break ;
00381
00382 case CD_STOPPED:
00383 return Stopped ;
00384 break ;
00385
00386 case CD_PLAYING:
00387 return Playing ;
00388 break ;
00389
00390 case CD_PAUSED:
00391 return Paused ;
00392 break ;
00393
00394 case CD_ERROR:
00395 return InError ;
00396 break ;
00397
00398 default:
00399 throw CDROMDriveException(
00400 "CDROMDrive::getConstStatus: unknown status read" ) ;
00401 break ;
00402
00403 }
00404
00405 #else // OSDL_USES_SDL
00406
00407 return InError ;
00408
00409 #endif // OSDL_USES_SDL
00410
00411 }
00412
00413
00414
00415 bool CDROMDrive::isCDInDrive()
00416 {
00417
00418 CDROMDrive::Status status = getStatus() ;
00419
00420 return ( ( status != TrayEmpty) && ( status != InError ) ) ;
00421
00422 }
00423
00424
00425
00426 TrackNumber CDROMDrive::getTracksCount() const
00427 {
00428
00429 #if OSDL_USES_SDL
00430
00431 if ( _driveStatus == 0 )
00432 throw CDROMDriveException(
00433 "CDROMDrive::getTracksCount: drive was not already opened." ) ;
00434
00435 return _driveStatus->numtracks ;
00436
00437 #else // OSDL_USES_SDL
00438
00439 return 0 ;
00440
00441 #endif // OSDL_USES_SDL
00442
00443 }
00444
00445
00446
00447 FrameCount CDROMDrive::getTrackDuration( TrackNumber targetTrack ) const
00448 {
00449
00450 #if OSDL_USES_SDL
00451
00452
00453 if ( targetTrack >= getTracksCount() )
00454 throw CDROMDriveException( "CDROMDrive::getTrackDuration: "
00455 "specified track (" + Ceylan::toString( targetTrack )
00456 + ") out of range." ) ;
00457
00458 return _driveStatus->track[targetTrack].length ;
00459
00460 #else // OSDL_USES_SDL
00461
00462 return 0 ;
00463
00464 #endif // OSDL_USES_SDL
00465
00466 }
00467
00468
00469
00470 CDTrack & CDROMDrive::getTrack( TrackNumber targetTrack ) const
00471 {
00472
00473 #if OSDL_USES_SDL
00474
00475
00476 if ( targetTrack >= getTracksCount() )
00477 throw CDROMDriveException( "CDROMDrive::getTrack: "
00478 "specified track (" + Ceylan::toString( targetTrack )
00479 + ") out of range." ) ;
00480
00481 return * new CDTrack( _driveStatus->track[ targetTrack ] ) ;
00482
00483 #else // OSDL_USES_SDL
00484
00485 throw CDROMDriveException( "CDROMDrive::getTrack: "
00486 "no SDL support available" ) ;
00487
00488 #endif // OSDL_USES_SDL
00489
00490 }
00491
00492
00493
00494 void CDROMDrive::playFrames( FrameCount startingFrame,
00495 FrameCount durationInFrames )
00496 {
00497
00498 #if OSDL_USES_SDL
00499
00500 if ( _driveStatus == 0 )
00501 throw CDROMDriveException(
00502 "CDROMDrive::playFrames: drive was not already opened." ) ;
00503
00504 if ( SDL_CDPlay( _driveStatus, startingFrame, durationInFrames) != 0 )
00505 throw CDROMDriveException( "CDROMDrive::playFrames failed: "
00506 + Utils::getBackendLastError() ) ;
00507
00508 #endif // OSDL_USES_SDL
00509
00510 }
00511
00512
00513
00514 void CDROMDrive::playTracks( TrackNumber startingTrack,
00515 TrackNumber numberOfTracks, FrameCount startingFrameOffset,
00516 FrameCount stoppingFrameOffset )
00517 {
00518
00519 #if OSDL_USES_SDL
00520
00521
00522 if ( ! _statusUpdated )
00523 getStatus() ;
00524
00525 if ( SDL_CDPlayTracks( _driveStatus, startingTrack, startingFrameOffset,
00526 numberOfTracks, stoppingFrameOffset ) != 0 )
00527 {
00528 throw CDROMDriveException( "CDROMDrive::playTracks failed: "
00529 + Utils::getBackendLastError() ) ;
00530 }
00531
00532 #endif // OSDL_USES_SDL
00533
00534 }
00535
00536
00537
00538 void CDROMDrive::pause() const
00539 {
00540
00541 #if OSDL_USES_SDL
00542
00543 if ( _driveStatus == 0 )
00544 throw CDROMDriveException(
00545 "CDROMDrive::pause: drive was not already opened." ) ;
00546
00547 if ( SDL_CDPause( _driveStatus ) != 0 )
00548 throw CDROMDriveException( "CDROMDrive::pause failed: "
00549 + Utils::getBackendLastError() ) ;
00550
00551 #endif // OSDL_USES_SDL
00552
00553 }
00554
00555
00556
00557 void CDROMDrive::resume() const
00558 {
00559
00560 #if OSDL_USES_SDL
00561
00562 if ( _driveStatus == 0 )
00563 throw CDROMDriveException(
00564 "CDROMDrive::resume: drive was not already opened." ) ;
00565
00566 if ( SDL_CDResume( _driveStatus ) != 0 )
00567 throw CDROMDriveException( "CDROMDrive::resume failed: "
00568 + Utils::getBackendLastError() ) ;
00569
00570 #endif // OSDL_USES_SDL
00571
00572 }
00573
00574
00575
00576 const string CDROMDrive::toString( Ceylan::VerbosityLevels level ) const
00577 {
00578
00579 #if OSDL_USES_SDL
00580
00581 string res ;
00582
00583 if ( _driveNumber == 0 )
00584 res = "Default CD-ROM drive (#0)" ;
00585 else
00586 res = "CD-ROM drive #" + Ceylan::toString( _driveNumber ) ;
00587
00588 res += ". System-dependent name for this drive is '"
00589 + string( SDL_CDName( _driveNumber ) ) ;
00590
00591 res += "'. It is currently " ;
00592
00593 if ( _driveStatus == 0 )
00594 res += "not " ;
00595 res += "opened for access" ;
00596
00597 if ( level == Ceylan::low )
00598 return res ;
00599
00600
00601 if ( _driveStatus != 0 )
00602 {
00603
00604 res + ". " ;
00605
00606 switch( getConstStatus() )
00607 {
00608
00609 case TrayEmpty:
00610 res += "Tray is empty" ;
00611 break ;
00612
00613 case Stopped:
00614 res += "Drive is stopped" ;
00615 break ;
00616
00617 case Playing:
00618 res += "Drive is playing" ;
00619 break ;
00620
00621 case Paused:
00622 res += "Drive is paused" ;
00623 break ;
00624
00625 case InError:
00626 res += "Drive is in error" ;
00627 break ;
00628
00629 default:
00630 res += "Unknown drive status (abnormal)" ;
00631 break ;
00632
00633 }
00634
00635 TrackNumber count = getTracksCount() ;
00636
00637 res += ". There is/are " + Ceylan::toString( count ) + " track(s): " ;
00638
00639 list<string> tracks ;
00640
00641 for ( TrackNumber i = 0; i < count; i++ )
00642 {
00643
00644 CDTrack currentTrack( _driveStatus->track[ i ] ) ;
00645
00646 tracks.push_back( "Track #" + Ceylan::toString( i ) + ": "
00647 + currentTrack.toString( level ) ) ;
00648
00649 }
00650
00651 res += Ceylan::formatStringList( tracks ) ;
00652 }
00653
00654 return res ;
00655
00656 #else // OSDL_USES_SDL
00657
00658 return "" ;
00659
00660 #endif // OSDL_USES_SDL
00661
00662 }
00663
00664
00665
00666 std::list<std::string> CDROMDrive::GetListOfInsertedMedia()
00667 {
00668
00669 #if OSDL_USES_PHYSICSFS
00670
00671
00672 EmbeddedFileSystemManager::SecureEmbeddedFileSystemManager() ;
00673
00674 char **cds = PHYSFS_getCdRomDirs() ;
00675
00676 std::list<std::string> res ;
00677
00678 for ( char ** i = cds; *i != 0; i++ )
00679 res.push_back( *i ) ;
00680
00681 PHYSFS_freeList(cds) ;
00682
00683 return res ;
00684
00685 #else // OSDL_USES_PHYSICSFS
00686
00687 throw CDROMDriveException( "CDROMDrive::GetListOfInsertedMedia failed: "
00688 "no PhysicsFS support available." ) ;
00689
00690 #endif // OSDL_USES_PHYSICSFS
00691
00692 }
00693
00694
00695
00696 FrameCount CDROMDrive::ConvertTimeToFrameCount(
00697 Ceylan::System::Second duration )
00698 {
00699
00700 return duration * FramesPerSecond ;
00701
00702 }
00703
00704
00705
00706 Ceylan::System::Second CDROMDrive::ConvertFrameCountToTime(
00707 FrameCount duration )
00708 {
00709
00710 return duration / FramesPerSecond ;
00711
00712 }
00713