File indexing completed on 2024-05-12 04:51:10
0001 /* 0002 SPDX-FileCopyrightText: 2003-2004 Christian Kvasny <chris@k3b.org> 0003 SPDX-FileCopyrightText: 2007-2009 Sebastian Trueg <trueg@k3b.org> 0004 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "k3bvcdjob.h" 0010 #include "k3bvcddoc.h" 0011 #include "k3bvcdtrack.h" 0012 #include "k3bvcdxmlview.h" 0013 #include "k3bcore.h" 0014 #include "k3bdoc.h" 0015 #include "k3bprocess.h" 0016 #include "k3bdevice.h" 0017 #include "k3bexternalbinmanager.h" 0018 #include "k3bglobals.h" 0019 #include "k3bcdrecordwriter.h" 0020 #include "k3bcdrdaowriter.h" 0021 #include "k3bglobalsettings.h" 0022 #include "k3bdevicehandler.h" 0023 #include "k3b_i18n.h" 0024 0025 #include <KConfig> 0026 #include <KIO/Global> 0027 0028 #include <QString> 0029 #include <QDateTime> 0030 #include <QFile> 0031 #include <QTemporaryFile> 0032 #include <QTimer> 0033 #include <QDebug> 0034 #include <QRegularExpression> 0035 #include <QUrl> 0036 #include <QDomDocument> 0037 0038 0039 class K3b::VcdJob::Private 0040 { 0041 public: 0042 QTemporaryFile* xmlFile; 0043 }; 0044 0045 0046 K3b::VcdJob::VcdJob( K3b::VcdDoc* doc, K3b::JobHandler* jh, QObject* parent ) 0047 : K3b::BurnJob( jh, parent ), 0048 d( new Private ) 0049 { 0050 d->xmlFile = 0; 0051 0052 m_doc = doc; 0053 m_doc->setCopies( m_doc->dummy() || m_doc->onlyCreateImages() ? 1 : m_doc->copies() ); 0054 m_process = 0; 0055 m_currentWrittenTrackNumber = 0; 0056 m_bytesFinishedTracks = 0; 0057 m_writerJob = 0; 0058 // m_createimageonlypercent = 33.3; 0059 m_createimageonlypercent = 100 / ( m_doc->copies() + 2 ); 0060 m_currentcopy = 1; 0061 m_imageFinished = false; 0062 } 0063 0064 0065 K3b::VcdJob::~VcdJob() 0066 { 0067 delete d->xmlFile; 0068 delete d; 0069 0070 delete m_process; 0071 0072 delete m_writerJob; 0073 } 0074 0075 0076 K3b::Doc* K3b::VcdJob::doc() const 0077 { 0078 return m_doc; 0079 } 0080 0081 0082 K3b::Device::Device* K3b::VcdJob::writer() const 0083 { 0084 if( doc()->onlyCreateImages() ) 0085 return 0; 0086 else 0087 return doc() ->burner(); 0088 } 0089 0090 void K3b::VcdJob::cancel() 0091 { 0092 cancelAll(); 0093 0094 emit canceled(); 0095 jobFinished( false ); 0096 } 0097 0098 0099 void K3b::VcdJob::cancelAll() 0100 { 0101 m_canceled = true; 0102 0103 if ( m_writerJob ) 0104 m_writerJob->cancel(); 0105 0106 if ( m_process->isRunning() ) { 0107 m_process->disconnect( this ); 0108 m_process->terminate(); 0109 } 0110 0111 // remove bin-file if it is unfinished or the user selected to remove image 0112 if ( QFile::exists( m_doc->vcdImage() ) ) { 0113 if ( (!m_doc->onTheFly() && m_doc->removeImages()) || !m_imageFinished ) { 0114 emit infoMessage( i18n( "Removing Binary file %1" , m_doc->vcdImage() ), K3b::Job::MessageSuccess ); 0115 QFile::remove 0116 ( m_doc->vcdImage() ); 0117 m_doc->setVcdImage( "" ); 0118 } 0119 } 0120 0121 // remove cue-file if it is unfinished or the user selected to remove image 0122 if ( QFile::exists( m_cueFile ) ) { 0123 if ( (!m_doc->onTheFly() && m_doc->removeImages()) || !m_imageFinished ) { 0124 emit infoMessage( i18n( "Removing Cue file %1" , m_cueFile ), K3b::Job::MessageSuccess ); 0125 QFile::remove 0126 ( m_cueFile ); 0127 m_cueFile = ""; 0128 } 0129 } 0130 } 0131 0132 0133 void K3b::VcdJob::start() 0134 { 0135 qDebug() << "(K3b::VcdJob) starting job"; 0136 0137 jobStarted(); 0138 emit burning( false ); 0139 m_canceled = false; 0140 0141 int pos = QString( m_doc->vcdImage() ).indexOf( ".bin", QString( m_doc->vcdImage() ).length() - 4 ); 0142 if ( pos > 0 ) { 0143 m_cueFile = m_doc->vcdImage().left( pos ) + ".cue"; 0144 } else { 0145 m_cueFile = m_doc->vcdImage() + ".cue"; 0146 m_doc->setVcdImage( m_doc->vcdImage() + ".bin" ); 0147 } 0148 0149 if ( vcdDoc() ->onlyCreateImages() ) 0150 m_createimageonlypercent = 50.0; 0151 0152 // vcdxGen(); 0153 xmlGen(); 0154 } 0155 0156 void K3b::VcdJob::xmlGen() 0157 { 0158 delete d->xmlFile; 0159 d->xmlFile = new QTemporaryFile; 0160 0161 if( d->xmlFile->open() ) { 0162 qDebug() << "(K3b::VcdJob) writing XML data to" << d->xmlFile->fileName(); 0163 0164 K3b::VcdXmlView xmlView( m_doc ); 0165 xmlView.write( *d->xmlFile ); 0166 0167 // emit infoMessage( i18n( "XML-file successfully created" ), K3b::Job::MessageSuccess ); 0168 emit debuggingOutput( "K3b::VcdXml:", xmlView.xmlString() ); 0169 0170 vcdxBuild(); 0171 } 0172 else { 0173 qDebug() << "(K3b::VcdJob) could not write xmlfile."; 0174 emit infoMessage( i18n( "Could not write correct XML file." ), K3b::Job::MessageError ); 0175 cancelAll(); 0176 jobFinished( false ); 0177 } 0178 } 0179 0180 void K3b::VcdJob::vcdxBuild() 0181 { 0182 emit newTask( i18n( "Creating image files" ) ); 0183 0184 m_stage = stageUnknown; 0185 firstTrack = true; 0186 delete m_process; 0187 m_process = new K3b::Process(); 0188 m_process->setSplitStdout( true ); 0189 0190 emit infoMessage( i18n( "Creating Cue/Bin files..." ), K3b::Job::MessageInfo ); 0191 const K3b::ExternalBin* bin = k3bcore ->externalBinManager() ->binObject( "vcdxbuild" ); 0192 if ( !bin ) { 0193 qDebug() << "(K3b::VcdJob) could not find vcdxbuild executable"; 0194 emit infoMessage( i18n( "Could not find %1 executable." , QString("vcdxbuild") ), K3b::Job::MessageError ); 0195 emit infoMessage( i18n( "To create Video CDs you have to install VcdImager version %1." ,QString( ">= 0.7.12") ), K3b::Job::MessageInfo ); 0196 emit infoMessage( i18n( "You can find this on your distribution disks or download it from https://www.gnu.org/software/vcdimager" ), K3b::Job::MessageInfo ); 0197 cancelAll(); 0198 jobFinished( false ); 0199 return ; 0200 } 0201 0202 if ( bin->version() < K3b::Version( "0.7.12" ) ) { 0203 qDebug() << "(K3b::VcdJob) vcdxbuild executable too old!"; 0204 emit infoMessage( i18n( "%1 executable too old: need version %2 or greater." ,QString( "Vcdxbuild" ),QString( "0.7.12" )), K3b::Job::MessageError ); 0205 emit infoMessage( i18n( "You can find this on your distribution disks or download it from https://www.gnu.org/software/vcdimager" ), K3b::Job::MessageInfo ); 0206 cancelAll(); 0207 jobFinished( false ); 0208 return ; 0209 } 0210 0211 if ( !bin->copyright().isEmpty() ) 0212 emit infoMessage( i18n( "Using %1 %2 – Copyright © %3" , bin->name() , bin->version() ,bin->copyright() ), MessageInfo ); 0213 0214 *m_process << bin; 0215 0216 // additional user parameters from config 0217 const QStringList& params = k3bcore->externalBinManager() ->program( "vcdxbuild" ) ->userParameters(); 0218 for ( QStringList::const_iterator it = params.begin(); it != params.end(); ++it ) 0219 *m_process << *it; 0220 0221 0222 if ( vcdDoc() ->vcdOptions() ->Sector2336() ) { 0223 qDebug() << "(K3b::VcdJob) Write 2336 Sectors = on"; 0224 *m_process << "--sector-2336"; 0225 } 0226 0227 *m_process << "--progress" << "--gui"; 0228 0229 *m_process << QString( "--cue-file=%1" ).arg( m_cueFile ); 0230 0231 *m_process << QString( "--bin-file=%1" ).arg( m_doc->vcdImage() ); 0232 0233 *m_process << d->xmlFile->fileName(); 0234 0235 connect( m_process, SIGNAL(stdoutLine(QString)), 0236 this, SLOT(slotParseVcdxBuildOutput(QString)) ); 0237 connect( m_process, SIGNAL(finished(int,QProcess::ExitStatus)), 0238 this, SLOT(slotVcdxBuildFinished(int,QProcess::ExitStatus)) ); 0239 0240 // vcdxbuild commandline parameters 0241 qDebug() << "***** vcdxbuild parameters:"; 0242 QString s = m_process->joinedArgs(); 0243 qDebug() << s << Qt::flush; 0244 emit debuggingOutput( "vcdxbuild command:", s ); 0245 0246 if ( !m_process->start( KProcess::MergedChannels ) ) { 0247 qDebug() << "(K3b::VcdJob) could not start vcdxbuild"; 0248 emit infoMessage( i18n( "Could not start %1." , QString("vcdxbuild") ), K3b::Job::MessageError ); 0249 cancelAll(); 0250 jobFinished( false ); 0251 } 0252 } 0253 0254 void K3b::VcdJob::slotParseVcdxBuildOutput( const QString& line ) 0255 { 0256 QDomDocument xml_doc; 0257 QDomElement xml_root; 0258 0259 QString str = line.trimmed(); 0260 0261 emit debuggingOutput( "vcdxbuild", str ); 0262 0263 xml_doc.setContent( QString( "<?xml version='1.0'?><vcdxbuild>" ) + str + "</vcdxbuild>" ); 0264 0265 xml_root = xml_doc.documentElement(); 0266 0267 // There should be only one... but ... 0268 for ( QDomNode node = xml_root.firstChild(); !node.isNull(); node = node.nextSibling() ) { 0269 QDomElement el = node.toElement(); 0270 if ( el.isNull() ) 0271 continue; 0272 0273 const QString tagName = el.tagName().toLower(); 0274 0275 if ( tagName == "progress" ) { 0276 const QString oper = el.attribute( "operation" ).toLower(); 0277 const unsigned long long pos = el.attribute( "position" ).toLong(); 0278 const long long size = el.attribute( "size" ).toLong(); 0279 0280 if ( oper == "scan" ) { 0281 // Scan Video Files 0282 if ( m_stage == stageUnknown || pos < m_bytesFinished ) { 0283 static const QRegularExpression rx( "sequence-" ); 0284 const uint index = el.attribute( "id" ).remove( rx ).toUInt(); 0285 0286 m_currentWrittenTrack = m_doc->at( m_currentWrittenTrackNumber ); 0287 emit newSubTask( i18n( "Scanning video file %1 of %2 (%3)" , index + 1 , doc() ->numOfTracks() , m_currentWrittenTrack->fileName() ) ); 0288 m_bytesFinished = 0; 0289 0290 if ( !firstTrack ) { 0291 m_bytesFinishedTracks += m_doc->at( m_currentWrittenTrackNumber ) ->size(); 0292 m_currentWrittenTrackNumber++; 0293 } else 0294 firstTrack = false; 0295 } 0296 emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); 0297 emit processedSubSize( pos / 1024 / 1024, size / 1024 / 1024 ); 0298 0299 // this is the first of three processes. 0300 double relOverallWritten = ( ( double ) m_bytesFinishedTracks + ( double ) pos ) / ( double ) doc() ->size(); 0301 emit percent( ( int ) ( m_createimageonlypercent * relOverallWritten ) ); 0302 0303 m_bytesFinished = pos; 0304 m_stage = stageScan; 0305 0306 } else if ( oper == "write" ) { 0307 emit subPercent( ( int ) ( 100.0 * ( double ) pos / ( double ) size ) ); 0308 emit processedSubSize( ( pos * 2048 ) / 1024 / 1024, ( size * 2048 ) / 1024 / 1024 ); 0309 emit percent( ( int ) ( m_createimageonlypercent + ( m_createimageonlypercent * ( double ) pos / ( double ) size ) ) ); 0310 0311 m_stage = stageWrite; 0312 } else { 0313 return ; 0314 } 0315 } else if ( tagName == "log" ) { 0316 QDomText tel = el.firstChild().toText(); 0317 const QString level = el.attribute( "level" ).toLower(); 0318 if ( tel.isText() ) { 0319 const QString text = tel.data(); 0320 if ( m_stage == stageWrite && level == "information" ) 0321 qDebug() << QString( "(K3b::VcdJob) VcdxBuild information, %1" ).arg( text ); 0322 if ( ( text ).startsWith( "writing track" ) ) 0323 emit newSubTask( i18n( "Creating Image for track %1" , ( text ).mid( 14 ) ) ); 0324 else { 0325 if ( level != "error" ) { 0326 qDebug() << QString( "(K3b::VcdJob) vcdxbuild warning, %1" ).arg( text ); 0327 parseInformation( text ); 0328 } else { 0329 qDebug() << QString( "(K3b::VcdJob) vcdxbuild error, %1" ).arg( text ); 0330 emit infoMessage( text, K3b::Job::MessageError ); 0331 } 0332 } 0333 } 0334 } 0335 } 0336 } 0337 0338 0339 void K3b::VcdJob::slotVcdxBuildFinished( int exitCode, QProcess::ExitStatus exitStatus ) 0340 { 0341 if ( exitStatus == QProcess::NormalExit ) { 0342 // TODO: check the process' exitStatus() 0343 switch ( exitCode ) { 0344 case 0: 0345 emit infoMessage( i18n( "Cue/Bin files successfully created." ), K3b::Job::MessageSuccess ); 0346 m_imageFinished = true; 0347 break; 0348 default: 0349 emit infoMessage( i18n( "%1 returned an unknown error (code %2)." , QString("vcdxbuild") , exitCode ), 0350 K3b::Job::MessageError ); 0351 emit infoMessage( i18n( "Please send me an email with the last output." ), K3b::Job::MessageError ); 0352 cancelAll(); 0353 jobFinished( false ); 0354 return ; 0355 } 0356 } else { 0357 emit infoMessage( i18n( "%1 did not exit cleanly." , QString("Vcdxbuild") ), K3b::Job::MessageError ); 0358 cancelAll(); 0359 jobFinished( false ); 0360 return ; 0361 } 0362 0363 //remove xml-file 0364 delete d->xmlFile; 0365 d->xmlFile = 0; 0366 0367 qDebug() << QString( "(K3b::VcdJob) create only image: %1" ).arg( vcdDoc() ->onlyCreateImages() ); 0368 if ( !vcdDoc() ->onlyCreateImages() ) 0369 startWriterjob(); 0370 else 0371 jobFinished( true ); 0372 } 0373 0374 0375 void K3b::VcdJob::startWriterjob() 0376 { 0377 qDebug() << QString( "(K3b::VcdJob) writing copy %1 of %2" ).arg( m_currentcopy ).arg( m_doc->copies() ); 0378 if ( prepareWriterJob() ) { 0379 if ( waitForMedium( m_doc->burner() ) == Device::MEDIA_UNKNOWN ) { 0380 cancel(); 0381 return ; 0382 } 0383 // just to be sure we did not get canceled during the async discWaiting 0384 if ( m_canceled ) 0385 return ; 0386 0387 if ( m_doc->copies() > 1 ) 0388 emit newTask( i18n( "Writing Copy %1 of %2" , m_currentcopy , m_doc->copies() ) ); 0389 0390 emit burning( true ); 0391 m_writerJob->start(); 0392 } 0393 } 0394 0395 bool K3b::VcdJob::prepareWriterJob() 0396 { 0397 if ( m_writerJob ) 0398 delete m_writerJob; 0399 0400 const K3b::ExternalBin* cdrecordBin = k3bcore->externalBinManager() ->binObject( "cdrecord" ); 0401 if ( writingApp() == K3b::WritingAppAuto && cdrecordBin->hasFeature( "cuefile" ) && m_doc->burner() ->dao() ) 0402 setWritingApp( K3b::WritingAppCdrecord ); 0403 0404 if ( writingApp() == K3b::WritingAppCdrdao || writingApp() == K3b::WritingAppAuto ) { 0405 K3b::CdrdaoWriter * writer = new K3b::CdrdaoWriter( m_doc->burner(), this, this ); 0406 // create cdrdao job 0407 writer->setCommand( K3b::CdrdaoWriter::WRITE ); 0408 writer->setSimulate( m_doc->dummy() ); 0409 writer->setBurnSpeed( m_doc->speed() ); 0410 0411 writer->setTocFile( m_cueFile ); 0412 0413 m_writerJob = writer; 0414 0415 } else if ( writingApp() == K3b::WritingAppCdrecord ) { 0416 K3b::CdrecordWriter * writer = new K3b::CdrecordWriter( m_doc->burner(), this, this ); 0417 // create cdrecord job 0418 0419 writer->setSimulate( m_doc->dummy() ); 0420 writer->setBurnSpeed( m_doc->speed() ); 0421 writer->setDao( true ); 0422 writer->setCueFile( m_cueFile ); 0423 0424 m_writerJob = writer; 0425 0426 } 0427 0428 connect( m_writerJob, SIGNAL(infoMessage(QString,int)), this, SIGNAL(infoMessage(QString,int)) ); 0429 connect( m_writerJob, SIGNAL(percent(int)), this, SLOT(slotWriterJobPercent(int)) ); 0430 connect( m_writerJob, SIGNAL(processedSize(int,int)), this, SLOT(slotProcessedSize(int,int)) ); 0431 connect( m_writerJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); 0432 connect( m_writerJob, SIGNAL(processedSubSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); 0433 connect( m_writerJob, SIGNAL(nextTrack(int,int)), this, SLOT(slotWriterNextTrack(int,int)) ); 0434 connect( m_writerJob, SIGNAL(buffer(int)), this, SIGNAL(bufferStatus(int)) ); 0435 connect( m_writerJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); 0436 connect( m_writerJob, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)) ); 0437 connect( m_writerJob, SIGNAL(finished(bool)), this, SLOT(slotWriterJobFinished(bool)) ); 0438 connect( m_writerJob, SIGNAL(newTask(QString)), this, SIGNAL(newTask(QString)) ); 0439 connect( m_writerJob, SIGNAL(newSubTask(QString)), this, SIGNAL(newSubTask(QString)) ); 0440 connect( m_writerJob, SIGNAL(debuggingOutput(QString,QString)), this, SIGNAL(debuggingOutput(QString,QString)) ); 0441 0442 return true; 0443 } 0444 0445 void K3b::VcdJob::slotWriterJobPercent( int p ) 0446 { 0447 emit percent( ( int ) ( ( m_createimageonlypercent * ( m_currentcopy + 1 ) ) + p / ( m_doc->copies() + 2 ) ) ); 0448 } 0449 0450 void K3b::VcdJob::slotProcessedSize( int cs, int ts ) 0451 { 0452 emit processedSize( cs + ( ts * ( m_currentcopy - 1 ) ) , ts * m_doc->copies() ); 0453 } 0454 0455 void K3b::VcdJob::slotWriterNextTrack( int t, int tt ) 0456 { 0457 emit newSubTask( i18n( "Writing Track %1 of %2" , t , tt ) ); 0458 } 0459 0460 void K3b::VcdJob::slotWriterJobFinished( bool success ) 0461 { 0462 if ( m_canceled ) 0463 return ; 0464 0465 if ( m_currentcopy >= m_doc->copies() ) { 0466 // remove bin-file if it is unfinished or the user selected to remove image 0467 if ( QFile::exists( m_doc->vcdImage() ) ) { 0468 if ( (!m_doc->onTheFly() && m_doc->removeImages()) || !m_imageFinished ) { 0469 emit infoMessage( i18n( "Removing Binary file %1" , m_doc->vcdImage() ), K3b::Job::MessageSuccess ); 0470 QFile::remove 0471 ( m_doc->vcdImage() ); 0472 m_doc->setVcdImage( "" ); 0473 } 0474 } 0475 0476 // remove cue-file if it is unfinished or the user selected to remove image 0477 if ( QFile::exists( m_cueFile ) ) { 0478 if ( (!m_doc->onTheFly() && m_doc->removeImages()) || !m_imageFinished ) { 0479 emit infoMessage( i18n( "Removing Cue file %1" , m_cueFile ), K3b::Job::MessageSuccess ); 0480 QFile::remove 0481 ( m_cueFile ); 0482 m_cueFile = ""; 0483 } 0484 } 0485 } 0486 0487 if ( success ) { 0488 // alright 0489 // the writerJob should have emitted the "simulation/writing successful" signal 0490 if ( m_currentcopy >= m_doc->copies() ) { 0491 if ( k3bcore->globalSettings()->ejectMedia() ) { 0492 K3b::Device::eject( m_doc->burner() ); 0493 } 0494 jobFinished( true ); 0495 } else { 0496 if( !K3b::eject( m_doc->burner() ) ) { 0497 blockingInformation( i18n("K3b was unable to eject the written disk. Please do so manually.") ); 0498 } 0499 m_currentcopy++; 0500 startWriterjob(); 0501 } 0502 } else { 0503 cancelAll(); 0504 jobFinished( false ); 0505 } 0506 } 0507 0508 void K3b::VcdJob::parseInformation( const QString &text ) 0509 { 0510 // parse warning 0511 if ( text.contains( "mpeg user scan data: one or more BCD fields out of range for" ) ) { 0512 int index = text.indexOf( " for" ); 0513 0514 emit infoMessage( i18n( "One or more BCD fields out of range for %1" , text.mid( index + 4 ).trimmed() ), K3b::Job::MessageWarning ); 0515 0516 } else if ( text.contains( "mpeg user scan data: from now on, scan information data errors will not be reported anymore" ) ) { 0517 emit infoMessage( i18n( "From now on, scan information data errors will not be reported anymore" ), K3b::Job::MessageInfo ); 0518 emit infoMessage( i18n( "Consider enabling the 'update scan offsets' option, if it is not enabled already." ), K3b::Job::MessageInfo ); 0519 0520 } else if ( text.contains( "APS' pts seems out of order (actual pts" ) ) { 0521 int index = text.indexOf( "(actual pts" ); 0522 int index2 = text.indexOf( ", last seen pts" ); 0523 int index3 = text.indexOf( ") -- ignoring this aps" ); 0524 0525 emit infoMessage( i18n( "APS' pts seems out of order (actual pts %1, last seen pts %2)" , text.mid( index + 12, index2 - index - 12 ).trimmed() , text.mid( index2 + 14, index3 - index2 - 14 ).trimmed() ), K3b::Job::MessageWarning ); 0526 emit infoMessage( i18n( "Ignoring this aps" ), K3b::Job::MessageInfo ); 0527 0528 } else if ( text.contains( "bad packet at packet" ) ) { 0529 int index = text.indexOf( "at packet #" ); 0530 int index2 = text.indexOf( "(stream byte offset" ); 0531 int index3 = text.indexOf( ") -- remaining " ); 0532 int index4 = text.indexOf( "bytes of stream will be ignored" ); 0533 0534 emit infoMessage( i18n( "Bad packet at packet #%1 (stream byte offset %2)" , text.mid( index + 11, index2 - index - 11 ).trimmed() , text.mid( index2 + 19, index3 - index2 - 19 ).trimmed() ), K3b::Job::MessageWarning ); 0535 0536 const QString ignoredString = text.mid( index3 + 15, index4 - index3 - 15 ).trimmed(); 0537 bool okay = true; 0538 const int ignoredBytes = ignoredString.toInt(&okay); 0539 0540 if (okay) { 0541 emit infoMessage( i18np( "The remaining byte of the stream will be ignored.", "The remaining %1 bytes of the stream will be ignored." , ignoredBytes ), K3b::Job::MessageWarning ); 0542 } else { 0543 emit infoMessage( i18n( "An unknown number of remaining stream bytes will be ignored." ), K3b::Job::MessageWarning ); 0544 } 0545 } 0546 } 0547 0548 QString K3b::VcdJob::jobDescription() const 0549 { 0550 switch ( m_doc->vcdType() ) { 0551 case K3b::VcdDoc::VCD11: 0552 return i18n( "Writing Video CD (Version 1.1)" ); 0553 case K3b::VcdDoc::VCD20: 0554 return i18n( "Writing Video CD (Version 2.0)" ); 0555 case K3b::VcdDoc::SVCD10: 0556 return i18n( "Writing Super Video CD" ); 0557 case K3b::VcdDoc::HQVCD: 0558 return i18n( "Writing High-Quality Video CD" ); 0559 default: 0560 return i18n( "Writing Video CD" ); 0561 } 0562 } 0563 0564 0565 QString K3b::VcdJob::jobDetails() const 0566 { 0567 return ( i18np( "1 MPEG (%2)", 0568 "%1 MPEGs (%2)", 0569 m_doc->tracks() ->count(), KIO::convertSize( m_doc->size() ) ) 0570 + ( m_doc->copies() > 1 0571 ? i18np( " - %1 copy", " - %1 copies", m_doc->copies() ) 0572 : QString() ) ); 0573 } 0574 0575 #include "moc_k3bvcdjob.cpp"