|
|
|
/*
|
|
|
|
*
|
|
|
|
* $Id: k3biso9660imagewritingjob.cpp 690187 2007-07-20 09:18:03Z trueg $
|
|
|
|
* Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
|
|
|
|
*
|
|
|
|
* This file is part of the K3b project.
|
|
|
|
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
* See the file "COPYING" for the exact licensing terms.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "k3biso9660imagewritingjob.h"
|
|
|
|
#include "k3bverificationjob.h"
|
|
|
|
|
|
|
|
#include <k3bdevice.h>
|
|
|
|
#include <k3bdiskinfo.h>
|
|
|
|
#include <k3bdevicehandler.h>
|
|
|
|
#include <k3bcdrecordwriter.h>
|
|
|
|
#include <k3bcdrdaowriter.h>
|
|
|
|
#include <k3bgrowisofswriter.h>
|
|
|
|
#include <k3bglobals.h>
|
|
|
|
#include <k3bcore.h>
|
|
|
|
#include <k3bversion.h>
|
|
|
|
#include <k3bexternalbinmanager.h>
|
|
|
|
#include <k3bchecksumpipe.h>
|
|
|
|
#include <k3bfilesplitter.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <ktempfile.h>
|
|
|
|
#include <kio/global.h>
|
|
|
|
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
|
|
|
|
|
|
|
|
class K3bIso9660ImageWritingJob::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
K3bChecksumPipe checksumPipe;
|
|
|
|
K3bFileSplitter imageFile;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
K3bIso9660ImageWritingJob::K3bIso9660ImageWritingJob( K3bJobHandler* hdl )
|
|
|
|
: K3bBurnJob( hdl ),
|
|
|
|
m_writingMode(K3b::WRITING_MODE_AUTO),
|
|
|
|
m_simulate(false),
|
|
|
|
m_device(0),
|
|
|
|
m_noFix(false),
|
|
|
|
m_speed(2),
|
|
|
|
m_dataMode(K3b::DATA_MODE_AUTO),
|
|
|
|
m_writer(0),
|
|
|
|
m_tocFile(0),
|
|
|
|
m_copies(1),
|
|
|
|
m_verifyJob(0)
|
|
|
|
{
|
|
|
|
d = new Private;
|
|
|
|
}
|
|
|
|
|
|
|
|
K3bIso9660ImageWritingJob::~K3bIso9660ImageWritingJob()
|
|
|
|
{
|
|
|
|
delete m_tocFile;
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::start()
|
|
|
|
{
|
|
|
|
m_canceled = m_finished = false;
|
|
|
|
m_currentCopy = 1;
|
|
|
|
|
|
|
|
jobStarted();
|
|
|
|
|
|
|
|
if( m_simulate )
|
|
|
|
m_verifyData = false;
|
|
|
|
|
|
|
|
emit newTask( i18n("Preparing data") );
|
|
|
|
|
|
|
|
if( !TQFile::exists( m_imagePath ) ) {
|
|
|
|
emit infoMessage( i18n("Could not find image %1").arg(m_imagePath), K3bJob::ERROR );
|
|
|
|
jobFinished( false );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned long gb = K3b::imageFilesize( m_imagePath )/1024/1024;
|
|
|
|
|
|
|
|
// very rough test but since most dvd images are 4,x or 8,x GB it should be enough
|
|
|
|
m_dvd = ( gb > 900 );
|
|
|
|
|
|
|
|
startWriting();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::slotWriterJobFinished( bool success )
|
|
|
|
{
|
|
|
|
if( m_canceled ) {
|
|
|
|
m_finished = true;
|
|
|
|
emit canceled();
|
|
|
|
jobFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
d->checksumPipe.close();
|
|
|
|
|
|
|
|
if( success ) {
|
|
|
|
if( !m_simulate && m_verifyData ) {
|
|
|
|
emit burning(false);
|
|
|
|
|
|
|
|
// allright
|
|
|
|
// the writerJob should have emited the "simulation/writing successful" signal
|
|
|
|
|
|
|
|
if( !m_verifyJob ) {
|
|
|
|
m_verifyJob = new K3bVerificationJob( this );
|
|
|
|
connectSubJob( m_verifyJob,
|
|
|
|
TQT_SLOT(slotVerificationFinished(bool)),
|
|
|
|
true,
|
|
|
|
TQT_SLOT(slotVerificationProgress(int)),
|
|
|
|
TQT_SIGNAL(subPercent(int)) );
|
|
|
|
}
|
|
|
|
m_verifyJob->setDevice( m_device );
|
|
|
|
m_verifyJob->clear();
|
|
|
|
m_verifyJob->addTrack( 1, d->checksumPipe.checksum(), K3b::imageFilesize( m_imagePath )/2048 );
|
|
|
|
|
|
|
|
if( m_copies == 1 )
|
|
|
|
emit newTask( i18n("Verifying written data") );
|
|
|
|
else
|
|
|
|
emit newTask( i18n("Verifying written copy %1 of %2").arg(m_currentCopy).arg(m_copies) );
|
|
|
|
|
|
|
|
m_verifyJob->start();
|
|
|
|
}
|
|
|
|
else if( m_currentCopy >= m_copies ) {
|
|
|
|
m_finished = true;
|
|
|
|
jobFinished(true);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_currentCopy++;
|
|
|
|
startWriting();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_finished = true;
|
|
|
|
jobFinished(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::slotVerificationFinished( bool success )
|
|
|
|
{
|
|
|
|
if( m_canceled ) {
|
|
|
|
m_finished = true;
|
|
|
|
emit canceled();
|
|
|
|
jobFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( success && m_currentCopy < m_copies ) {
|
|
|
|
m_currentCopy++;
|
|
|
|
connect( K3bDevice::eject( m_device ), TQT_SIGNAL(finished(bool)),
|
|
|
|
this, TQT_SLOT(startWriting()) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
k3bcore->config()->setGroup("General Options");
|
|
|
|
if( !k3bcore->config()->readBoolEntry( "No cd eject", false ) )
|
|
|
|
K3bDevice::eject( m_device );
|
|
|
|
|
|
|
|
m_finished = true;
|
|
|
|
jobFinished( success );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::slotVerificationProgress( int p )
|
|
|
|
{
|
|
|
|
emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + 0.5 + (double)p/200.0 )) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::slotWriterPercent( int p )
|
|
|
|
{
|
|
|
|
emit subPercent( p );
|
|
|
|
|
|
|
|
if( m_verifyData )
|
|
|
|
emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + ((double)p/200.0) )) );
|
|
|
|
else
|
|
|
|
emit percent( (int)(100.0 / (double)m_copies * ( (double)(m_currentCopy-1) + ((double)p/100.0) )) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::slotNextTrack( int, int )
|
|
|
|
{
|
|
|
|
if( m_copies == 1 )
|
|
|
|
emit newSubTask( i18n("Writing image") );
|
|
|
|
else
|
|
|
|
emit newSubTask( i18n("Writing copy %1 of %2").arg(m_currentCopy).arg(m_copies) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::cancel()
|
|
|
|
{
|
|
|
|
if( !m_finished ) {
|
|
|
|
m_canceled = true;
|
|
|
|
|
|
|
|
if( m_writer )
|
|
|
|
m_writer->cancel();
|
|
|
|
if( m_verifyData && m_verifyJob )
|
|
|
|
m_verifyJob->cancel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bIso9660ImageWritingJob::startWriting()
|
|
|
|
{
|
|
|
|
emit newSubTask( i18n("Waiting for medium") );
|
|
|
|
|
|
|
|
// we wait for the following:
|
|
|
|
// 1. if writing mode auto and writing app auto: all writable media types
|
|
|
|
// 2. if writing mode auto and writing app not growisofs: all writable cd types
|
|
|
|
// 3. if writing mode auto and writing app growisofs: all writable dvd types
|
|
|
|
// 4. if writing mode TAO or RAW: all writable cd types
|
|
|
|
// 5. if writing mode DAO and writing app auto: all writable cd types and DVD-R(W)
|
|
|
|
// 6. if writing mode DAO and writing app GROWISOFS: DVD-R(W)
|
|
|
|
// 7. if writing mode DAO and writing app CDRDAO or CDRECORD: all writable cd types
|
|
|
|
// 8. if writing mode WRITING_MODE_INCR_SEQ: DVD-R(W)
|
|
|
|
// 9. if writing mode WRITING_MODE_RES_OVWR: DVD-RW or DVD+RW
|
|
|
|
|
|
|
|
int mt = 0;
|
|
|
|
if( m_writingMode == K3b::WRITING_MODE_AUTO ) {
|
|
|
|
if( writingApp() == K3b::DEFAULT ) {
|
|
|
|
if( m_dvd )
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_DVD;
|
|
|
|
else
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_CD;
|
|
|
|
}
|
|
|
|
else if( writingApp() != K3b::GROWISOFS )
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_CD;
|
|
|
|
else
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_DVD;
|
|
|
|
}
|
|
|
|
else if( m_writingMode == K3b::TAO || m_writingMode == K3b::RAW )
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_CD;
|
|
|
|
else if( m_writingMode == K3b::DAO ) {
|
|
|
|
if( writingApp() == K3b::DEFAULT ) {
|
|
|
|
if( m_dvd )
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_DVD;
|
|
|
|
else
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_CD;
|
|
|
|
}
|
|
|
|
else if( writingApp() == K3b::GROWISOFS )
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_DVD;
|
|
|
|
else
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_CD;
|
|
|
|
}
|
|
|
|
else if( m_writingMode == K3b::WRITING_MODE_RES_OVWR )
|
|
|
|
mt = K3bDevice::MEDIA_DVD_PLUS_R|K3bDevice::MEDIA_DVD_PLUS_R_DL|K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR;
|
|
|
|
else
|
|
|
|
mt = K3bDevice::MEDIA_WRITABLE_DVD;
|
|
|
|
|
|
|
|
|
|
|
|
// wait for the media
|
|
|
|
int media = waitForMedia( m_device, K3bDevice::STATE_EMPTY, mt );
|
|
|
|
if( media < 0 ) {
|
|
|
|
m_finished = true;
|
|
|
|
emit canceled();
|
|
|
|
jobFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// we simply always calculate the checksum, thus making the code simpler
|
|
|
|
d->imageFile.close();
|
|
|
|
d->imageFile.setName( m_imagePath );
|
|
|
|
d->imageFile.open( IO_ReadOnly );
|
|
|
|
d->checksumPipe.close();
|
|
|
|
d->checksumPipe.readFromIODevice( &d->imageFile );
|
|
|
|
|
|
|
|
if( prepareWriter( media ) ) {
|
|
|
|
emit burning(true);
|
|
|
|
m_writer->start();
|
|
|
|
d->checksumPipe.writeToFd( m_writer->fd(), true );
|
|
|
|
d->checksumPipe.open( K3bChecksumPipe::MD5, true );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_finished = true;
|
|
|
|
jobFinished(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool K3bIso9660ImageWritingJob::prepareWriter( int mediaType )
|
|
|
|
{
|
|
|
|
if( mediaType == 0 ) { // media forced
|
|
|
|
// just to get it going...
|
|
|
|
if( writingApp() != K3b::GROWISOFS && !m_dvd )
|
|
|
|
mediaType = K3bDevice::MEDIA_CD_R;
|
|
|
|
else
|
|
|
|
mediaType = K3bDevice::MEDIA_DVD_R;
|
|
|
|
}
|
|
|
|
|
|
|
|
delete m_writer;
|
|
|
|
|
|
|
|
if( mediaType == K3bDevice::MEDIA_CD_R || mediaType == K3bDevice::MEDIA_CD_RW ) {
|
|
|
|
int usedWritingMode = m_writingMode;
|
|
|
|
if( usedWritingMode == K3b::WRITING_MODE_AUTO ) {
|
|
|
|
// cdrecord seems to have problems when writing in mode2 in dao mode
|
|
|
|
// so with cdrecord we use TAO
|
|
|
|
if( m_noFix || m_dataMode == K3b::MODE2 || !m_device->dao() )
|
|
|
|
usedWritingMode = K3b::TAO;
|
|
|
|
else
|
|
|
|
usedWritingMode = K3b::DAO;
|
|
|
|
}
|
|
|
|
|
|
|
|
int usedApp = writingApp();
|
|
|
|
if( usedApp == K3b::DEFAULT ) {
|
|
|
|
if( usedWritingMode == K3b::DAO &&
|
|
|
|
( m_dataMode == K3b::MODE2 || m_noFix ) )
|
|
|
|
usedApp = K3b::CDRDAO;
|
|
|
|
else
|
|
|
|
usedApp = K3b::CDRECORD;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if( usedApp == K3b::CDRECORD ) {
|
|
|
|
K3bCdrecordWriter* writer = new K3bCdrecordWriter( m_device, this );
|
|
|
|
|
|
|
|
writer->setWritingMode( usedWritingMode );
|
|
|
|
writer->setSimulate( m_simulate );
|
|
|
|
writer->setBurnSpeed( m_speed );
|
|
|
|
|
|
|
|
if( m_noFix ) {
|
|
|
|
writer->addArgument("-multi");
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (m_dataMode == K3b::DATA_MODE_AUTO && m_noFix) ||
|
|
|
|
m_dataMode == K3b::MODE2 ) {
|
|
|
|
if( k3bcore->externalBinManager()->binObject("cdrecord") &&
|
|
|
|
k3bcore->externalBinManager()->binObject("cdrecord")->hasFeature( "xamix" ) )
|
|
|
|
writer->addArgument( "-xa" );
|
|
|
|
else
|
|
|
|
writer->addArgument( "-xa1" );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
writer->addArgument("-data");
|
|
|
|
|
|
|
|
// read from stdin
|
|
|
|
writer->addArgument( TQString("-tsize=%1s").arg( K3b::imageFilesize( m_imagePath )/2048 ) )->addArgument( "-" );
|
|
|
|
|
|
|
|
m_writer = writer;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// create cdrdao job
|
|
|
|
K3bCdrdaoWriter* writer = new K3bCdrdaoWriter( m_device, this );
|
|
|
|
writer->setCommand( K3bCdrdaoWriter::WRITE );
|
|
|
|
writer->setSimulate( m_simulate );
|
|
|
|
writer->setBurnSpeed( m_speed );
|
|
|
|
// multisession
|
|
|
|
writer->setMulti( m_noFix );
|
|
|
|
|
|
|
|
// now write the tocfile
|
|
|
|
delete m_tocFile;
|
|
|
|
m_tocFile = new KTempFile( TQString(), "toc" );
|
|
|
|
m_tocFile->setAutoDelete(true);
|
|
|
|
|
|
|
|
if( TQTextStream* s = m_tocFile->textStream() ) {
|
|
|
|
if( (m_dataMode == K3b::DATA_MODE_AUTO && m_noFix) ||
|
|
|
|
m_dataMode == K3b::MODE2 ) {
|
|
|
|
*s << "CD_ROM_XA" << "\n";
|
|
|
|
*s << "\n";
|
|
|
|
*s << "TRACK MODE2_FORM1" << "\n";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*s << "CD_ROM" << "\n";
|
|
|
|
*s << "\n";
|
|
|
|
*s << "TRACK MODE1" << "\n";
|
|
|
|
}
|
|
|
|
*s << "DATAFILE \"-\" " << TQString::number( K3b::imageFilesize( m_imagePath ) ) << "\n";
|
|
|
|
|
|
|
|
m_tocFile->close();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kdDebug() << "(K3bDataJob) could not write tocfile." << endl;
|
|
|
|
emit infoMessage( i18n("IO Error"), ERROR );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
writer->setTocFile( m_tocFile->name() );
|
|
|
|
|
|
|
|
m_writer = writer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // DVD
|
|
|
|
if( mediaType & K3bDevice::MEDIA_DVD_PLUS_ALL ) {
|
|
|
|
if( m_simulate ) {
|
|
|
|
if( questionYesNo( i18n("K3b does not support simulation with DVD+R(W) media. "
|
|
|
|
"Do you really want to continue? The media will be written "
|
|
|
|
"for real."),
|
|
|
|
i18n("No Simulation with DVD+R(W)") ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_simulate = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
K3bGrowisofsWriter* writer = new K3bGrowisofsWriter( m_device, this );
|
|
|
|
writer->setSimulate( m_simulate );
|
|
|
|
writer->setBurnSpeed( m_speed );
|
|
|
|
writer->setWritingMode( m_writingMode == K3b::DAO ? K3b::DAO : 0 );
|
|
|
|
writer->setImageToWrite( TQString() ); // read from stdin
|
|
|
|
writer->setCloseDvd( !m_noFix );
|
|
|
|
writer->setTrackSize( K3b::imageFilesize( m_imagePath )/2048 );
|
|
|
|
|
|
|
|
m_writer = writer;
|
|
|
|
}
|
|
|
|
|
|
|
|
connect( m_writer, TQT_SIGNAL(infoMessage(const TQString&, int)), this, TQT_SIGNAL(infoMessage(const TQString&, int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(nextTrack(int, int)), this, TQT_SLOT(slotNextTrack(int, int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(percent(int)), this, TQT_SLOT(slotWriterPercent(int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(processedSize(int, int)), this, TQT_SIGNAL(processedSize(int, int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(buffer(int)), this, TQT_SIGNAL(bufferStatus(int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(deviceBuffer(int)), this, TQT_SIGNAL(deviceBuffer(int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(writeSpeed(int, int)), this, TQT_SIGNAL(writeSpeed(int, int)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(finished(bool)), this, TQT_SLOT(slotWriterJobFinished(bool)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(newTask(const TQString&)), this, TQT_SIGNAL(newTask(const TQString&)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(newSubTask(const TQString&)), this, TQT_SIGNAL(newSubTask(const TQString&)) );
|
|
|
|
connect( m_writer, TQT_SIGNAL(debuggingOutput(const TQString&, const TQString&)),
|
|
|
|
this, TQT_SIGNAL(debuggingOutput(const TQString&, const TQString&)) );
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString K3bIso9660ImageWritingJob::jobDescription() const
|
|
|
|
{
|
|
|
|
if( m_simulate )
|
|
|
|
return i18n("Simulating ISO9660 Image");
|
|
|
|
else
|
|
|
|
return ( i18n("Burning ISO9660 Image")
|
|
|
|
+ ( m_copies > 1
|
|
|
|
? i18n(" - %n Copy", " - %n Copies", m_copies)
|
|
|
|
: TQString() ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString K3bIso9660ImageWritingJob::jobDetails() const
|
|
|
|
{
|
|
|
|
return m_imagePath.section("/", -1) + TQString( " (%1)" ).arg(KIO::convertSize(K3b::filesize(KURL::fromPathOrURL(m_imagePath))));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "k3biso9660imagewritingjob.moc"
|