File indexing completed on 2024-05-05 04:50:56

0001 /*
0002     SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3bdvdbooktypejob.h"
0007 
0008 #include "k3bglobals.h"
0009 #include "k3bprocess.h"
0010 #include "k3bdevice.h"
0011 #include "k3bdeviceglobals.h"
0012 #include "k3bdevicehandler.h"
0013 #include "k3bdiskinfo.h"
0014 #include "k3bexternalbinmanager.h"
0015 #include "k3bcore.h"
0016 #include "k3bversion.h"
0017 #include "k3bglobalsettings.h"
0018 #include "k3b_i18n.h"
0019 
0020 #include <QDebug>
0021 #include <QRegExp>
0022 
0023 #include <errno.h>
0024 #include <string.h>
0025 
0026 
0027 class K3b::DvdBooktypeJob::Private
0028 {
0029 public:
0030     Private()
0031         : device(0),
0032           process(0),
0033           dvdBooktypeBin(0),
0034           running(false),
0035           forceNoEject(false) {
0036     }
0037 
0038     K3b::Device::Device* device;
0039     K3b::Process* process;
0040     const K3b::ExternalBin* dvdBooktypeBin;
0041 
0042     bool success;
0043     bool canceled;
0044     bool running;
0045 
0046     bool forceNoEject;
0047 
0048     int foundMediaType;
0049 };
0050 
0051 
0052 K3b::DvdBooktypeJob::DvdBooktypeJob( K3b::JobHandler* jh, QObject* parent )
0053     : K3b::Job( jh, parent ),
0054       m_action(0)
0055 {
0056     d = new Private;
0057 }
0058 
0059 
0060 K3b::DvdBooktypeJob::~DvdBooktypeJob()
0061 {
0062     delete d->process;
0063     delete d;
0064 }
0065 
0066 
0067 void K3b::DvdBooktypeJob::setForceNoEject( bool b )
0068 {
0069     d->forceNoEject = b;
0070 }
0071 
0072 
0073 QString K3b::DvdBooktypeJob::jobDescription() const
0074 {
0075     return i18n("Changing DVD Booktype"); // Changing DVD±R(W) Booktype
0076 }
0077 
0078 
0079 QString K3b::DvdBooktypeJob::jobDetails() const
0080 {
0081     return QString();
0082 }
0083 
0084 
0085 void K3b::DvdBooktypeJob::start()
0086 {
0087     d->canceled = false;
0088     d->running = true;
0089 
0090     jobStarted();
0091 
0092     if( !d->device ) {
0093         emit infoMessage( i18n("No device set"), MessageError );
0094         jobFinished(false);
0095         d->running = false;
0096         return;
0097     }
0098 
0099     //
0100     // In case we want to change the writers default we do not need to wait for a media
0101     //
0102     if( m_action == SET_MEDIA_DVD_ROM ||
0103         m_action == SET_MEDIA_DVD_R_W ) {
0104         emit newSubTask( i18n("Waiting for media") );
0105         if( waitForMedium( d->device,
0106                            K3b::Device::STATE_COMPLETE|K3b::Device::STATE_INCOMPLETE|K3b::Device::STATE_EMPTY,
0107                            K3b::Device::MEDIA_DVD_PLUS_RW|K3b::Device::MEDIA_DVD_PLUS_R,
0108                            0,
0109                            i18n("Please insert an empty DVD+R or a DVD+RW medium into drive<p><b>%1 %2 (%3)</b>.",
0110                                 d->device->vendor(),
0111                                 d->device->description(),
0112                                 d->device->blockDeviceName()) ) == Device::MEDIA_UNKNOWN ) {
0113             emit canceled();
0114             jobFinished(false);
0115             d->running = false;
0116             return;
0117         }
0118 
0119         emit infoMessage( i18n("Checking medium"), MessageInfo );
0120         emit newTask( i18n("Checking medium") );
0121 
0122         connect( K3b::Device::sendCommand( K3b::Device::DeviceHandler::CommandDiskInfo, d->device ),
0123                  SIGNAL(finished(K3b::Device::DeviceHandler*)),
0124                  this,
0125                  SLOT(slotDeviceHandlerFinished(K3b::Device::DeviceHandler*)) );
0126     }
0127     else {
0128         // change writer defaults
0129         startBooktypeChange();
0130     }
0131 }
0132 
0133 
0134 void K3b::DvdBooktypeJob::start( K3b::Device::DeviceHandler* dh )
0135 {
0136     d->canceled = false;
0137     d->running = true;
0138 
0139     jobStarted();
0140 
0141     slotDeviceHandlerFinished( dh );
0142 }
0143 
0144 
0145 void K3b::DvdBooktypeJob::cancel()
0146 {
0147     if( d->running ) {
0148         d->canceled = true;
0149         if( d->process )
0150             d->process->terminate();
0151     }
0152     else {
0153         qDebug() << "(K3b::DvdBooktypeJob) not running.";
0154     }
0155 }
0156 
0157 
0158 void K3b::DvdBooktypeJob::setDevice( K3b::Device::Device* dev )
0159 {
0160     d->device = dev;
0161 }
0162 
0163 
0164 void K3b::DvdBooktypeJob::slotStderrLine( const QString& line )
0165 {
0166     emit debuggingOutput( "dvd+rw-booktype", line );
0167     // FIXME
0168 }
0169 
0170 
0171 void K3b::DvdBooktypeJob::slotProcessFinished( int exitCode, QProcess::ExitStatus exitStatus )
0172 {
0173     if( d->canceled ) {
0174         emit canceled();
0175         d->success = false;
0176     }
0177     else if( exitStatus == QProcess::NormalExit ) {
0178         if( exitCode == 0 ) {
0179             emit infoMessage( i18n("Booktype successfully changed"), K3b::Job::MessageSuccess );
0180             d->success = true;
0181         }
0182         else {
0183             emit infoMessage( i18n("%1 returned an unknown error (code %2).",d->dvdBooktypeBin->name(), exitCode),
0184                               K3b::Job::MessageError );
0185             emit infoMessage( i18n("Please send me an email with the last output."), K3b::Job::MessageError );
0186 
0187             d->success = false;
0188         }
0189     }
0190     else {
0191         emit infoMessage( i18n("%1 did not exit cleanly.",d->dvdBooktypeBin->name()),
0192                           MessageError );
0193         d->success = false;
0194     }
0195 
0196     //
0197     // No need to eject the media if we changed the writer's default
0198     //
0199     if( m_action == SET_MEDIA_DVD_ROM ||
0200         m_action == SET_MEDIA_DVD_R_W ) {
0201 
0202         if( d->forceNoEject ||
0203             !k3bcore->globalSettings()->ejectMedia() ) {
0204             d->running = false;
0205             jobFinished(d->success);
0206         }
0207         else {
0208             emit infoMessage( i18n("Ejecting DVD..."), MessageInfo );
0209             connect( K3b::Device::eject( d->device ),
0210                      SIGNAL(finished(K3b::Device::DeviceHandler*)),
0211                      this,
0212                      SLOT(slotEjectingFinished(K3b::Device::DeviceHandler*)) );
0213         }
0214     }
0215     else {
0216         d->running = false;
0217         jobFinished(d->success);
0218     }
0219 }
0220 
0221 
0222 void K3b::DvdBooktypeJob::slotEjectingFinished( K3b::Device::DeviceHandler* dh )
0223 {
0224     if( !dh->success() )
0225         emit infoMessage( i18n("Unable to eject media."), MessageError );
0226 
0227     d->running = false;
0228     jobFinished(d->success);
0229 }
0230 
0231 
0232 void K3b::DvdBooktypeJob::slotDeviceHandlerFinished( K3b::Device::DeviceHandler* dh )
0233 {
0234     if( d->canceled ) {
0235         emit canceled();
0236         d->running = false;
0237         jobFinished(false);
0238     }
0239 
0240     if( dh->success() ) {
0241 
0242         d->foundMediaType = dh->diskInfo().mediaType();
0243         if( d->foundMediaType == K3b::Device::MEDIA_DVD_PLUS_R ) {
0244             // the media needs to be empty
0245             if( dh->diskInfo().empty() )
0246                 startBooktypeChange();
0247             else {
0248                 emit infoMessage( i18n("Cannot change booktype on non-empty DVD+R media."), MessageError );
0249                 jobFinished(false);
0250             }
0251         }
0252         else if( d->foundMediaType == K3b::Device::MEDIA_DVD_PLUS_RW ) {
0253             startBooktypeChange();
0254         }
0255         else {
0256             emit infoMessage( i18n("No DVD+R(W) media found."), MessageError );
0257             jobFinished(false);
0258         }
0259     }
0260     else {
0261         emit infoMessage( i18n("Unable to determine media state."), MessageError );
0262         d->running = false;
0263         jobFinished(false);
0264     }
0265 }
0266 
0267 
0268 void K3b::DvdBooktypeJob::startBooktypeChange()
0269 {
0270     delete d->process;
0271     d->process = new K3b::Process();
0272     d->process->setSuppressEmptyLines(true);
0273     connect( d->process, SIGNAL(stderrLine(QString)), this, SLOT(slotStderrLine(QString)) );
0274     connect( d->process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)) );
0275 
0276     d->dvdBooktypeBin = k3bcore->externalBinManager()->binObject( "dvd+rw-booktype" );
0277     if( !d->dvdBooktypeBin ) {
0278         emit infoMessage( i18n("Could not find %1 executable.",QString("dvd+rw-booktype")), MessageError );
0279         d->running = false;
0280         jobFinished(false);
0281         return;
0282     }
0283 
0284     *d->process << d->dvdBooktypeBin;
0285 
0286     switch( m_action ) {
0287     case SET_MEDIA_DVD_ROM:
0288         *d->process << "-dvd-rom-spec"
0289                     << "-media";
0290         break;
0291     case SET_MEDIA_DVD_R_W:
0292         if( d->foundMediaType == K3b::Device::MEDIA_DVD_PLUS_RW )
0293             *d->process << "-dvd+rw-spec";
0294         else
0295             *d->process << "-dvd+r-spec";
0296         *d->process << "-media";
0297         break;
0298     case SET_UNIT_DVD_ROM_ON_NEW_DVD_R:
0299         *d->process << "-dvd-rom-spec"
0300                     << "-unit+r";
0301         break;
0302     case SET_UNIT_DVD_ROM_ON_NEW_DVD_RW:
0303         *d->process << "-dvd-rom-spec"
0304                     << "-unit+rw";
0305         break;
0306     case SET_UNIT_DVD_R_ON_NEW_DVD_R:
0307         *d->process << "-dvd+r-spec"
0308                     << "-unit+r";
0309         break;
0310     case SET_UNIT_DVD_RW_ON_NEW_DVD_RW:
0311         *d->process << "-dvd+rw-spec"
0312                     << "-unit+rw";
0313         break;
0314     }
0315 
0316     *d->process << d->device->blockDeviceName();
0317 
0318     qDebug() << "***** dvd+rw-booktype parameters:\n";
0319     QString s = d->process->joinedArgs();
0320     qDebug() << s << Qt::endl << Qt::flush;
0321     emit debuggingOutput( "dvd+rw-booktype command:", s );
0322 
0323     if( !d->process->start( KProcess::OnlyStderrChannel ) ) {
0324         // something went wrong when starting the program
0325         // it "should" be the executable
0326         emit infoMessage( i18n("Could not start %1.",d->dvdBooktypeBin->name()), K3b::Job::MessageError );
0327         d->running = false;
0328         jobFinished(false);
0329     }
0330     else {
0331         emit newTask( i18n("Changing Booktype") );
0332     }
0333 }
0334 
0335 #include "moc_k3bdvdbooktypejob.cpp"