00001 #include "OSDLCDROMDrive.h"
00002
00003
00004 #include "OSDLUtils.h"
00005
00006 #include "SDL.h"
00007
00008 #include <list>
00009
00010 using std::list ;
00011 using std::string ;
00012
00013
00014 using namespace OSDL ;
00015
00016
00017
00018
00019 CDTrack::CDTrack( const SDL_CDtrack & track ) throw() :
00020 _trackData( & track )
00021 {
00022
00023 }
00024
00025
00026 CDTrack::~CDTrack() throw()
00027 {
00028
00029
00030
00031 }
00032
00033
00034 TrackNumber CDTrack::getTrackNumber() const throw()
00035 {
00036
00037 return _trackData->id ;
00038
00039 }
00040
00041
00042 TrackType CDTrack::getTrackType() const throw()
00043 {
00044
00045 switch( _trackData->type )
00046 {
00047
00048 case SDL_AUDIO_TRACK:
00049 return audioTrack ;
00050 break ;
00051
00052 case SDL_DATA_TRACK:
00053 return dataTrack ;
00054 break ;
00055
00056 default:
00057 Ceylan::emergencyShutdown(
00058 "CDTrack::getTrackType : unexpected type (abnormal)." ) ;
00059
00060 return dataTrack ;
00061 break ;
00062
00063 }
00064
00065 }
00066
00067
00068 FrameCount CDTrack::getLength() const throw()
00069 {
00070
00071 return _trackData->length ;
00072
00073 }
00074
00075
00076 FrameCount CDTrack::getFrameOffset() const throw()
00077 {
00078
00079 return _trackData->offset ;
00080
00081 }
00082
00083
00084 const string CDTrack::toString( Ceylan::VerbosityLevels level ) const throw()
00085 {
00086
00087 string res = "Track #" + Ceylan::toString( getTrackNumber() )
00088 + " : this is " ;
00089
00090 switch( getTrackType() )
00091 {
00092
00093 case audioTrack:
00094 res += "an audio track, its length is "
00095 + Ceylan::toString( getLength() )
00096 + " frames (about "
00097 + Ceylan::toString(
00098 CDROMDrive::ConvertFrameCountToTime( getLength() ) )
00099 + " seconds)" ;
00100 break ;
00101
00102 case dataTrack:
00103 res += "a data track, its length is "
00104 + Ceylan::toString( getLength() )
00105 + " frames" ;
00106 break ;
00107
00108 default:
00109 res += "unexpected track type" ;
00110 break ;
00111
00112 }
00113
00114 res += ". Current frame offset is " + Ceylan::toString( getFrameOffset() ) ;
00115
00116 return res ;
00117
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 const FrameCount CDROMDrive::FramesPerSecond = CD_FPS ;
00128
00129
00130 CDROMDrive::CDROMDrive( CDROMDriveNumber driveNumber )
00131 throw( CDROMDriveException ) :
00132 Object(),
00133 _driveNumber( driveNumber ),
00134 _statusUpdated( false ),
00135 _driveStatus( 0 )
00136 {
00137
00138 }
00139
00140
00141 CDROMDrive::~CDROMDrive() throw()
00142 {
00143
00144 if ( _driveStatus != 0 )
00145 close() ;
00146
00147 }
00148
00149
00150 void CDROMDrive::open() throw( CDROMDriveException )
00151 {
00152
00153 if ( _driveStatus != 0 )
00154 throw CDROMDriveException(
00155 "CDROMDrive::open : drive already opened." ) ;
00156
00157 _driveStatus = SDL_CDOpen( _driveNumber ) ;
00158
00159 if ( _driveStatus == 0 )
00160 throw CDROMDriveException( "CDROMDrive::open : open failed : "
00161 + Utils::getBackendLastError() ) ;
00162
00163 }
00164
00165
00166 void CDROMDrive::close() throw( CDROMDriveException )
00167 {
00168
00169 if ( _driveStatus == 0 )
00170 throw CDROMDriveException(
00171 "CDROMDrive::close : drive was not already opened." ) ;
00172
00173 SDL_CDClose( _driveStatus ) ;
00174
00175
00176 _driveStatus = 0 ;
00177
00178 }
00179
00180
00181 void CDROMDrive::eject() const throw( CDROMDriveException )
00182 {
00183
00184 if ( _driveStatus == 0 )
00185 throw CDROMDriveException(
00186 "CDROMDrive::eject : drive was not already opened." ) ;
00187
00188 if ( SDL_CDEject( _driveStatus ) != 0 )
00189 throw CDROMDriveException(
00190 "CDROMDrive::eject : " + Utils::getBackendLastError() ) ;
00191
00192 }
00193
00194
00195 CDROMDrive::Status CDROMDrive::getStatus() throw( CDROMDriveException )
00196 {
00197
00198 Status status = getConstStatus() ;
00199
00200 _statusUpdated = true ;
00201
00202 return status ;
00203
00204 }
00205
00206
00207 CDROMDrive::Status CDROMDrive::getConstStatus() const
00208 throw( CDROMDriveException )
00209 {
00210
00211 if ( _driveStatus == 0 )
00212 throw CDROMDriveException(
00213 "CDROMDrive::getConstStatus : drive was not already opened." ) ;
00214
00215
00216 switch( SDL_CDStatus( _driveStatus ) )
00217 {
00218
00219 case CD_TRAYEMPTY:
00220 return TrayEmpty ;
00221 break ;
00222
00223 case CD_STOPPED:
00224 return Stopped ;
00225 break ;
00226
00227 case CD_PLAYING:
00228 return Playing ;
00229 break ;
00230
00231 case CD_PAUSED:
00232 return Paused ;
00233 break ;
00234
00235 case CD_ERROR:
00236 return InError ;
00237 break ;
00238
00239 default:
00240 Ceylan::emergencyShutdown(
00241 "CDROMDrive::getConstStatus : unknown status read" ) ;
00242
00243 return InError ;
00244 break ;
00245
00246 }
00247
00248 }
00249
00250
00251
00252 bool CDROMDrive::isCDInDrive() throw( CDROMDriveException )
00253 {
00254
00255 CDROMDrive::Status status = getStatus() ;
00256
00257 return ( ( status != TrayEmpty) && ( status != InError ) ) ;
00258
00259 }
00260
00261 TrackNumber CDROMDrive::getTracksCount() const throw( CDROMDriveException )
00262 {
00263
00264 if ( _driveStatus == 0 )
00265 throw CDROMDriveException(
00266 "CDROMDrive::getTracksCount : drive was not already opened." ) ;
00267
00268 return _driveStatus->numtracks ;
00269
00270 }
00271
00272
00273 FrameCount CDROMDrive::getTrackDuration( TrackNumber targetTrack )
00274 const throw( CDROMDriveException )
00275 {
00276
00277
00278 if ( targetTrack >= getTracksCount() )
00279 throw CDROMDriveException( "CDROMDrive::getTrackDuration : "
00280 "specified track ("
00281 + Ceylan::toString( targetTrack ) + ") out of range." ) ;
00282
00283 return _driveStatus->track[targetTrack].length ;
00284
00285 }
00286
00287
00288 CDTrack & CDROMDrive::getTrack( TrackNumber targetTrack ) const
00289 throw( CDROMDriveException )
00290 {
00291
00292
00293 if ( targetTrack >= getTracksCount() )
00294 throw CDROMDriveException( "CDROMDrive::getTrack : "
00295 "specified track (" + Ceylan::toString( targetTrack )
00296 + ") out of range." ) ;
00297
00298 return * new CDTrack( _driveStatus->track[ targetTrack ] ) ;
00299
00300 }
00301
00302
00303 void CDROMDrive::playFrames( FrameCount startingFrame,
00304 FrameCount durationInFrames ) throw( CDROMDriveException )
00305 {
00306
00307 if ( _driveStatus == 0 )
00308 throw CDROMDriveException(
00309 "CDROMDrive::playFrames : drive was not already opened." ) ;
00310
00311 if ( SDL_CDPlay( _driveStatus, startingFrame, durationInFrames) != 0 )
00312 throw CDROMDriveException( "CDROMDrive::playFrames failed : "
00313 + Utils::getBackendLastError() ) ;
00314
00315 }
00316
00317
00318 void CDROMDrive::playTracks( TrackNumber startingTrack,
00319 TrackNumber numberOfTracks, FrameCount startingFrameOffset,
00320 FrameCount stoppingFrameOffset ) throw( CDROMDriveException )
00321 {
00322
00323
00324 if ( ! _statusUpdated )
00325 getStatus() ;
00326
00327 if ( SDL_CDPlayTracks( _driveStatus, startingTrack, startingFrameOffset,
00328 numberOfTracks, stoppingFrameOffset ) != 0 )
00329 {
00330 throw CDROMDriveException( "CDROMDrive::playTracks failed : "
00331 + Utils::getBackendLastError() ) ;
00332 }
00333
00334 }
00335
00336
00337 void CDROMDrive::pause() const throw( CDROMDriveException )
00338 {
00339
00340 if ( _driveStatus == 0 )
00341 throw CDROMDriveException(
00342 "CDROMDrive::pause : drive was not already opened." ) ;
00343
00344 if ( SDL_CDPause( _driveStatus ) != 0 )
00345 throw CDROMDriveException( "CDROMDrive::pause failed : "
00346 + Utils::getBackendLastError() ) ;
00347
00348 }
00349
00350
00351 void CDROMDrive::resume() const throw( CDROMDriveException )
00352 {
00353
00354 if ( _driveStatus == 0 )
00355 throw CDROMDriveException(
00356 "CDROMDrive::resume : drive was not already opened." ) ;
00357
00358 if ( SDL_CDResume( _driveStatus ) != 0 )
00359 throw CDROMDriveException( "CDROMDrive::resume failed : "
00360 + Utils::getBackendLastError() ) ;
00361
00362 }
00363
00364
00365 const string CDROMDrive::toString( Ceylan::VerbosityLevels level ) const throw()
00366 {
00367
00368 string res ;
00369
00370 if ( _driveNumber == 0 )
00371 res = "Default CD-ROM drive (#0)" ;
00372 else
00373 res = "CD-ROM drive #" + Ceylan::toString( _driveNumber ) ;
00374
00375 res += ". System-dependent name for this drive is '"
00376 + string( SDL_CDName( _driveNumber ) ) ;
00377
00378 res += "'. It is currently " ;
00379
00380 if ( _driveStatus == 0 )
00381 res += "not " ;
00382 res += "opened for access" ;
00383
00384 if ( level == Ceylan::low )
00385 return res ;
00386
00387
00388 if ( _driveStatus != 0 )
00389 {
00390
00391 res + ". " ;
00392
00393 switch( getConstStatus() )
00394 {
00395
00396 case TrayEmpty:
00397 res += "Tray is empty" ;
00398 break ;
00399
00400 case Stopped:
00401 res += "Drive is stopped" ;
00402 break ;
00403
00404 case Playing:
00405 res += "Drive is playing" ;
00406 break ;
00407
00408 case Paused:
00409 res += "Drive is paused" ;
00410 break ;
00411
00412 case InError:
00413 res += "Drive is in error" ;
00414 break ;
00415
00416 default:
00417 res += "Unknown drive status (abnormal)" ;
00418 break ;
00419
00420 }
00421
00422 TrackNumber count = getTracksCount() ;
00423
00424 res += ". There is/are " + Ceylan::toString( count ) + " track(s) : " ;
00425
00426 list<string> tracks ;
00427
00428 for ( TrackNumber i = 0; i < count; i++ )
00429 {
00430
00431 CDTrack currentTrack( _driveStatus->track[ i ] ) ;
00432
00433 tracks.push_back( "Track #" + Ceylan::toString( i ) + " : "
00434 + currentTrack.toString( level ) ) ;
00435
00436 }
00437
00438 res += Ceylan::formatStringList( tracks ) ;
00439 }
00440
00441 return res ;
00442
00443 }
00444
00445
00446
00447 FrameCount CDROMDrive::ConvertTimeToFrameCount(
00448 Ceylan::System::Second duration ) throw()
00449 {
00450
00451 return duration * FramesPerSecond ;
00452
00453 }
00454
00455
00456 Ceylan::System::Second CDROMDrive::ConvertFrameCountToTime(
00457 FrameCount duration ) throw()
00458 {
00459
00460 return duration / FramesPerSecond ;
00461
00462 }
00463