3
* Copyright (C) 2003-2010 Sebastian Trueg <trueg@k3b.org>
5
* This file is part of the K3b project.
6
* Copyright (C) 1998-2010 Sebastian Trueg <trueg@k3b.org>
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
* See the file "COPYING" for the exact licensing terms.
15
#include "k3bdvdcopyjob.h"
16
#include "k3blibdvdcss.h"
18
#include "k3breadcdreader.h"
19
#include "k3bdatatrackreader.h"
20
#include "k3bexternalbinmanager.h"
21
#include "k3bdevice.h"
22
#include "k3bdeviceglobals.h"
23
#include "k3bdevicehandler.h"
24
#include "k3bdiskinfo.h"
25
#include "k3bglobals.h"
27
#include "k3bgrowisofswriter.h"
28
#include "k3bcdrecordwriter.h"
29
#include "k3bversion.h"
30
#include "k3biso9660.h"
31
#include "k3bfilesplitter.h"
32
#include "k3bchecksumpipe.h"
33
#include "k3bverificationjob.h"
34
#include "k3bglobalsettings.h"
38
#include <kio/global.h>
41
#include <qfileinfo.h>
42
#include <qapplication.h>
45
class K3b::DvdCopyJob::Private
56
usedWritingMode(K3b::WritingModeAuto),
58
outPipe.readFrom( &imageFile, true );
61
K3b::WritingApp usedWritingApp;
70
K3b::AbstractWriter* writerJob;
71
K3b::ReadcdReader* readcdReader;
72
K3b::DataTrackReader* dataTrackReader;
73
K3b::VerificationJob* verificationJob;
75
K3b::Device::DiskInfo sourceDiskInfo;
79
K3b::WritingMode usedWritingMode;
81
K3b::FileSplitter imageFile;
82
K3b::ChecksumPipe inPipe;
83
K3b::ActivePipe outPipe;
89
K3b::DvdCopyJob::DvdCopyJob( K3b::JobHandler* hdl, QObject* parent )
90
: K3b::BurnJob( hdl, parent ),
94
m_removeImageFiles(false),
98
m_onlyCreateImage(false),
99
m_ignoreReadErrors(false),
101
m_writingMode( K3b::WritingModeAuto )
107
K3b::DvdCopyJob::~DvdCopyJob()
113
void K3b::DvdCopyJob::start()
120
d->readerRunning = d->writerRunning = false;
122
emit newTask( i18n("Checking Source Medium") );
125
k3bcore->externalBinManager()->binObject( "growisofs" )->version < K3b::Version( 5, 12 ) ) {
127
emit infoMessage( i18n("K3b does not support writing on-the-fly with growisofs %1.",
128
k3bcore->externalBinManager()->binObject( "growisofs" )->version), MessageError );
129
emit infoMessage( i18n("Disabling on-the-fly writing."), MessageInfo );
132
emit newSubTask( i18n("Waiting for source medium") );
134
// wait for a source disk
135
if( waitForMedium( m_readerDevice,
136
K3b::Device::STATE_COMPLETE|K3b::Device::STATE_INCOMPLETE,
137
K3b::Device::MEDIA_WRITABLE_DVD|K3b::Device::MEDIA_DVD_ROM|K3b::Device::MEDIA_BD_ALL ) == Device::MEDIA_UNKNOWN ) {
140
jobFinished( false );
144
emit newSubTask( i18n("Checking source medium") );
146
connect( K3b::Device::sendCommand( K3b::Device::DeviceHandler::CommandMediaInfo, m_readerDevice ),
147
SIGNAL(finished(K3b::Device::DeviceHandler*)),
149
SLOT(slotDiskInfoReady(K3b::Device::DeviceHandler*)) );
153
void K3b::DvdCopyJob::slotDiskInfoReady( K3b::Device::DeviceHandler* dh )
161
d->sourceDiskInfo = dh->diskInfo();
163
if( dh->diskInfo().empty() || dh->diskInfo().diskState() == K3b::Device::STATE_NO_MEDIA ) {
164
emit infoMessage( i18n("No source medium found."), MessageError );
169
// first let's determine which application to use
170
d->usedWritingApp = writingApp();
171
if ( d->usedWritingApp == K3b::WritingAppAuto ) {
172
// let's default to cdrecord for the time being
173
// FIXME: use growisofs for non-dao and non-auto mode
174
if ( K3b::Device::isBdMedia( d->sourceDiskInfo.mediaType() ) ) {
175
if ( k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "blu-ray" ) )
176
d->usedWritingApp = K3b::WritingAppCdrecord;
178
d->usedWritingApp = K3b::WritingAppGrowisofs;
182
if( m_readerDevice->copyrightProtectionSystemType() == K3b::Device::COPYRIGHT_PROTECTION_CSS ) { // CSS is the the only one we support ATM
183
emit infoMessage( i18n("Found encrypted DVD."), MessageWarning );
184
// check for libdvdcss
185
bool haveLibdvdcss = false;
186
kDebug() << "(K3b::DvdCopyJob) trying to open libdvdcss.";
187
if( K3b::LibDvdCss* libcss = K3b::LibDvdCss::create() ) {
188
kDebug() << "(K3b::DvdCopyJob) succeeded.";
189
kDebug() << "(K3b::DvdCopyJob) dvdcss_open(" << m_readerDevice->blockDeviceName() << ") = "
190
<< libcss->open(m_readerDevice) << endl;
191
haveLibdvdcss = true;
196
kDebug() << "(K3b::DvdCopyJob) failed.";
198
if( !haveLibdvdcss ) {
199
emit infoMessage( i18n("Cannot copy encrypted DVDs."), MessageError );
201
jobFinished( false );
208
// We cannot rely on the kernel to determine the size of the DVD for some reason
209
// On the other hand it is not always a good idea to rely on the size from the ISO9660
210
// header since that may be wrong due to some buggy encoder or some boot code appended
211
// after creating the image.
212
// That is why we try our best to determine the size of the DVD. For DVD-ROM this is very
213
// easy since it has only one track. The same goes for single session DVD-R(W) and DVD+R.
214
// Multisession DVDs we will simply not copy. ;)
215
// For DVD+RW and DVD-RW in restricted overwrite mode we are left with no other choice but
216
// to use the ISO9660 header.
218
// On the other hand: in on-the-fly mode growisofs determines the size of the data to be written
219
// by looking at the ISO9660 header when writing in DAO mode. So in this case
220
// it would be best for us to do the same....
222
// With growisofs 5.15 we have the option to specify the size of the image to be written in DAO mode.
225
switch( dh->diskInfo().mediaType() ) {
226
case K3b::Device::MEDIA_DVD_ROM:
227
case K3b::Device::MEDIA_DVD_PLUS_R_DL:
228
case K3b::Device::MEDIA_DVD_R_DL:
229
case K3b::Device::MEDIA_DVD_R_DL_SEQ:
230
case K3b::Device::MEDIA_DVD_R_DL_JUMP:
231
if( !m_onlyCreateImage ) {
232
if( dh->diskInfo().numLayers() > 1 &&
233
dh->diskInfo().size() > MediaSizeDvd4Gb ) {
234
if( !(m_writerDevice->type() & (K3b::Device::DEVICE_DVD_R_DL|K3b::Device::DEVICE_DVD_PLUS_R_DL)) ) {
235
emit infoMessage( i18n("The writer does not support writing Double Layer DVDs."), MessageError );
240
else if( k3bcore->externalBinManager()->binObject( "growisofs" ) &&
241
!k3bcore->externalBinManager()->binObject( "growisofs" )->hasFeature( "dual-layer" ) ) {
242
emit infoMessage( i18n("This growisofs version does not support writing Double Layer DVDs."), MessageError );
249
case K3b::Device::MEDIA_DVD_R:
250
case K3b::Device::MEDIA_DVD_R_SEQ:
251
case K3b::Device::MEDIA_DVD_RW:
252
case K3b::Device::MEDIA_DVD_RW_SEQ:
253
case K3b::Device::MEDIA_DVD_PLUS_R:
254
case K3b::Device::MEDIA_BD_ROM:
255
case K3b::Device::MEDIA_BD_R:
256
case K3b::Device::MEDIA_BD_R_SRM:
258
if( dh->diskInfo().numSessions() > 1 ) {
259
emit infoMessage( i18n("K3b does not support copying multi-session DVD or Blu-ray disks."), MessageError );
265
// growisofs only uses the size from the PVD for reserving
266
// writable space in DAO mode
267
// with version >= 5.15 growisofs supports specifying the size of the track
268
if( m_writingMode != K3b::WritingModeSao || !m_onTheFly || m_onlyCreateImage ||
269
( k3bcore->externalBinManager()->binObject( "growisofs" ) &&
270
k3bcore->externalBinManager()->binObject( "growisofs" )->hasFeature( "daosize" ) ) ||
271
d->usedWritingApp == K3b::WritingAppCdrecord ) {
272
d->lastSector = dh->toc().lastSector();
278
case K3b::Device::MEDIA_DVD_PLUS_RW:
279
case K3b::Device::MEDIA_DVD_RW_OVWR:
280
case K3b::Device::MEDIA_BD_RE:
282
emit infoMessage( i18n("K3b relies on the size saved in the ISO9660 header."), MessageWarning );
283
emit infoMessage( i18n("This might result in a corrupt copy if the source was mastered with buggy software."), MessageWarning );
285
K3b::Iso9660 isoF( m_readerDevice, 0 );
287
d->lastSector = ((long long)isoF.primaryDescriptor().logicalBlockSize*isoF.primaryDescriptor().volumeSpaceSize)/2048LL - 1;
290
emit infoMessage( i18n("Unable to determine the ISO9660 filesystem size."), MessageError );
298
case K3b::Device::MEDIA_DVD_RAM:
299
emit infoMessage( i18n("K3b does not support copying DVD-RAM."), MessageError );
305
emit infoMessage( i18n("Unsupported media type."), MessageError );
314
// Check the image path
316
QFileInfo fi( m_imagePath );
318
questionYesNo( i18n("Do you want to overwrite %1?",m_imagePath),
319
i18n("File Exists") ) ) {
321
m_imagePath = K3b::findTempFile( "iso", m_imagePath );
322
else if( !QFileInfo( m_imagePath.section( '/', 0, -2 ) ).isDir() ) {
323
emit infoMessage( i18n("Specified an unusable temporary path. Using default."), MessageWarning );
324
m_imagePath = K3b::findTempFile( "iso" );
326
// else the user specified a file in an existing dir
328
emit infoMessage( i18n("Writing image file to %1.",m_imagePath), MessageInfo );
329
emit newSubTask( i18n("Reading source medium.") );
338
// check free temp space
340
KIO::filesize_t imageSpaceNeeded = (KIO::filesize_t)(d->lastSector.lba()+1)*2048;
341
unsigned long avail, size;
342
QString pathToTest = m_imagePath.left( m_imagePath.lastIndexOf( '/' ) );
343
if( !K3b::kbFreeOnFs( pathToTest, size, avail ) ) {
344
emit infoMessage( i18n("Unable to determine free space in temporary folder '%1'.",pathToTest), MessageError );
350
if( avail < imageSpaceNeeded/1024 ) {
351
emit infoMessage( i18n("Not enough space left in temporary folder."), MessageError );
358
d->imageFile.setName( m_imagePath );
359
if( !d->imageFile.open( QIODevice::WriteOnly ) ) {
360
emit infoMessage( i18n("Unable to open '%1' for writing.",m_imagePath), MessageError );
361
jobFinished( false );
367
if( K3b::isMounted( m_readerDevice ) ) {
368
emit infoMessage( i18n("Unmounting source medium"), MessageInfo );
369
K3b::unmount( m_readerDevice );
372
if( m_onlyCreateImage || !m_onTheFly ) {
373
emit newTask( i18n("Creating image") );
375
else if( m_onTheFly && !m_onlyCreateImage ) {
379
emit newTask( i18n("Simulating copy") );
380
else if( m_copies > 1 )
381
emit newTask( i18n("Writing copy %1",d->doneCopies+1) );
383
emit newTask( i18n("Writing copy") );
386
d->writerRunning = true;
387
d->writerJob->start();
399
d->readerRunning = true;
400
d->dataTrackReader->start();
405
void K3b::DvdCopyJob::cancel()
409
if( d->readerRunning )
410
d->dataTrackReader->cancel();
411
if( d->writerRunning )
412
d->writerJob->cancel();
413
if ( d->verificationJob && d->verificationJob->active() )
414
d->verificationJob->cancel();
417
d->imageFile.close();
420
kDebug() << "(K3b::DvdCopyJob) not running.";
425
void K3b::DvdCopyJob::prepareReader()
427
if( !d->dataTrackReader ) {
428
d->dataTrackReader = new K3b::DataTrackReader( this );
429
connect( d->dataTrackReader, SIGNAL(percent(int)), this, SLOT(slotReaderProgress(int)) );
430
connect( d->dataTrackReader, SIGNAL(processedSize(int, int)), this, SLOT(slotReaderProcessedSize(int, int)) );
431
connect( d->dataTrackReader, SIGNAL(finished(bool)), this, SLOT(slotReaderFinished(bool)) );
432
connect( d->dataTrackReader, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) );
433
connect( d->dataTrackReader, SIGNAL(newTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) );
434
connect( d->dataTrackReader, SIGNAL(debuggingOutput(const QString&, const QString&)),
435
this, SIGNAL(debuggingOutput(const QString&, const QString&)) );
438
d->dataTrackReader->setDevice( m_readerDevice );
439
d->dataTrackReader->setIgnoreErrors( m_ignoreReadErrors );
440
d->dataTrackReader->setRetries( m_readRetries );
441
d->dataTrackReader->setSectorRange( 0, d->lastSector );
443
if( m_onTheFly && !m_onlyCreateImage )
444
// there are several uses of pipe->writeTo( d->writerJob->ioDevice(), ... ) in this file!
446
#warning Growisofs needs stdin to be closed in order to exit gracefully. Cdrecord does not. However, if closed with cdrecord we loose parts of stderr. Why?
448
d->inPipe.writeTo( d->writerJob->ioDevice(), d->usedWritingApp == K3b::WritingAppGrowisofs );
450
d->inPipe.writeTo( &d->imageFile, true );
452
d->inPipe.open( true );
453
d->dataTrackReader->writeTo( &d->inPipe );
457
// ALWAYS CALL WAITFORDVD BEFORE PREPAREWRITER!
458
void K3b::DvdCopyJob::prepareWriter()
462
if ( d->usedWritingApp == K3b::WritingAppGrowisofs ) {
463
K3b::GrowisofsWriter* job = new K3b::GrowisofsWriter( m_writerDevice, this, this );
465
// these do only make sense with DVD-R(W)
466
job->setSimulate( m_simulate );
467
job->setBurnSpeed( m_speed );
468
job->setWritingMode( d->usedWritingMode );
469
job->setCloseDvd( true );
472
// In case the first layer size is not known let the
473
// split be determined by growisofs
475
if( d->sourceDiskInfo.numLayers() > 1 &&
476
d->sourceDiskInfo.firstLayerSize() > 0 ) {
477
job->setLayerBreak( d->sourceDiskInfo.firstLayerSize().lba() );
480
// this is only used in DAO mode with growisofs >= 5.15
481
job->setTrackSize( d->lastSector.lba()+1 );
484
job->setImageToWrite( QString() ); // write to stdin
490
K3b::CdrecordWriter* writer = new K3b::CdrecordWriter( m_writerDevice, this, this );
492
writer->setWritingMode( d->usedWritingMode );
493
writer->setSimulate( m_simulate );
494
writer->setBurnSpeed( m_speed );
496
writer->addArgument( "-data" );
497
writer->addArgument( QString("-tsize=%1s").arg( d->lastSector.lba()+1 ) )->addArgument("-");
499
d->writerJob = writer;
503
connect( d->writerJob, SIGNAL(infoMessage(const QString&, int)), this, SIGNAL(infoMessage(const QString&, int)) );
504
connect( d->writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterProgress(int)) );
505
connect( d->writerJob, SIGNAL(processedSize(int, int)), this, SIGNAL(processedSize(int, int)) );
506
connect( d->writerJob, SIGNAL(processedSubSize(int, int)), this, SIGNAL(processedSubSize(int, int)) );
507
connect( d->writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) );
508
connect( d->writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) );
509
connect( d->writerJob, SIGNAL(writeSpeed(int, K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int, K3b::Device::SpeedMultiplicator)) );
510
connect( d->writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterFinished(bool)) );
511
// connect( d->writerJob, SIGNAL(newTask(const QString&)), this, SIGNAL(newTask(const QString&)) );
512
connect( d->writerJob, SIGNAL(newSubTask(const QString&)), this, SIGNAL(newSubTask(const QString&)) );
513
connect( d->writerJob, SIGNAL(debuggingOutput(const QString&, const QString&)),
514
this, SIGNAL(debuggingOutput(const QString&, const QString&)) );
518
void K3b::DvdCopyJob::slotReaderProgress( int p )
520
if( !m_onTheFly || m_onlyCreateImage ) {
521
emit subPercent( p );
523
int bigParts = ( m_onlyCreateImage ? 1 : (m_simulate ? 2 : ( d->verifyData ? m_copies*2 : m_copies ) + 1 ) );
524
emit percent( p/bigParts );
529
void K3b::DvdCopyJob::slotReaderProcessedSize( int p, int c )
531
if( !m_onTheFly || m_onlyCreateImage )
532
emit processedSubSize( p, c );
534
if( m_onlyCreateImage )
535
emit processedSize( p, c );
539
void K3b::DvdCopyJob::slotWriterProgress( int p )
541
int bigParts = ( m_simulate ? 1 : ( d->verifyData ? m_copies*2 : m_copies ) ) + ( m_onTheFly ? 0 : 1 );
542
int doneParts = ( m_simulate ? 0 : ( d->verifyData ? d->doneCopies*2 : d->doneCopies ) ) + ( m_onTheFly ? 0 : 1 );
543
emit percent( 100*doneParts/bigParts + p/bigParts );
545
emit subPercent( p );
549
void K3b::DvdCopyJob::slotVerificationProgress( int p )
551
int bigParts = ( m_simulate ? 1 : ( d->verifyData ? m_copies*2 : m_copies ) ) + ( m_onTheFly ? 0 : 1 );
552
int doneParts = ( m_simulate ? 0 : ( d->verifyData ? d->doneCopies*2 : d->doneCopies ) ) + ( m_onTheFly ? 0 : 1 ) + 1;
553
emit percent( 100*doneParts/bigParts + p/bigParts );
557
void K3b::DvdCopyJob::slotReaderFinished( bool success )
559
d->readerRunning = false;
573
emit infoMessage( i18n("Successfully read source medium."), MessageSuccess );
574
if( m_onlyCreateImage ) {
579
if( m_writerDevice == m_readerDevice ) {
580
// eject the media (we do this blocking to know if it worked
581
// because if it did not it might happen that k3b overwrites a CD-RW
583
kDebug() << "Ejecting read medium" << m_readerDevice->blockDeviceName();
584
if( !K3b::eject( m_readerDevice ) ) {
585
blockingInformation( i18n("K3b was unable to eject the source medium. Please do so manually.") );
591
d->imageFile.close();
596
emit newTask( i18n("Writing copy %1",d->doneCopies+1) );
598
emit newTask( i18n("Writing copy") );
602
d->writerRunning = true;
603
d->writerJob->start();
605
#warning Growisofs needs stdin to be closed in order to exit gracefully. Cdrecord does not. However, if closed with cdrecord we loose parts of stderr. Why?
607
d->outPipe.writeTo( d->writerJob->ioDevice(), d->usedWritingApp == K3b::WritingAppGrowisofs );
608
d->outPipe.open( true );
611
if( m_removeImageFiles )
629
void K3b::DvdCopyJob::slotWriterFinished( bool success )
631
d->writerRunning = false;
638
if( m_removeImageFiles )
646
emit infoMessage( i18n("Successfully written copy %1.",d->doneCopies+1), MessageInfo );
648
if( d->verifyData && !m_simulate ) {
649
if( !d->verificationJob ) {
650
d->verificationJob = new K3b::VerificationJob( this, this );
651
connect( d->verificationJob, SIGNAL(infoMessage(const QString&, int)),
652
this, SIGNAL(infoMessage(const QString&, int)) );
653
connect( d->verificationJob, SIGNAL(newTask(const QString&)),
654
this, SIGNAL(newSubTask(const QString&)) );
655
connect( d->verificationJob, SIGNAL(percent(int)),
656
this, SLOT(slotVerificationProgress(int)) );
657
connect( d->verificationJob, SIGNAL(percent(int)),
658
this, SIGNAL(subPercent(int)) );
659
connect( d->verificationJob, SIGNAL(finished(bool)),
660
this, SLOT(slotVerificationFinished(bool)) );
661
connect( d->verificationJob, SIGNAL(debuggingOutput(const QString&, const QString&)),
662
this, SIGNAL(debuggingOutput(const QString&, const QString&)) );
665
d->verificationJob->setDevice( m_writerDevice );
666
d->verificationJob->addTrack( 1, d->inPipe.checksum(), d->lastSector+1 );
669
emit newTask( i18n("Verifying copy %1",d->doneCopies+1) );
671
emit newTask( i18n("Verifying copy") );
673
emit burning( false );
675
d->verificationJob->start();
678
else if( ++d->doneCopies < m_copies ) {
680
if( !K3b::eject( m_writerDevice ) ) {
681
blockingInformation( i18n("K3b was unable to eject the written medium. Please do so manually.") );
686
emit newTask( i18n("Writing copy %1",d->doneCopies+1) );
690
d->writerRunning = true;
691
d->writerJob->start();
703
d->readerRunning = true;
704
d->dataTrackReader->start();
708
#warning Growisofs needs stdin to be closed in order to exit gracefully. Cdrecord does not. However, if closed with cdrecord we loose parts of stderr. Why?
710
d->outPipe.writeTo( d->writerJob->ioDevice(), true/*d->usedWritingApp == K3b::WritingAppGrowisofs*/ );
711
d->outPipe.open( true );
715
if ( k3bcore->globalSettings()->ejectMedia() ) {
716
K3b::Device::eject( m_writerDevice );
718
if( m_removeImageFiles )
725
if( m_removeImageFiles )
733
void K3b::DvdCopyJob::slotVerificationFinished( bool success )
737
jobFinished( false );
740
// we simply ignore the results from the verification, the verification
741
// job already emits a message
742
else if( ++d->doneCopies < m_copies ) {
746
emit newTask( i18n("Writing copy %1",d->doneCopies+1) );
750
d->writerRunning = true;
751
d->writerJob->start();
763
d->readerRunning = true;
764
d->dataTrackReader->start();
768
#warning Growisofs needs stdin to be closed in order to exit gracefully. Cdrecord does not. However, if closed with cdrecord we loose parts of stderr. Why?
770
d->outPipe.writeTo( d->writerJob->ioDevice(), d->usedWritingApp == K3b::WritingAppGrowisofs );
771
d->outPipe.open( true );
775
if( m_removeImageFiles )
778
jobFinished( success );
783
// this is basically the same code as in K3b::DvdJob... :(
784
// perhaps this should be moved to some K3b::GrowisofsHandler which also parses the growisofs output?
785
bool K3b::DvdCopyJob::waitForDvd()
787
Device::MediaTypes mt = 0;
788
if ( !K3b::Device::isDvdMedia( d->sourceDiskInfo.mediaType() ) &&
789
!K3b::Device::isBdMedia( d->sourceDiskInfo.mediaType() ) ) {
790
// this should NEVER happen
791
emit infoMessage( i18n( "Unsupported media type: %1" , K3b::Device::mediaTypeString( d->sourceDiskInfo.mediaType() ) ), MessageError );
795
Device::MediaType m = waitForMedium( m_writerDevice,
796
K3b::Device::STATE_EMPTY,
797
Device::MEDIA_WRITABLE_DVD|Device::MEDIA_WRITABLE_BD,
798
d->sourceDiskInfo.size() );
800
if( m == Device::MEDIA_UNKNOWN ) {
806
// -------------------------------
808
// -------------------------------
809
if( m & K3b::Device::MEDIA_DVD_PLUS_ALL ) {
811
if ( m & ( Device::MEDIA_DVD_PLUS_R|Device::MEDIA_DVD_PLUS_R_DL ) )
812
d->usedWritingMode = K3b::WritingModeSao;
814
d->usedWritingMode = K3b::WritingModeRestrictedOverwrite;
817
if( !questionYesNo( i18n("%1 media do not support write simulation. "
818
"Do you really want to continue? The disc will actually be "
819
"written to.", Device::mediaTypeString(m, true)),
820
i18n("No Simulation with %1", Device::mediaTypeString(m, true)) ) ) {
825
// m_simulate = false;
826
emit newTask( i18n("Writing DVD copy") );
829
if( m_writingMode != K3b::WritingModeAuto && m_writingMode != K3b::WritingModeRestrictedOverwrite )
830
emit infoMessage( i18n("Writing mode ignored when writing DVD+R(W) media."), MessageInfo );
832
emit infoMessage( i18n("Writing %1.", Device::mediaTypeString( m, true ) ), MessageInfo );
835
// -------------------------------
837
// -------------------------------
838
else if ( m & K3b::Device::MEDIA_DVD_MINUS_ALL ) {
839
if( m_simulate && !m_writerDevice->dvdMinusTestwrite() ) {
840
if( !questionYesNo( i18n("Your writer (%1 %2) does not support simulation with DVD-R(W) media. "
841
"Do you really want to continue? The media will actually be "
843
m_writerDevice->vendor(),
844
m_writerDevice->description()),
845
i18n("No Simulation with DVD-R(W)") ) ) {
850
// m_simulate = false;
854
// We do not default to DAO in onthefly mode since otherwise growisofs would
855
// use the size from the PVD to reserve space on the DVD and that can be bad
856
// if this size is wrong
857
// With growisofs 5.15 we have the option to specify the size of the image to be written in DAO mode.
859
// bool sizeWithDao = ( k3bcore->externalBinManager()->binObject( "growisofs" ) &&
860
// k3bcore->externalBinManager()->binObject( "growisofs" )->version >= K3b::Version( 5, 15, -1 ) );
863
// TODO: check for feature 0x21
865
if( m & K3b::Device::MEDIA_DVD_RW_OVWR ) {
866
emit infoMessage( i18n("Writing DVD-RW in restricted overwrite mode."), MessageInfo );
867
d->usedWritingMode = K3b::WritingModeRestrictedOverwrite;
869
else if( m & (K3b::Device::MEDIA_DVD_RW_SEQ|
870
K3b::Device::MEDIA_DVD_RW) ) {
871
if( m_writingMode == K3b::WritingModeSao ) {
872
// ( m_writingMode == K3b::WritingModeAuto &&
873
// ( sizeWithDao || !m_onTheFly ) ) ) {
874
emit infoMessage( i18n("Writing DVD-RW in DAO mode."), MessageInfo );
875
d->usedWritingMode = K3b::WritingModeSao;
878
emit infoMessage( i18n("Writing DVD-RW in incremental mode."), MessageInfo );
879
d->usedWritingMode = K3b::WritingModeIncrementalSequential;
884
// FIXME: DVD-R DL jump and stuff
886
if( m_writingMode == K3b::WritingModeRestrictedOverwrite )
887
emit infoMessage( i18n("Restricted Overwrite is not possible with DVD-R media."), MessageInfo );
889
if( m_writingMode == K3b::WritingModeSao ) {
890
// ( m_writingMode == K3b::WritingModeAuto &&
891
// ( sizeWithDao || !m_onTheFly ) ) ) {
892
emit infoMessage( i18n("Writing %1 in DAO mode.",K3b::Device::mediaTypeString(m, true) ), MessageInfo );
893
d->usedWritingMode = K3b::WritingModeSao;
896
emit infoMessage( i18n("Writing %1 in incremental mode.",K3b::Device::mediaTypeString(m, true) ), MessageInfo );
897
d->usedWritingMode = K3b::WritingModeIncrementalSequential;
903
// -------------------------------
905
// -------------------------------
907
d->usedWritingMode = K3b::WritingModeSao;
910
if( !questionYesNo( i18n("%1 media do not support write simulation. "
911
"Do you really want to continue? The disc will actually be "
912
"written to.", Device::mediaTypeString(m, true)),
913
i18n("No Simulation with %1", Device::mediaTypeString(m, true)) ) ) {
919
emit newTask( i18n("Writing BD copy") );
922
emit infoMessage( i18n("Writing %1.", Device::mediaTypeString(m, true) ), MessageInfo );
931
void K3b::DvdCopyJob::removeImageFiles()
933
if( QFile::exists( m_imagePath ) ) {
934
d->imageFile.remove();
935
emit infoMessage( i18n("Removed image file %1",m_imagePath), K3b::Job::MessageSuccess );
940
QString K3b::DvdCopyJob::jobDescription() const
942
if( m_onlyCreateImage ) {
943
return i18n("Creating Image");
947
return i18n("Copying DVD or BD On-The-Fly");
949
return i18n("Copying DVD or BD");
954
QString K3b::DvdCopyJob::jobDetails() const
956
return i18np("Creating 1 copy",
957
"Creating %1 copies",
958
(m_simulate||m_onlyCreateImage) ? 1 : m_copies );
962
void K3b::DvdCopyJob::setVerifyData( bool b )
967
#include "k3bdvdcopyjob.moc"