K3b::MovixJob::MovixJob( K3b::MovixDoc* doc, K3b::JobHandler* jh, QObject* parent ) : K3b::BurnJob( jh, parent ), m_doc(doc) { m_dataJob = new K3b::DataJob( doc, this, this ); m_movixDocPreparer = new K3b::MovixDocPreparer( doc, this, this ); // pipe signals connect( m_dataJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); connect( m_dataJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); connect( m_dataJob, SIGNAL(processedSubSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); connect( m_dataJob, SIGNAL(processedSize(int,int)), this, SIGNAL(processedSize(int,int)) ); connect( m_dataJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); connect( m_dataJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); connect( m_dataJob, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)) ); connect( m_dataJob, SIGNAL(newTask(QString)), this, SIGNAL(newTask(QString)) ); connect( m_dataJob, SIGNAL(newSubTask(QString)), this, SIGNAL(newSubTask(QString)) ); connect( m_dataJob, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); connect( m_dataJob, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); connect( m_dataJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); // we need to clean up here connect( m_dataJob, SIGNAL(finished(bool)), this, SLOT(slotDataJobFinished(bool)) ); connect( m_movixDocPreparer, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); }
K3b::AudioCueFileWritingJob::AudioCueFileWritingJob( K3b::JobHandler* jh, QObject* parent ) : K3b::BurnJob( jh, parent ), d( new Private() ) { d->analyserJob = new K3b::AudioFileAnalyzerJob( this, this ); connect( d->analyserJob, SIGNAL(finished(bool)), this, SLOT(slotAnalyserJobFinished(bool)) ); d->audioDoc = new K3b::AudioDoc( this ); d->audioDoc->newDocument(); d->audioJob = new K3b::AudioJob( d->audioDoc, this, this ); // just loop all through connect( d->audioJob, SIGNAL(newTask(QString)), this, SIGNAL(newTask(QString)) ); connect( d->audioJob, SIGNAL(newSubTask(QString)), this, SIGNAL(newSubTask(QString)) ); connect( d->audioJob, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); connect( d->audioJob, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); connect( d->audioJob, SIGNAL(finished(bool)), this, SIGNAL(finished(bool)) ); connect( d->audioJob, SIGNAL(canceled()), this, SIGNAL(canceled()) ); connect( d->audioJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); connect( d->audioJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); connect( d->audioJob, SIGNAL(processedSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); connect( d->audioJob, SIGNAL(processedSubSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); connect( d->audioJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); connect( d->audioJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); connect( d->audioJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); connect( d->audioJob, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)) ); d->canceled = false; d->audioJobRunning = false; }
void K3b::VerificationJob::readTrack() { if( d->currentTrackEntry == d->trackEntries.end() ) { jobFinished(true); return; } d->readSuccessful = true; d->currentTrackSize = d->trackLength( *d->currentTrackEntry ); if( d->currentTrackSize == 0 ) { jobFinished(false); return; } emit newTask( i18n("Verifying track %1", d->currentTrackEntry->trackNumber ) ); K3b::Device::Track& track = d->toc[ d->currentTrackEntry->trackNumber-1 ]; d->pipe.open(); if( track.type() == K3b::Device::Track::TYPE_DATA ) { if( !d->dataTrackReader ) { d->dataTrackReader = new K3b::DataTrackReader( this ); connect( d->dataTrackReader, SIGNAL(percent(int)), this, SLOT(slotReaderProgress(int)) ); connect( d->dataTrackReader, SIGNAL(finished(bool)), this, SLOT(slotReaderFinished(bool)) ); connect( d->dataTrackReader, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); connect( d->dataTrackReader, SIGNAL(newTask(QString)), this, SIGNAL(newSubTask(QString)) ); connect( d->dataTrackReader, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); } d->dataTrackReader->setDevice( d->device ); d->dataTrackReader->setIgnoreErrors( false ); d->dataTrackReader->setSectorSize( K3b::DataTrackReader::MODE1 ); d->dataTrackReader->writeTo( &d->pipe ); // in case a session was grown the track size does not say anything about the verification data size if( d->diskInfo.mediaType() & (K3b::Device::MEDIA_DVD_PLUS_RW|K3b::Device::MEDIA_DVD_RW_OVWR) && d->grownSessionSize > 0 ) { K3b::Iso9660 isoF( d->device ); if( isoF.open() ) { int firstSector = isoF.primaryDescriptor().volumeSpaceSize - d->grownSessionSize.lba(); d->dataTrackReader->setSectorRange( firstSector, isoF.primaryDescriptor().volumeSpaceSize -1 ); } else { emit infoMessage( i18n("Unable to determine the ISO 9660 filesystem size."), MessageError ); jobFinished( false ); return; } } else d->dataTrackReader->setSectorRange( track.firstSector(), track.firstSector() + d->currentTrackSize -1 ); d->pipe.open(); d->dataTrackReader->start(); }
bool K3b::VcdJob::prepareWriterJob() { if ( m_writerJob ) delete m_writerJob; const K3b::ExternalBin* cdrecordBin = k3bcore->externalBinManager() ->binObject( "cdrecord" ); if ( writingApp() == K3b::WritingAppAuto && cdrecordBin->hasFeature( "cuefile" ) && m_doc->burner() ->dao() ) setWritingApp( K3b::WritingAppCdrecord ); if ( writingApp() == K3b::WritingAppCdrdao || writingApp() == K3b::WritingAppAuto ) { K3b::CdrdaoWriter * writer = new K3b::CdrdaoWriter( m_doc->burner(), this, this ); // create cdrdao job writer->setCommand( K3b::CdrdaoWriter::WRITE ); writer->setSimulate( m_doc->dummy() ); writer->setBurnSpeed( m_doc->speed() ); writer->setTocFile( m_cueFile ); m_writerJob = writer; } else if ( writingApp() == K3b::WritingAppCdrecord ) { K3b::CdrecordWriter * writer = new K3b::CdrecordWriter( m_doc->burner(), this, this ); // create cdrecord job writer->setSimulate( m_doc->dummy() ); writer->setBurnSpeed( m_doc->speed() ); writer->setDao( true ); writer->setCueFile( m_cueFile ); m_writerJob = writer; } connect( m_writerJob, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); connect( m_writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterJobPercent(int)) ); connect( m_writerJob, SIGNAL(processedSize(int,int)), this, SLOT(slotProcessedSize(int,int)) ); connect( m_writerJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); connect( m_writerJob, SIGNAL(processedSubSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); connect( m_writerJob, SIGNAL(nextTrack(int,int)), this, SLOT(slotWriterNextTrack(int,int)) ); connect( m_writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); connect( m_writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); connect( m_writerJob, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)) ); connect( m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterJobFinished(bool)) ); connect( m_writerJob, SIGNAL(newTask(QString)), this, SIGNAL(newTask(QString)) ); connect( m_writerJob, SIGNAL(newSubTask(QString)), this, SIGNAL(newSubTask(QString)) ); connect( m_writerJob, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); return true; }
void K3bIsoImager::slotCollectMkisofsPrintSizeStdout( const QString& line ) { // newer versions of mkisofs outut additional lines of junk before the size :( // so we only use the last line emit debuggingOutput( "mkisofs", line ); m_collectedMkisofsPrintSizeStdout = line; }
void K3b::BlankingJob::slotStartErasing() { m_canceled = false; if( m_writerJob ) delete m_writerJob; if( m_writingApp == K3b::WritingAppCdrdao ) { K3b::CdrdaoWriter* writer = new K3b::CdrdaoWriter( m_device, this ); m_writerJob = writer; writer->setCommand( K3b::CdrdaoWriter::BLANK ); writer->setBlankMode( m_mode ); writer->setForce( m_force ); writer->setBurnSpeed( m_speed ); } else { K3b::CdrecordWriter* writer = new K3b::CdrecordWriter( m_device, this ); m_writerJob = writer; writer->setFormattingMode( m_mode ); writer->setForce( m_force ); writer->setBurnSpeed( m_speed ); } connect(m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotFinished(bool))); connect(m_writerJob, SIGNAL(infoMessage(QString,int)), this,SIGNAL(infoMessage(QString,int))); connect( m_writerJob, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); if( waitForMedium( m_device, K3b::Device::STATE_COMPLETE|K3b::Device::STATE_INCOMPLETE, K3b::Device::MEDIA_CD_RW, 0, i18n("Please insert a rewritable CD medium into drive<p><b>%1 %2 (%3)</b>.", m_device->vendor(), m_device->description(), m_device->blockDeviceName()) ) == Device::MEDIA_UNKNOWN ) { emit canceled(); jobFinished(false); return; } m_writerJob->start(); }
void K3bThreadJob::customEvent( QCustomEvent* e ) { if( K3bDataEvent* de = dynamic_cast<K3bDataEvent*>(e) ) { emit data( de->data(), de->length() ); } else { K3bProgressInfoEvent* be = static_cast<K3bProgressInfoEvent*>(e); switch( be->type() ) { case K3bProgressInfoEvent::Progress: emit percent( be->firstValue() ); break; case K3bProgressInfoEvent::SubProgress: emit subPercent( be->firstValue() ); break; case K3bProgressInfoEvent::ProcessedSize: emit processedSize( be->firstValue(), be->secondValue() ); break; case K3bProgressInfoEvent::ProcessedSubSize: emit processedSubSize( be->firstValue(), be->secondValue() ); break; case K3bProgressInfoEvent::InfoMessage: emit infoMessage( be->firstString(), be->firstValue() ); break; case K3bProgressInfoEvent::Started: jobStarted(); break; case K3bProgressInfoEvent::Canceled: emit canceled(); break; case K3bProgressInfoEvent::Finished: // we wait until the thred really finished // although this may be dangerous if some thread // emits the finished signal although it has not finished yet // but makes a lot stuff easier. kdDebug() << "(K3bThreadJob) waiting for the thread to finish." << endl; m_thread->wait(); kdDebug() << "(K3bThreadJob) thread finished." << endl; cleanupJob( be->firstValue() ); m_running = false; jobFinished( be->firstValue() ); break; case K3bProgressInfoEvent::NewTask: emit newTask( be->firstString() ); break; case K3bProgressInfoEvent::NewSubTask: emit newSubTask( be->firstString() ); break; case K3bProgressInfoEvent::DebuggingOutput: emit debuggingOutput( be->firstString(), be->secondString() ); break; case K3bProgressInfoEvent::NextTrack: emit nextTrack( be->firstValue(), be->secondValue() ); break; } } }
void K3b::IsoImager::start() { jobStarted(); cleanup(); d->mkisofsBin = initMkisofs(); if( !d->mkisofsBin ) { jobFinished( false ); return; } initVariables(); delete m_process; m_process = new K3b::Process( this ); m_process->setFlags( K3bQProcess::RawStdout ); *m_process << d->mkisofsBin; // prepare the filenames as written to the image m_doc->prepareFilenames(); if( !prepareMkisofsFiles() || !addMkisofsParameters() ) { cleanup(); jobFinished( false ); return; } connect( m_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotProcessExited(int,QProcess::ExitStatus)) ); connect( m_process, SIGNAL(stderrLine(QString)), this, SLOT(slotReceivedStderr(QString)) ); qDebug() << "***** mkisofs parameters:\n"; QString s = m_process->joinedArgs(); qDebug() << s << endl << flush; emit debuggingOutput("mkisofs command:", s); if( !m_process->start( KProcess::SeparateChannels ) ) { // something went wrong when starting the program // it "should" be the executable qDebug() << "(K3b::IsoImager) could not start mkisofs"; emit infoMessage( i18n("Could not start %1.", QLatin1String("mkisofs")), K3b::Job::MessageError ); jobFinished( false ); cleanup(); } }
void K3bIsoImager::slotMkisofsPrintSizeFinished() { if( m_canceled ) { emit canceled(); jobFinished( false ); return; } bool success = true; // if m_collectedMkisofsPrintSizeStdout is not empty we have a recent version of // mkisofs and parsing is very easy (s.o.) if( !m_collectedMkisofsPrintSizeStdout.isEmpty() ) { kdDebug() << "(K3bIsoImager) iso size: " << m_collectedMkisofsPrintSizeStdout << endl; m_mkisofsPrintSizeResult = m_collectedMkisofsPrintSizeStdout.toInt( &success ); } else { // parse the stderr output // I hope parsing the last line is enough! int pos = m_collectedMkisofsPrintSizeStderr.findRev( "extents scheduled to be written" ); if( pos == -1 ) success = false; else m_mkisofsPrintSizeResult = m_collectedMkisofsPrintSizeStderr.mid( pos+33 ).toInt( &success ); } emit debuggingOutput( "K3bIsoImager", QString("mkisofs print size result: %1 (%2 bytes)") .arg(m_mkisofsPrintSizeResult) .arg(Q_UINT64(m_mkisofsPrintSizeResult)*2048ULL) ); cleanup(); if( success ) { jobFinished( true ); } else { m_mkisofsPrintSizeResult = 0; kdDebug() << "(K3bIsoImager) Parsing mkisofs -print-size failed: " << m_collectedMkisofsPrintSizeStdout << endl; emit infoMessage( i18n("Could not determine size of resulting image file."), ERROR ); jobFinished( false ); } }
void K3bDvdFormattingJob::slotStderrLine( const QString& line ) { // * DVD±RW format utility by <*****@*****.**>, version 4.4. // * 4.7GB DVD-RW media in Sequential mode detected. // * blanking 100.0| // * formatting 100.0| emit debuggingOutput( "dvd+rw-format", line ); // parsing for the -gui mode (since dvd+rw-format 4.6) int pos = line.find( "blanking" ); if( pos < 0 ) pos = line.find( "formatting" ); if( pos >= 0 ) { pos = line.find( QRegExp( "\\d" ), pos ); } // parsing for \b\b... stuff else if( !line.startsWith("*") ) { pos = line.find( QRegExp( "\\d" ) ); } else if( line.startsWith( ":-(" ) ) { if( line.startsWith( ":-( unable to proceed with format" ) ) { d->error = true; } } if( pos >= 0 ) { int endPos = line.find( QRegExp("[^\\d\\.]"), pos ) - 1; bool ok; int progress = (int)(line.mid( pos, endPos - pos ).toDouble(&ok)); if( ok ) { d->lastProgressValue = progress; emit percent( progress ); } else { kdDebug() << "(K3bDvdFormattingJob) parsing error: '" << line.mid( pos, endPos - pos ) << "'" << endl; } } }
void K3b::VcdJob::xmlGen() { delete d->xmlFile; d->xmlFile = new QTemporaryFile; if( d->xmlFile->open() ) { qDebug() << "(K3b::VcdJob) writing XML data to" << d->xmlFile->fileName(); K3b::VcdXmlView xmlView( m_doc ); xmlView.write( *d->xmlFile ); // emit infoMessage( i18n( "XML-file successfully created" ), K3b::Job::MessageSuccess ); emit debuggingOutput( "K3b::VcdXml:", xmlView.xmlString() ); vcdxBuild(); } else { qDebug() << "(K3b::VcdJob) could not write xmlfile."; emit infoMessage( i18n( "Could not write correct XML file." ), K3b::Job::MessageError ); cancelAll(); jobFinished( false ); } }
void K3b::Md5Job::slotUpdate() { if( !d->finished ) { // determine bytes to read qint64 readSize = Private::BUFFERSIZE; if( d->maxSize > 0 ) readSize = qMin( readSize, d->maxSize - d->readData ); if( readSize <= 0 ) { // qDebug() << "(K3b::Md5Job) reached max size of " << d->maxSize << ". Stopping."; emit debuggingOutput( "K3b::Md5Job", QString("Reached max read of %1. Stopping after %2 bytes.").arg(d->maxSize).arg(d->readData) ); stopAll(); emit percent( 100 ); jobFinished(true); } else { int read = 0; // // read from the iso9660 file // if( d->isoFile ) { read = d->isoFile->read( d->readData, d->data, readSize ); } // // read from the device // else if( d->device ) { // // when reading from a device we always read multiples of 2048 bytes. // Only the last sector may not be used completely. // qint64 sector = d->readData/2048; qint64 sectorCnt = qMax( readSize/2048, ( qint64 )1 ); read = -1; if( d->device->read10( reinterpret_cast<unsigned char*>(d->data), sectorCnt*2048, sector, sectorCnt ) ) read = qMin( readSize, sectorCnt*2048 ); } // // read from the file // else if( !d->ioDevice ) { read = d->file.read( d->data, readSize ); } // // reading from the io device // else { read = d->ioDevice->read( d->data, readSize ); } if( read < 0 ) { emit infoMessage( i18n("Error while reading from file %1", d->filename), MessageError ); stopAll(); jobFinished(false); } else if( read == 0 ) { // qDebug() << "(K3b::Md5Job) read all data. Total size: " << d->readData << ". Stopping."; emit debuggingOutput( "K3b::Md5Job", QString("All data read. Stopping after %1 bytes.").arg(d->readData) ); stopAll(); emit percent( 100 ); jobFinished(true); } else { d->readData += read; d->md5.addData( d->data, read ); int progress = 0; if( d->isoFile || !d->filename.isEmpty() ) progress = (int)((double)d->readData * 100.0 / (double)d->imageSize); else if( d->maxSize > 0 ) progress = (int)((double)d->readData * 100.0 / (double)d->maxSize); if( progress != d->lastProgress ) { d->lastProgress = progress; emit percent( progress ); } } } } }
void K3b::VcdJob::slotParseVcdxBuildOutput( const QString& line ) { QDomDocument xml_doc; QDomElement xml_root; QString str = line.trimmed(); emit debuggingOutput( "vcdxbuild", str ); xml_doc.setContent( QString( "<?xml version='1.0'?><vcdxbuild>" ) + str + "</vcdxbuild>" ); xml_root = xml_doc.documentElement(); // There should be only one... but ... for ( QDomNode node = xml_root.firstChild(); !node.isNull(); node = node.nextSibling() ) { QDomElement el = node.toElement(); if ( el.isNull() ) continue; const QString tagName = el.tagName().toLower(); if ( tagName == "progress" ) { const QString oper = el.attribute( "operation" ).toLower(); const unsigned long long pos = el.attribute( "position" ).toLong(); const long long size = el.attribute( "size" ).toLong(); if ( oper == "scan" ) { // Scan Video Files if ( m_stage == stageUnknown || pos < m_bytesFinished ) { const uint index = el.attribute( "id" ).remove( QRegExp( "sequence-" ) ).toUInt(); m_currentWrittenTrack = m_doc->at( m_currentWrittenTrackNumber ); emit newSubTask( i18n( "Scanning video file %1 of %2 (%3)" , index + 1 , doc() ->numOfTracks() , m_currentWrittenTrack->fileName() ) ); m_bytesFinished = 0; if ( !firstTrack ) { m_bytesFinishedTracks += m_doc->at( m_currentWrittenTrackNumber ) ->size(); m_currentWrittenTrackNumber++; } else firstTrack = false; } emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); emit processedSubSize( pos / 1024 / 1024, size / 1024 / 1024 ); // this is the first of three processes. double relOverallWritten = ( ( double ) m_bytesFinishedTracks + ( double ) pos ) / ( double ) doc() ->size(); emit percent( ( int ) ( m_createimageonlypercent * relOverallWritten ) ); m_bytesFinished = pos; m_stage = stageScan; } else if ( oper == "write" ) { emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); emit processedSubSize( ( pos * 2048 ) / 1024 / 1024, ( size * 2048 ) / 1024 / 1024 ); emit percent( ( int ) ( m_createimageonlypercent + ( m_createimageonlypercent * ( double ) pos / ( double ) size ) ) ); m_stage = stageWrite; } else { return ; } } else if ( tagName == "log" ) { QDomText tel = el.firstChild().toText(); const QString level = el.attribute( "level" ).toLower(); if ( tel.isText() ) { const QString text = tel.data(); if ( m_stage == stageWrite && level == "information" ) qDebug() << QString( "(K3b::VcdJob) VcdxBuild information, %1" ).arg( text ); if ( ( text ).startsWith( "writing track" ) ) emit newSubTask( i18n( "Creating Image for track %1" , ( text ).mid( 14 ) ) ); else { if ( level != "error" ) { qDebug() << QString( "(K3b::VcdJob) vcdxbuild warning, %1" ).arg( text ); parseInformation( text ); } else { qDebug() << QString( "(K3b::VcdJob) vcdxbuild error, %1" ).arg( text ); emit infoMessage( text, K3b::Job::MessageError ); } } } } } }
void K3b::VcdJob::vcdxBuild() { emit newTask( i18n( "Creating image files" ) ); m_stage = stageUnknown; firstTrack = true; delete m_process; m_process = new K3b::Process(); m_process->setSplitStdout( true ); emit infoMessage( i18n( "Creating Cue/Bin files..." ), K3b::Job::MessageInfo ); const K3b::ExternalBin* bin = k3bcore ->externalBinManager() ->binObject( "vcdxbuild" ); if ( !bin ) { qDebug() << "(K3b::VcdJob) could not find vcdxbuild executable"; emit infoMessage( i18n( "Could not find %1 executable." , QString("vcdxbuild") ), K3b::Job::MessageError ); emit infoMessage( i18n( "To create Video CDs you have to install VcdImager version %1." ,QString( ">= 0.7.12") ), K3b::Job::MessageInfo ); emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3b::Job::MessageInfo ); cancelAll(); jobFinished( false ); return ; } if ( bin->version() < K3b::Version( "0.7.12" ) ) { qDebug() << "(K3b::VcdJob) vcdxbuild executable too old!"; emit infoMessage( i18n( "%1 executable too old: need version %2 or greater." ,QString( "Vcdxbuild" ),QString( "0.7.12" )), K3b::Job::MessageError ); emit infoMessage( i18n( "You can find this on your distribution disks or download it from http://www.vcdimager.org" ), K3b::Job::MessageInfo ); cancelAll(); jobFinished( false ); return ; } if ( !bin->copyright().isEmpty() ) emit infoMessage( i18n( "Using %1 %2 – Copyright © %3" , bin->name() , bin->version() ,bin->copyright() ), MessageInfo ); *m_process << bin; // additional user parameters from config const QStringList& params = k3bcore->externalBinManager() ->program( "vcdxbuild" ) ->userParameters(); for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *m_process << *it; if ( vcdDoc() ->vcdOptions() ->Sector2336() ) { qDebug() << "(K3b::VcdJob) Write 2336 Sectors = on"; *m_process << "--sector-2336"; } *m_process << "--progress" << "--gui"; *m_process << QString( "--cue-file=%1" ).arg( m_cueFile ); *m_process << QString( "--bin-file=%1" ).arg( m_doc->vcdImage() ); *m_process << d->xmlFile->fileName(); connect( m_process, SIGNAL(stdoutLine(QString)), this, SLOT(slotParseVcdxBuildOutput(QString)) ); connect( m_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotVcdxBuildFinished(int,QProcess::ExitStatus)) ); // vcdxbuild commandline parameters qDebug() << "***** vcdxbuild parameters:"; QString s = m_process->joinedArgs(); qDebug() << s << flush; emit debuggingOutput( "vcdxbuild command:", s ); if ( !m_process->start( KProcess::MergedChannels ) ) { qDebug() << "(K3b::VcdJob) could not start vcdxbuild"; emit infoMessage( i18n( "Could not start %1." , QString("vcdxbuild") ), K3b::Job::MessageError ); cancelAll(); jobFinished( false ); } }
void K3bGrowisofsWriter::start() { jobStarted(); d->lastWritingSpeed = 0; d->lastProgressed = 0; d->lastProgress = 0; d->firstSizeFromOutput = -1; d->lastSpeedCalculationTime = QTime::currentTime(); d->lastSpeedCalculationBytes = 0; d->writingStarted = false; d->canceled = false; d->speedEst->reset(); d->finished = false; if( !prepareProcess() ) { jobFinished( false ); } else { kdDebug() << "***** " << d->growisofsBin->name() << " parameters:\n"; const QValueList<QCString>& args = d->process->args(); QString s; for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << flush << endl; emit debuggingOutput( d->growisofsBin->name() + " command:", s); emit newSubTask( i18n("Preparing write process...") ); // FIXME: check the return value if( K3b::isMounted( burnDevice() ) ) { emit infoMessage( i18n("Unmounting medium"), INFO ); K3b::unmount( burnDevice() ); } // block the device (including certain checks) k3bcore->blockDevice( burnDevice() ); // lock the device for good in this process since it will // be opened in the growisofs process burnDevice()->close(); burnDevice()->usageLock(); if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { // something went wrong when starting the program // it "should" be the executable kdDebug() << "(K3bGrowisofsWriter) could not start " << d->growisofsBin->path << endl; emit infoMessage( i18n("Could not start %1.").arg(d->growisofsBin->name()), K3bJob::ERROR ); jobFinished(false); } else { if( simulate() ) { emit newTask( i18n("Simulating") ); emit infoMessage( i18n("Starting simulation..."), K3bJob::INFO ); } else { emit newTask( i18n("Writing") ); emit infoMessage( i18n("Starting disc write..."), K3bJob::INFO ); } d->gh->handleStart(); // create the ring buffer if( d->usingRingBuffer ) { if( !d->ringBuffer ) { d->ringBuffer = new K3bPipeBuffer( this, this ); connect( d->ringBuffer, SIGNAL(percent(int)), this, SIGNAL(buffer(int)) ); connect( d->ringBuffer, SIGNAL(finished(bool)), this, SLOT(slotRingBufferFinished(bool)) ); } d->ringBuffer->writeToFd( d->process->stdinFd() ); bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); int bufSize = ( manualBufferSize ? k3bcore->globalSettings()->bufferSize() : 20 ); d->ringBuffer->setBufferSize( bufSize ); if( !d->image.isEmpty() ) d->ringBuffer->readFromFd( d->inputFile.handle() ); d->ringBuffer->start(); } } }
void K3bIsoImager::slotCollectMkisofsPrintSizeStderr(KProcess*, char* data , int len) { emit debuggingOutput( "mkisofs", QString::fromLocal8Bit( data, len ) ); m_collectedMkisofsPrintSizeStderr.append( QString::fromLocal8Bit( data, len ) ); }
void K3bIsoImager::startSizeCalculation() { d->mkisofsBin = initMkisofs(); if( !d->mkisofsBin ) { jobFinished( false ); return; } initVariables(); delete m_process; m_process = new K3bProcess(); m_process->setRunPrivileged(true); m_process->setSplitStdout(true); emit debuggingOutput( "Used versions", "mkisofs: " + d->mkisofsBin->version ); *m_process << d->mkisofsBin; if( !prepareMkisofsFiles() || !addMkisofsParameters(true) ) { cleanup(); jobFinished( false ); return; } // add empty dummy dir since one path-spec is needed // ??? Seems it is not needed after all. At least mkisofs 1.14 and above don't need it. ??? // *m_process << dummyDir(); kdDebug() << "***** mkisofs calculate size parameters:\n"; const QValueList<QCString>& args = m_process->args(); QString s; for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << endl << flush; emit debuggingOutput("mkisofs calculate size command:", s); // since output changed during mkisofs version changes we grab both // stdout and stderr // mkisofs version >= 1.15 (don't know about 1.14!) // the extends on stdout (as lonely number) // and error and warning messages on stderr // mkisofs >= 1.13 // everything is written to stderr // last line is: "Total extents scheduled to be written = XXXXX" // TODO: use K3bProcess::OutputCollector instead iof our own two slots. connect( m_process, SIGNAL(receivedStderr(KProcess*, char*, int)), this, SLOT(slotCollectMkisofsPrintSizeStderr(KProcess*, char*, int)) ); connect( m_process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotCollectMkisofsPrintSizeStdout(const QString&)) ); connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(slotMkisofsPrintSizeFinished()) ); // we also want error messages connect( m_process, SIGNAL(stderrLine( const QString& )), this, SLOT(slotReceivedStderr( const QString& )) ); m_collectedMkisofsPrintSizeStdout = QString::null; m_collectedMkisofsPrintSizeStderr = QString::null; m_mkisofsPrintSizeResult = 0; if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { emit infoMessage( i18n("Could not start %1.").arg("mkisofs"), K3bJob::ERROR ); cleanup(); jobFinished( false ); return; } }
void K3bIsoImager::slotProcessExited( KProcess* p ) { kdDebug() << k_funcinfo << endl; m_processExited = true; d->pipe->close(); emit debuggingOutput( "K3bIsoImager", QString("Pipe throughput: %1 bytes read, %2 bytes written.") .arg(d->pipe->bytesRead()).arg(d->pipe->bytesWritten()) ); if( d->imageFile.isOpen() ) { d->imageFile.close(); if( m_canceled || p->exitStatus() != 0 ) { d->imageFile.remove(); emit infoMessage( i18n("Removed incomplete image file %1.").arg(d->imageFile.name()), WARNING ); } } if( m_canceled ) { emit canceled(); jobFinished(false); } else { if( p->normalExit() ) { if( p->exitStatus() == 0 ) { jobFinished( !mkisofsReadError() ); } else { switch( p->exitStatus() ) { case 104: // connection reset by peer // This only happens if cdrecord does not finish successfully // so we may leave the error handling to it meaning we handle this // as a known error break; case 2: // mkisofs seems to have a bug that prevents to use filenames // that contain one or more backslashes // mkisofs 1.14 has the bug, 1.15a40 not // TODO: find out the version that fixed the bug if( m_containsFilesWithMultibleBackslashes && !k3bcore->externalBinManager()->binObject( "mkisofs" )->hasFeature( "backslashed_filenames" ) ) { emit infoMessage( i18n("Due to a bug in mkisofs <= 1.15a40, K3b is unable to handle " "filenames that contain more than one backslash:"), ERROR ); break; } // otherwise just fall through default: if( !d->knownError && !mkisofsReadError() ) { emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg("mkisofs").arg(p->exitStatus()), K3bJob::ERROR ); emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); } } jobFinished( false ); } } else { emit infoMessage( i18n("%1 did not exit cleanly.").arg("mkisofs"), ERROR ); jobFinished( false ); } } cleanup(); }
void K3bIsoImager::slotReceivedStderr( const QString& line ) { parseMkisofsOutput( line ); emit debuggingOutput( "mkisofs", line ); }
void K3b::DvdFormattingJob::startFormatting( const Device::DiskInfo& diskInfo ) { // // Now check the media type: // if DVD-RW: use d->mode // emit warning if formatting is full and stuff // // in overwrite mode: emit info that progress might stop before 100% since formatting will continue // in the background once the media gets rewritten (only DVD+RW/BD-RE?) // // emit info about what kind of media has been found if( diskInfo.mediaType() & (Device::MEDIA_REWRITABLE_DVD | Device::MEDIA_BD_RE) ) { emit infoMessage( i18n("Found %1 medium.", Device::mediaTypeString(diskInfo.mediaType())), MessageInfo ); } else { emit infoMessage( i18n("No rewritable DVD or BD medium found. Unable to format."), MessageError ); d->running = false; jobFinished(false); return; } bool format = true; // do we need to format bool blank = false; // blank is for DVD-RW sequential incremental // DVD-RW restricted overwrite and DVD+RW uses the force option (or no option at all) // // DVD+RW/BD-RE is quite easy to handle. There is only one possible mode and it is always recommended to not // format it more than once but to overwrite it once it is formatted // Once the initial formatting has been done it's always "appendable" (or "complete"???) // if( diskInfo.mediaType() & (Device::MEDIA_DVD_PLUS_ALL | Device::MEDIA_BD_RE) ) { if( diskInfo.empty() ) { // // The DVD+RW/BD is blank and needs to be initially formatted // blank = false; } else { emit infoMessage( i18n("No need to format %1 media more than once.", Device::mediaTypeString(diskInfo.mediaType())), MessageInfo ); emit infoMessage( i18n("It may simply be overwritten."), MessageInfo ); if( d->force ) { emit infoMessage( i18n("Forcing formatting anyway."), MessageInfo ); emit infoMessage( i18n("It is not recommended to force formatting of %1 media.", Device::mediaTypeString(diskInfo.mediaType())), MessageInfo ); emit infoMessage( i18n("After 10-20 reformats the media might become unusable."), MessageInfo ); blank = false; } else { format = false; } } if( format ) emit newSubTask( i18n("Formatting %1 medium", Device::mediaTypeString(diskInfo.mediaType())) ); } // // DVD-RW has two modes: incremental sequential (the default which is also needed for DAO writing) // and restricted overwrite which compares to the DVD+RW mode. // else { // MEDIA_DVD_RW if( diskInfo.currentProfile() != Device::MEDIA_UNKNOWN ) { emit infoMessage( i18n("Formatted in %1 mode.",Device::mediaTypeString(diskInfo.currentProfile())), MessageInfo ); // // Is it possible to have an empty DVD-RW in restricted overwrite mode???? I don't think so. // if( diskInfo.empty() && (d->mode == WritingModeAuto || (d->mode == WritingModeIncrementalSequential && diskInfo.currentProfile() == Device::MEDIA_DVD_RW_SEQ) || (d->mode == WritingModeRestrictedOverwrite && diskInfo.currentProfile() == Device::MEDIA_DVD_RW_OVWR) ) ) { emit infoMessage( i18n("Media is already empty."), MessageInfo ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), MessageInfo ); else format = false; } else if( diskInfo.currentProfile() == Device::MEDIA_DVD_RW_OVWR && d->mode != WritingModeIncrementalSequential ) { emit infoMessage( i18n("No need to format %1 media more than once.", Device::mediaTypeString(diskInfo.currentProfile())), MessageInfo ); emit infoMessage( i18n("It may simply be overwritten."), MessageInfo ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), MessageInfo ); else format = false; } if( format ) { if( d->mode == WritingModeAuto ) { // just format in the same mode as the media is currently formatted blank = (diskInfo.currentProfile() == Device::MEDIA_DVD_RW_SEQ); } else { blank = (d->mode == WritingModeIncrementalSequential); } emit newSubTask( i18n("Formatting" " DVD-RW in %1 mode.",Device::mediaTypeString( blank ? Device::MEDIA_DVD_RW_SEQ : Device::MEDIA_DVD_RW_OVWR )) ); } } else { emit infoMessage( i18n("Unable to determine the current formatting state of the DVD-RW medium."), MessageError ); d->running = false; jobFinished(false); return; } } if( format ) { delete d->process; d->process = new Process(); connect( d->process, SIGNAL(stderrLine(QString)), this, SLOT(slotStderrLine(QString)) ); connect( d->process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotProcessFinished(int,QProcess::ExitStatus)) ); d->dvdFormatBin = k3bcore->externalBinManager()->binObject( "dvd+rw-format" ); if( !d->dvdFormatBin ) { emit infoMessage( i18n("Could not find %1 executable.",QString("dvd+rw-format")), MessageError ); d->running = false; jobFinished(false); return; } if( !d->dvdFormatBin->copyright().isEmpty() ) emit infoMessage( i18n("Using %1 %2 – Copyright © %3",d->dvdFormatBin->name(),d->dvdFormatBin->version(),d->dvdFormatBin->copyright()), MessageInfo ); *d->process << d->dvdFormatBin; if( d->dvdFormatBin->version() >= Version( 4, 6 ) ) *d->process << "-gui"; QString p; if( blank ) p = "-blank"; else p = "-force"; if( d->formattingMode == FormattingComplete ) p += "=full"; *d->process << p; *d->process << d->device->blockDeviceName(); // additional user parameters from config const QStringList& params = d->dvdFormatBin->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; qDebug() << "***** dvd+rw-format parameters:\n"; QString s = d->process->joinedArgs(); qDebug() << s << endl << flush; emit debuggingOutput( "dvd+rw-format command:", s ); if( !d->process->start( KProcess::OnlyStderrChannel ) ) { // something went wrong when starting the program // it "should" be the executable qDebug() << "(K3b::DvdFormattingJob) could not start " << d->dvdFormatBin->path(); emit infoMessage( i18n("Could not start %1.",d->dvdFormatBin->name()), Job::MessageError ); d->running = false; jobFinished(false); } else { emit newTask( i18n("Formatting") ); } } else {
void K3bDvdFormattingJob::startFormatting( const K3bDevice::DiskInfo& diskInfo ) { // // Now check the media type: // if DVD-RW: use d->mode // emit warning if formatting is full and stuff // // in overwrite mode: emit info that progress might stop before 100% since formatting will continue // in the background once the media gets rewritten (only DVD+RW?) // // emit info about what kind of media has been found if( !(diskInfo.mediaType() & (K3bDevice::MEDIA_DVD_RW| K3bDevice::MEDIA_DVD_RW_SEQ| K3bDevice::MEDIA_DVD_RW_OVWR| K3bDevice::MEDIA_DVD_PLUS_RW)) ) { emit infoMessage( i18n("No rewritable DVD media found. Unable to format."), ERROR ); d->running = false; jobFinished(false); return; } bool format = true; // do we need to format bool blank = false; // blank is for DVD-RW sequential incremental // DVD-RW restricted overwrite and DVD+RW uses the force option (or no option at all) // // DVD+RW is quite easy to handle. There is only one possible mode and it is always recommended to not // format it more than once but to overwrite it once it is formatted // Once the initial formatting has been done it's always "appendable" (or "complete"???) // if( diskInfo.mediaType() == K3bDevice::MEDIA_DVD_PLUS_RW ) { emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), INFO ); // mode is ignored if( diskInfo.empty() ) { // // The DVD+RW is blank and needs to be initially formatted // blank = false; } else { emit infoMessage( i18n("No need to format %1 media more than once.") .arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_PLUS_RW)), INFO ); emit infoMessage( i18n("It may simply be overwritten."), INFO ); if( d->force ) { emit infoMessage( i18n("Forcing formatting anyway."), INFO ); emit infoMessage( i18n("It is not recommended to force formatting of DVD+RW media."), INFO ); emit infoMessage( i18n("Already after 10-20 reformats the media might be unusable."), INFO ); blank = false; } else { format = false; } } if( format ) emit newSubTask( i18n("Formatting DVD+RW") ); } // // DVD-RW has two modes: incremental sequential (the default which is also needed for DAO writing) // and restricted overwrite which compares to the DVD+RW mode. // else { // MEDIA_DVD_RW emit infoMessage( i18n("Found %1 media.").arg(K3bDevice::mediaTypeString(K3bDevice::MEDIA_DVD_RW)), INFO ); if( diskInfo.currentProfile() != K3bDevice::MEDIA_UNKNOWN ) { emit infoMessage( i18n("Formatted in %1 mode.").arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); // // Is it possible to have an empty DVD-RW in restricted overwrite mode???? I don't think so. // if( diskInfo.empty() && (d->mode == K3b::WRITING_MODE_AUTO || (d->mode == K3b::WRITING_MODE_INCR_SEQ && diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ) || (d->mode == K3b::WRITING_MODE_RES_OVWR && diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR) ) ) { emit infoMessage( i18n("Media is already empty."), INFO ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), INFO ); else format = false; } else if( diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_OVWR && d->mode != K3b::WRITING_MODE_INCR_SEQ ) { emit infoMessage( i18n("No need to format %1 media more than once.") .arg(K3bDevice::mediaTypeString(diskInfo.currentProfile())), INFO ); emit infoMessage( i18n("It may simply be overwritten."), INFO ); if( d->force ) emit infoMessage( i18n("Forcing formatting anyway."), INFO ); else format = false; } if( format ) { if( d->mode == K3b::WRITING_MODE_AUTO ) { // just format in the same mode as the media is currently formatted blank = (diskInfo.currentProfile() == K3bDevice::MEDIA_DVD_RW_SEQ); } else { blank = (d->mode == K3b::WRITING_MODE_INCR_SEQ); } emit newSubTask( i18n("Formatting" " DVD-RW in %1 mode.").arg(K3bDevice::mediaTypeString( blank ? K3bDevice::MEDIA_DVD_RW_SEQ : K3bDevice::MEDIA_DVD_RW_OVWR )) ); } } else { emit infoMessage( i18n("Unable to determine the current formatting state of the DVD-RW media."), ERROR ); d->running = false; jobFinished(false); return; } } if( format ) { delete d->process; d->process = new K3bProcess(); d->process->setRunPrivileged(true); // d->process->setSuppressEmptyLines(false); connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotStderrLine(const QString&)) ); connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessFinished(KProcess*)) ); d->dvdFormatBin = k3bcore->externalBinManager()->binObject( "dvd+rw-format" ); if( !d->dvdFormatBin ) { emit infoMessage( i18n("Could not find %1 executable.").arg("dvd+rw-format"), ERROR ); d->running = false; jobFinished(false); return; } if( !d->dvdFormatBin->copyright.isEmpty() ) emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg(d->dvdFormatBin->name()).arg(d->dvdFormatBin->version).arg(d->dvdFormatBin->copyright), INFO ); *d->process << d->dvdFormatBin; if( d->dvdFormatBin->version >= K3bVersion( 4, 6 ) ) *d->process << "-gui"; QString p; if( blank ) p = "-blank"; else p = "-force"; if( !d->quick ) p += "=full"; *d->process << p; *d->process << d->device->blockDeviceName(); // additional user parameters from config const QStringList& params = d->dvdFormatBin->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; kdDebug() << "***** dvd+rw-format parameters:\n"; const QValueList<QCString>& args = d->process->args(); QString s; for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << endl << flush; emit debuggingOutput( "dvd+rw-format command:", s ); if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) { // something went wrong when starting the program // it "should" be the executable kdDebug() << "(K3bDvdFormattingJob) could not start " << d->dvdFormatBin->path << endl; emit infoMessage( i18n("Could not start %1.").arg(d->dvdFormatBin->name()), K3bJob::ERROR ); d->running = false; jobFinished(false); } else { emit newTask( i18n("Formatting") ); } } else {
void K3bIsoImager::start() { jobStarted(); cleanup(); d->mkisofsBin = initMkisofs(); if( !d->mkisofsBin ) { jobFinished( false ); return; } initVariables(); m_process = new K3bProcess(); m_process->setRunPrivileged(true); *m_process << d->mkisofsBin; // prepare the filenames as written to the image m_doc->prepareFilenames(); if( !prepareMkisofsFiles() || !addMkisofsParameters() ) { cleanup(); jobFinished( false ); return; } connect( m_process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); connect( m_process, SIGNAL(stderrLine( const QString& )), this, SLOT(slotReceivedStderr( const QString& )) ); // // Check the image file if( m_fdToWriteTo == -1 ) { d->imageFile.setName( d->imagePath ); if( !d->imageFile.open( IO_WriteOnly ) ) { emit infoMessage( i18n("Could not open %1 for writing").arg(d->imagePath), ERROR ); cleanup(); jobFinished(false); return; } } // // Open the active pipe which does the streaming delete d->pipe; if( m_doc->verifyData() ) d->pipe = new K3bChecksumPipe(); else d->pipe = new K3bActivePipe(); if( m_fdToWriteTo == -1 ) d->pipe->writeToIODevice( &d->imageFile ); else d->pipe->writeToFd( m_fdToWriteTo ); d->pipe->open(); m_process->writeToFd( d->pipe->in() ); kdDebug() << "***** mkisofs parameters:\n"; const QValueList<QCString>& args = m_process->args(); QString s; for( QValueList<QCString>::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << endl << flush; emit debuggingOutput("mkisofs command:", s); if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput) ) { // something went wrong when starting the program // it "should" be the executable kdDebug() << "(K3bIsoImager) could not start mkisofs" << endl; emit infoMessage( i18n("Could not start %1.").arg("mkisofs"), K3bJob::ERROR ); jobFinished( false ); cleanup(); } }
void K3b::Md5Job::stop() { emit debuggingOutput( "K3b::Md5Job", QString("Stopped manually after %1 bytes.").arg(d->readData) ); stopAll(); jobFinished( true ); }
bool K3bGrowisofsWriter::prepareProcess() { d->growisofsBin = k3bcore->externalBinManager()->binObject( "growisofs" ); if( !d->growisofsBin ) { emit infoMessage( i18n("Could not find %1 executable.").arg("growisofs"), ERROR ); return false; } if( d->growisofsBin->version < K3bVersion( 5, 10 ) ) { emit infoMessage( i18n("Growisofs version %1 is too old. " "K3b needs at least version 5.10.").arg(d->growisofsBin->version), ERROR ); return false; } emit debuggingOutput( "Used versions", "growisofs: " + d->growisofsBin->version ); if( !d->growisofsBin->copyright.isEmpty() ) emit infoMessage( i18n("Using %1 %2 - Copyright (C) %3").arg("growisofs") .arg(d->growisofsBin->version).arg(d->growisofsBin->copyright), INFO ); // // The growisofs bin is ready. Now we add the parameters // delete d->process; d->process = new K3bProcess(); d->process->setRunPrivileged(true); // d->process->setPriority( KProcess::PrioHighest ); d->process->setSplitStdout(true); d->process->setRawStdin(true); connect( d->process, SIGNAL(stderrLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); connect( d->process, SIGNAL(stdoutLine(const QString&)), this, SLOT(slotReceivedStderr(const QString&)) ); connect( d->process, SIGNAL(processExited(KProcess*)), this, SLOT(slotProcessExited(KProcess*)) ); // // growisofs < 5.20 wants the tracksize to be a multiple of 16 (1 ECC block: 16*2048 bytes) // we simply pad ourselves. // // But since the writer itself properly pads or writes a longer lead-out we don't really need // to write zeros. We just tell growisofs to reserve a multiple of 16 blocks. // This is only releveant in DAO mode anyway. // // FIXME: seems as we also need this for double layer writing. Better make it the default and // actually write the pad bytes. The only possibility I see right now is to add a padding option // to the pipebuffer. int trackSizePadding = 0; if( d->trackSize > 0 && d->growisofsBin->version < K3bVersion( 5, 20 ) ) { if( d->trackSize % 16 ) { trackSizePadding = (16 - d->trackSize%16); kdDebug() << "(K3bGrowisofsWriter) need to pad " << trackSizePadding << " blocks." << endl; } } *d->process << d->growisofsBin; // set this var to true to enable the ringbuffer d->usingRingBuffer = ( d->growisofsBin->version < K3bVersion( 6, 0 ) ); QString s = burnDevice()->blockDeviceName() + "="; if( d->usingRingBuffer || d->image.isEmpty() ) { // we always read from stdin since the ringbuffer does the actual reading from the source s += "/dev/fd/0"; } else s += d->image; if( d->multiSession && !d->multiSessionInfo.isEmpty() ) *d->process << "-C" << d->multiSessionInfo; if( d->multiSession ) *d->process << "-M"; else *d->process << "-Z"; *d->process << s; if( !d->image.isEmpty() && d->usingRingBuffer ) { d->inputFile.setName( d->image ); d->trackSize = (K3b::filesize( d->image ) + 1024) / 2048; if( !d->inputFile.open( IO_ReadOnly ) ) { emit infoMessage( i18n("Could not open file %1.").arg(d->image), ERROR ); return false; } } // now we use the force (luke ;) do not reload the dvd, K3b does that. *d->process << "-use-the-force-luke=notray"; // we check for existing filesystems ourselves, so we always force the overwrite... *d->process << "-use-the-force-luke=tty"; bool dvdCompat = d->closeDvd; // DL writing with forced layer break if( d->layerBreak > 0 ) { *d->process << "-use-the-force-luke=break:" + QString::number(d->layerBreak); dvdCompat = true; } // the tracksize parameter takes priority over the dao:tracksize parameter since growisofs 5.18 else if( d->growisofsBin->version > K3bVersion( 5, 17 ) && d->trackSize > 0 ) *d->process << "-use-the-force-luke=tracksize:" + QString::number(d->trackSize + trackSizePadding); if( simulate() ) *d->process << "-use-the-force-luke=dummy"; if( d->writingMode == K3b::DAO ) { dvdCompat = true; if( d->growisofsBin->version >= K3bVersion( 5, 15 ) && d->trackSize > 0 ) *d->process << "-use-the-force-luke=dao:" + QString::number(d->trackSize + trackSizePadding); else *d->process << "-use-the-force-luke=dao"; d->gh->reset( burnDevice(), true ); } else d->gh->reset( burnDevice(), false ); // // Never use the -dvd-compat parameter with DVD+RW media // because the only thing it does is creating problems. // Normally this should be done in growisofs // int mediaType = burnDevice()->mediaType(); if( dvdCompat && mediaType != K3bDevice::MEDIA_DVD_PLUS_RW && mediaType != K3bDevice::MEDIA_DVD_RW_OVWR ) *d->process << "-dvd-compat"; // // Some DVD writers do not allow changing the writing speed so we allow // the user to ignore the speed setting // int speed = burnSpeed(); if( speed >= 0 ) { if( speed == 0 ) { // try to determine the writeSpeed // if it fails determineOptimalWriteSpeed() will return 0 and // the choice is left to growisofs which means that the choice is // really left to the drive since growisofs does not change the speed // if no option is given speed = burnDevice()->determineMaximalWriteSpeed(); } // speed may be a float number. example: DVD+R(W): 2.4x if( speed != 0 ) *d->process << QString("-speed=%1").arg( speed%1385 > 0 ? QString::number( (float)speed/1385.0, 'f', 1 ) : QString::number( speed/1385 ) ); } if( k3bcore->globalSettings()->overburn() ) *d->process << "-overburn"; if( !d->usingRingBuffer && d->growisofsBin->version >= K3bVersion( 6, 0 ) ) { bool manualBufferSize = k3bcore->globalSettings()->useManualBufferSize(); int bufSize = ( manualBufferSize ? k3bcore->globalSettings()->bufferSize() : 32 ); *d->process << QString("-use-the-force-luke=bufsize:%1m").arg(bufSize); } // additional user parameters from config const QStringList& params = d->growisofsBin->userParameters(); for( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; emit debuggingOutput( "Burned media", K3bDevice::mediaTypeString(mediaType) ); return true; }
void K3b::IsoImager::startSizeCalculation() { d->mkisofsBin = initMkisofs(); if( !d->mkisofsBin ) { jobFinished( false ); return; } initVariables(); delete m_process; m_process = new K3b::Process( this ); m_process->setSplitStdout(true); emit debuggingOutput( QLatin1String( "Used versions" ), QString::fromLatin1( "mkisofs: %1").arg(d->mkisofsBin->version()) ); *m_process << d->mkisofsBin; if( !prepareMkisofsFiles() || !addMkisofsParameters(true) ) { cleanup(); jobFinished( false ); return; } // add empty dummy dir since one path-spec is needed // ??? Seems it is not needed after all. At least mkisofs 1.14 and above don't need it. ??? // *m_process << dummyDir(); qDebug() << "***** mkisofs calculate size parameters:"; QString s = m_process->joinedArgs(); qDebug() << s << endl << flush; emit debuggingOutput("mkisofs calculate size command:", s); // since output changed during mkisofs version changes we grab both // stdout and stderr // mkisofs version >= 1.15 (don't know about 1.14!) // the extends on stdout (as lonely number) // and error and warning messages on stderr // mkisofs >= 1.13 // everything is written to stderr // last line is: "Total extents scheduled to be written = XXXXX" connect( m_process, SIGNAL(stdoutLine(QString)), this, SLOT(slotCollectMkisofsPrintSizeStdout(QString)) ); connect( m_process, SIGNAL(stderrLine(QString)), this, SLOT(slotCollectMkisofsPrintSizeStderr(QString)) ); connect( m_process, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotMkisofsPrintSizeFinished()) ); // we also want error messages connect( m_process, SIGNAL(stderrLine(QString)), this, SLOT(slotReceivedStderr(QString)) ); m_collectedMkisofsPrintSizeStdout = QString(); m_collectedMkisofsPrintSizeStderr = QString(); m_mkisofsPrintSizeResult = 0; if( !m_process->start( KProcess::SeparateChannels ) ) { emit infoMessage( i18n("Could not start %1.",QString("mkisofs")), K3b::Job::MessageError ); cleanup(); jobFinished( false ); return; } }