File indexing completed on 2024-04-28 04:49:50

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 
0008 #include "k3bdevicehandler.h"
0009 #include "k3bprogressinfoevent.h"
0010 #include "k3bthread.h"
0011 #include "k3bdevice.h"
0012 #include "k3bcdtext.h"
0013 #include "k3bcore.h"
0014 #include "k3bmediacache.h"
0015 
0016 
0017 class K3b::Device::DeviceHandler::Private
0018 {
0019 public:
0020     Private( bool _selfDelete )
0021         : selfDelete( _selfDelete ) {
0022     }
0023 
0024     bool selfDelete;
0025 
0026     bool success;
0027     Commands command;
0028     DiskInfo diskInfo;
0029     Toc toc;
0030     CdText cdText;
0031     QByteArray cdTextRaw;
0032     long long bufferCapacity;
0033     long long availableBufferCapacity;
0034     Device* dev;
0035     K3b::Msf nextWritableAddress;
0036 };
0037 
0038 
0039 K3b::Device::DeviceHandler::DeviceHandler( Device* dev, QObject* parent )
0040     : K3b::ThreadJob( 0, parent ),
0041       d( new Private( false ) )
0042 {
0043     d->dev = dev;
0044 }
0045 
0046 
0047 K3b::Device::DeviceHandler::DeviceHandler( QObject* parent )
0048     : K3b::ThreadJob( 0, parent ),
0049       d( new Private( false ) )
0050 {
0051 }
0052 
0053 
0054 K3b::Device::DeviceHandler::DeviceHandler( Commands command, Device* dev )
0055     : K3b::ThreadJob( 0, 0 ),
0056       d( new Private( false ) )
0057 {
0058     d->dev = dev;
0059     sendCommand(command);
0060 }
0061 
0062 K3b::Device::DeviceHandler::~DeviceHandler()
0063 {
0064     delete d;
0065 }
0066 
0067 
0068 bool K3b::Device::DeviceHandler::success() const
0069 {
0070     return d->success;
0071 }
0072 
0073 
0074 K3b::Device::DiskInfo K3b::Device::DeviceHandler::diskInfo() const
0075 {
0076     return d->diskInfo;
0077 }
0078 
0079 
0080 K3b::Device::Toc K3b::Device::DeviceHandler::toc() const
0081 {
0082     return d->toc;
0083 }
0084 
0085 K3b::Device::CdText K3b::Device::DeviceHandler::cdText() const
0086 {
0087     return d->cdText;
0088 }
0089 
0090 
0091 QByteArray K3b::Device::DeviceHandler::cdTextRaw() const
0092 {
0093     return d->cdTextRaw;
0094 }
0095 
0096 
0097 K3b::Msf K3b::Device::DeviceHandler::diskSize() const
0098 {
0099     return d->diskInfo.capacity();
0100 }
0101 
0102 K3b::Msf K3b::Device::DeviceHandler::remainingSize() const
0103 {
0104     return d->diskInfo.remainingSize();
0105 }
0106 
0107 int K3b::Device::DeviceHandler::tocType() const
0108 {
0109     return d->toc.contentType();
0110 }
0111 
0112 int K3b::Device::DeviceHandler::numSessions() const
0113 {
0114     return d->diskInfo.numSessions();
0115 }
0116 
0117 long long K3b::Device::DeviceHandler::bufferCapacity() const
0118 {
0119     return d->bufferCapacity;
0120 }
0121 
0122 long long K3b::Device::DeviceHandler::availableBufferCapacity() const
0123 {
0124     return d->availableBufferCapacity;
0125 }
0126 
0127 K3b::Msf K3b::Device::DeviceHandler::nextWritableAddress() const
0128 {
0129     return d->nextWritableAddress;
0130 }
0131 
0132 void K3b::Device::DeviceHandler::setDevice( Device* dev )
0133 {
0134     d->dev = dev;
0135 }
0136 
0137 
0138 void K3b::Device::DeviceHandler::sendCommand( DeviceHandler::Commands command )
0139 {
0140     if( active() ) {
0141         qDebug() << "thread already running. canceling thread...";
0142         cancel();
0143         wait();
0144     }
0145 
0146     d->command = command;
0147     start();
0148 }
0149 
0150 void K3b::Device::DeviceHandler::getToc()
0151 {
0152     sendCommand(DeviceHandler::CommandToc);
0153 }
0154 
0155 void K3b::Device::DeviceHandler::getDiskInfo()
0156 {
0157     sendCommand(DeviceHandler::CommandDiskInfo);
0158 }
0159 
0160 void K3b::Device::DeviceHandler::getDiskSize()
0161 {
0162     sendCommand(DeviceHandler::CommandDiskSize);
0163 }
0164 
0165 void K3b::Device::DeviceHandler::getRemainingSize()
0166 {
0167     sendCommand(DeviceHandler::CommandRemainingSize);
0168 }
0169 
0170 void K3b::Device::DeviceHandler::getTocType()
0171 {
0172     sendCommand(DeviceHandler::CommandTocType);
0173 }
0174 
0175 void K3b::Device::DeviceHandler::getNumSessions()
0176 {
0177     sendCommand(DeviceHandler::CommandNumSessions);
0178 }
0179 
0180 
0181 void K3b::Device::DeviceHandler::block( bool b )
0182 {
0183     sendCommand(b ? DeviceHandler::CommandBlock : DeviceHandler::CommandUnblock);
0184 }
0185 
0186 void K3b::Device::DeviceHandler::eject()
0187 {
0188     sendCommand(DeviceHandler::CommandEject);
0189 }
0190 
0191 K3b::Device::DeviceHandler* K3b::Device::sendCommand( DeviceHandler::Commands command, Device* dev )
0192 {
0193     return new DeviceHandler( command, dev );
0194 }
0195 
0196 void K3b::Device::DeviceHandler::jobFinished( bool success )
0197 {
0198     K3b::ThreadJob::jobFinished( success );
0199 
0200     emit finished( this );
0201 
0202     if( d->selfDelete ) {
0203         deleteLater();
0204     }
0205 }
0206 
0207 
0208 bool K3b::Device::DeviceHandler::run()
0209 {
0210     qDebug() << "starting command: " << d->command;
0211 
0212     d->success = false;
0213 
0214     // clear data
0215     d->toc.clear();
0216     d->diskInfo = DiskInfo();
0217     d->cdText.clear();
0218     d->cdTextRaw.clear();
0219 
0220     if( d->dev ) {
0221         d->success = d->dev->open();
0222         if( !canceled() && d->command & CommandBlock )
0223             d->success = (d->success && d->dev->block( true ));
0224 
0225         if( !canceled() && d->command & CommandUnblock )
0226             d->success = (d->success && d->dev->block( false ));
0227 
0228         //
0229         // It is important that eject is performed before load
0230         // since the CommandReload command is a combination of both
0231         //
0232 
0233         if( !canceled() && d->command & CommandEject ) {
0234             d->success = (d->success && d->dev->eject());
0235 
0236             // to be on the safe side, especially with respect to the EmptyDiscWaiter
0237             // we reset the device in the cache.
0238             k3bcore->mediaCache()->resetDevice( d->dev );
0239         }
0240 
0241         if( !canceled() && d->command & CommandLoad )
0242             d->success = (d->success && d->dev->load());
0243 
0244         if( !canceled() && d->command & (CommandDiskInfo|
0245                                          CommandDiskSize|
0246                                          CommandRemainingSize|
0247                                          CommandNumSessions) ) {
0248             d->diskInfo = d->dev->diskInfo();
0249         }
0250 
0251         if( !canceled() && d->command & (CommandToc|CommandTocType) ) {
0252             d->toc = d->dev->readToc();
0253         }
0254 
0255         if( !canceled() &&
0256             d->command & CommandCdText &&
0257               !( d->command & CommandToc &&
0258                  d->toc.contentType() == DATA )
0259             ) {
0260             d->cdText = d->dev->readCdText();
0261             if ( d->command != CommandMediaInfo )
0262                 d->success = (d->success && !d->cdText.isEmpty());
0263         }
0264 
0265         if( !canceled() && d->command & CommandCdTextRaw ) {
0266             bool cdTextSuccess = true;
0267             d->cdTextRaw = d->dev->readRawCdText( &cdTextSuccess );
0268             d->success = d->success && cdTextSuccess;
0269         }
0270 
0271         if( !canceled() && d->command & CommandBufferCapacity )
0272             d->success = d->dev->readBufferCapacity( d->bufferCapacity, d->availableBufferCapacity );
0273 
0274         if ( !canceled() && d->command & CommandNextWritableAddress ) {
0275             int nwa = d->dev->nextWritableAddress();
0276             d->nextWritableAddress = nwa;
0277             d->success = ( d->success && ( nwa > 0 ) );
0278         }
0279 
0280         d->dev->close();
0281     }
0282 
0283     qDebug() << "finished command: " << d->command;
0284 
0285     return d->success;
0286 }
0287 
0288 
0289 QDebug operator<<( QDebug dbg, K3b::Device::DeviceHandler::Commands commands )
0290 {
0291     QStringList commandStrings;
0292     if ( commands & K3b::Device::DeviceHandler::CommandDiskInfo )
0293         commandStrings << QLatin1String( "CommandDiskInfo" );
0294     if ( commands & K3b::Device::DeviceHandler::CommandToc )
0295         commandStrings << QLatin1String( "CommandToc" );
0296     if ( commands & K3b::Device::DeviceHandler::CommandCdText )
0297         commandStrings << QLatin1String( "CommandCdText" );
0298     if ( commands & K3b::Device::DeviceHandler::CommandCdTextRaw )
0299         commandStrings << QLatin1String( "CommandCdTextRaw" );
0300     if ( commands & K3b::Device::DeviceHandler::CommandDiskSize )
0301         commandStrings << QLatin1String( "CommandDiskSize" );
0302     if ( commands & K3b::Device::DeviceHandler::CommandRemainingSize )
0303         commandStrings << QLatin1String( "CommandRemainingSize" );
0304     if ( commands & K3b::Device::DeviceHandler::CommandTocType )
0305         commandStrings << QLatin1String( "CommandTocType" );
0306     if ( commands & K3b::Device::DeviceHandler::CommandNumSessions )
0307         commandStrings << QLatin1String( "CommandNumSessions" );
0308     if ( commands & K3b::Device::DeviceHandler::CommandBlock )
0309         commandStrings << QLatin1String( "CommandBlock" );
0310     if ( commands & K3b::Device::DeviceHandler::CommandUnblock )
0311         commandStrings << QLatin1String( "CommandUnblock" );
0312     if ( commands & K3b::Device::DeviceHandler::CommandEject )
0313         commandStrings << QLatin1String( "CommandEject" );
0314     if ( commands & K3b::Device::DeviceHandler::CommandLoad )
0315         commandStrings << QLatin1String( "CommandLoad" );
0316     if ( commands & K3b::Device::DeviceHandler::CommandBufferCapacity )
0317         commandStrings << QLatin1String( "CommandBufferCapacity" );
0318     if ( commands & K3b::Device::DeviceHandler::CommandNextWritableAddress )
0319         commandStrings << QLatin1String( "CommandNextWritableAddress" );
0320     dbg.nospace() << '(' + commandStrings.join( "|" ) + ')';
0321     return dbg.space();
0322 }
0323 
0324 #include "moc_k3bdevicehandler.cpp"