/* * * $Id: k3bdvdformattingjob.cpp 696897 2007-08-06 07:14:14Z trueg $ * Copyright (C) 2003 Sebastian Trueg * * This file is part of the K3b project. * Copyright (C) 1998-2007 Sebastian Trueg * * 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 "k3bdvdformattingjob.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class K3bDvdFormattingJob::Private { public: Private() : quick(false), force(false), mode(K3b::WRITING_MODE_AUTO), device(0), process(0), dvdFormatBin(0), lastProgressValue(0), running(false), forceNoEject(false) { } bool quick; bool force; int mode; K3bDevice::Device* device; K3bProcess* process; const K3bExternalBin* dvdFormatBin; int lastProgressValue; bool success; bool canceled; bool running; bool forceNoEject; bool error; }; K3bDvdFormattingJob::K3bDvdFormattingJob( K3bJobHandler* jh, TQObject* parent, const char* name ) : K3bBurnJob( jh, parent, name ) { d = new Private; } K3bDvdFormattingJob::~K3bDvdFormattingJob() { delete d->process; delete d; } K3bDevice::Device* K3bDvdFormattingJob::writer() const { return d->device; } void K3bDvdFormattingJob::setForceNoEject( bool b ) { d->forceNoEject = b; } TQString K3bDvdFormattingJob::jobDescription() const { return i18n("Formatting DVD"); // Formatting DVD±RW } TQString K3bDvdFormattingJob::jobDetails() const { if( d->quick ) return i18n("Quick Format"); else return TQString(); } void K3bDvdFormattingJob::start() { d->canceled = false; d->running = true; d->error = false; jobStarted(); if( !d->device ) { emit infoMessage( i18n("No device set"), ERROR ); d->running = false; jobFinished(false); return; } // FIXME: check the return value if( K3b::isMounted( d->device ) ) { emit infoMessage( i18n("Unmounting medium"), INFO ); K3b::unmount( d->device ); } // // first wait for a dvd+rw or dvd-rw // Be aware that an empty DVD-RW might be reformatted to another writing mode // so we also wait for empty dvds // if( waitForMedia( d->device, K3bDevice::STATE_COMPLETE|K3bDevice::STATE_INCOMPLETE|K3bDevice::STATE_EMPTY, K3bDevice::MEDIA_WRITABLE_DVD, i18n("Please insert a rewritable DVD medium into drive

%1 %2 (%3).") .arg(d->device->vendor()).arg(d->device->description()).arg(d->device->devicename()) ) == -1 ) { emit canceled(); d->running = false; jobFinished(false); return; } emit infoMessage( i18n("Checking media..."), INFO ); emit newTask( i18n("Checking media") ); connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, d->device ), TQT_SIGNAL(finished(K3bDevice::DeviceHandler*)), this, TQT_SLOT(slotDeviceHandlerFinished(K3bDevice::DeviceHandler*)) ); } void K3bDvdFormattingJob::start( const K3bDevice::DiskInfo& di ) { d->canceled = false; d->running = true; jobStarted(); startFormatting( di ); } void K3bDvdFormattingJob::cancel() { if( d->running ) { d->canceled = true; if( d->process ) d->process->kill(); } else { kdDebug() << "(K3bDvdFormattingJob) not running." << endl; } } void K3bDvdFormattingJob::setDevice( K3bDevice::Device* dev ) { d->device = dev; } void K3bDvdFormattingJob::setMode( int m ) { d->mode = m; } void K3bDvdFormattingJob::setQuickFormat( bool b ) { d->quick = b; } void K3bDvdFormattingJob::setForce( bool b ) { d->force = b; } void K3bDvdFormattingJob::slotStderrLine( const TQString& 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( TQRegExp( "\\d" ), pos ); } // parsing for \b\b... stuff else if( !line.startsWith("*") ) { pos = line.find( TQRegExp( "\\d" ) ); } else if( line.startsWith( ":-(" ) ) { if( line.startsWith( ":-( unable to proceed with format" ) ) { d->error = true; } } if( pos >= 0 ) { int endPos = line.find( TQRegExp("[^\\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 K3bDvdFormattingJob::slotProcessFinished( TDEProcess* p ) { if( d->canceled ) { emit canceled(); d->success = false; } else if( p->normalExit() ) { if( !d->error && p->exitStatus() == 0 ) { emit infoMessage( i18n("Formatting successfully completed"), K3bJob::SUCCESS ); if( d->lastProgressValue < 100 ) { emit infoMessage( i18n("Do not be concerned with the progress stopping before 100%."), INFO ); emit infoMessage( i18n("The formatting will continue in the background while writing."), INFO ); } d->success = true; } else { emit infoMessage( i18n("%1 returned an unknown error (code %2).").arg(d->dvdFormatBin->name()).arg(p->exitStatus()), K3bJob::ERROR ); emit infoMessage( i18n("Please send me an email with the last output."), K3bJob::ERROR ); d->success = false; } } else { emit infoMessage( i18n("%1 did not exit cleanly.").arg(d->dvdFormatBin->name()), ERROR ); d->success = false; } if( d->forceNoEject || !k3bcore->globalSettings()->ejectMedia() ) { d->running = false; jobFinished(d->success); } else { emit infoMessage( i18n("Ejecting DVD..."), INFO ); connect( K3bDevice::eject( d->device ), TQT_SIGNAL(finished(K3bDevice::DeviceHandler*)), this, TQT_SLOT(slotEjectingFinished(K3bDevice::DeviceHandler*)) ); } } void K3bDvdFormattingJob::slotEjectingFinished( K3bDevice::DeviceHandler* dh ) { if( !dh->success() ) emit infoMessage( i18n("Unable to eject media."), ERROR ); d->running = false; jobFinished(d->success); } void K3bDvdFormattingJob::slotDeviceHandlerFinished( K3bDevice::DeviceHandler* dh ) { if( d->canceled ) { emit canceled(); jobFinished(false); d->running = false; } if( dh->success() ) { startFormatting( dh->diskInfo() ); } else { emit infoMessage( i18n("Unable to determine media state."), ERROR ); d->running = false; jobFinished(false); } } 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, TQT_SIGNAL(stderrLine(const TQString&)), this, TQT_SLOT(slotStderrLine(const TQString&)) ); connect( d->process, TQT_SIGNAL(processExited(TDEProcess*)), this, TQT_SLOT(slotProcessFinished(TDEProcess*)) ); 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"; TQString 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 TQStringList& params = d->dvdFormatBin->userParameters(); for( TQStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *d->process << *it; kdDebug() << "***** dvd+rw-format parameters:\n"; const TQValueList& args = d->process->args(); TQString s; for( TQValueList::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( TDEProcess::NotifyOnExit, TDEProcess::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 { // already formatted :) d->running = false; jobFinished(true); } } #include "k3bdvdformattingjob.moc"