/* * * $Id: k3bmsinfofetcher.cpp 619556 2007-01-03 17:38:12Z 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 "k3bmsinfofetcher.h" #include #include #include #include #include #include #include #include #include #include #include K3bMsInfoFetcher::K3bMsInfoFetcher( K3bJobHandler* jh, TQObject* parent, const char* name ) : K3bJob( jh, parent, name ), m_process(0), m_device(0), m_dvd(false) { } K3bMsInfoFetcher::~K3bMsInfoFetcher() { delete m_process; } void K3bMsInfoFetcher::start() { jobStarted(); emit infoMessage( i18n("Searching previous session"), K3bJob::INFO ); if( !k3bcore->externalBinManager()->foundBin( "cdrecord" ) ) { kdDebug() << "(K3bMsInfoFetcher) could not find cdrecord executable" << endl; emit infoMessage( i18n("Could not find %1 executable.").arg("cdrecord"), K3bJob::ERROR ); jobFinished(false); return; } if( m_device == 0 ) { kdDebug() << "(K3bMsInfoFetcher) internal error: No device set!" << endl; jobFinished(false); return; } // // first we try to determine if it is a dvd. If so we need to // read the info on our own // connect( K3bDevice::sendCommand( K3bDevice::DeviceHandler::NG_DISKINFO, m_device ), TQT_SIGNAL(finished(K3bDevice::DeviceHandler*)), this, TQT_SLOT(slotMediaDetectionFinished(K3bDevice::DeviceHandler*)) ); } void K3bMsInfoFetcher::getMsInfo() { delete m_process; m_process = new KProcess(); const K3bExternalBin* bin = 0; if( m_dvd ) { // already handled } else { bin = k3bcore->externalBinManager()->binObject( "cdrecord" ); if( !bin ) { emit infoMessage( i18n("Could not find %1 executable.").arg( m_dvd ? "dvdrecord" : "cdrecord" ), ERROR ); jobFinished(false); return; } *m_process << bin->path; // add the device (e.g. /dev/sg1) *m_process << TQString("dev=%1").arg( K3b::externalBinDeviceParameter(m_device, bin) ); *m_process << "-msinfo"; // additional user parameters from config const TQStringList& params = bin->userParameters(); for( TQStringList::const_iterator it = params.begin(); it != params.end(); ++it ) *m_process << *it; kdDebug() << "***** " << bin->name() << " parameters:\n"; const TQValueList& args = m_process->args(); TQString s; for( TQValueList::const_iterator it = args.begin(); it != args.end(); ++it ) { s += *it + " "; } kdDebug() << s << flush << endl; emit debuggingOutput( "msinfo command:", s ); // connect( m_process, TQT_SIGNAL(receivedStderr(KProcess*, char*, int)), // this, TQT_SLOT(slotCollectOutput(KProcess*, char*, int)) ); connect( m_process, TQT_SIGNAL(receivedStdout(KProcess*, char*, int)), this, TQT_SLOT(slotCollectOutput(KProcess*, char*, int)) ); connect( m_process, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotProcessExited()) ); m_msInfo = TQString(); m_collectedOutput = TQString(); m_canceled = false; if( !m_process->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { emit infoMessage( i18n("Could not start %1.").arg(bin->name()), K3bJob::ERROR ); jobFinished(false); } } } void K3bMsInfoFetcher::slotMediaDetectionFinished( K3bDevice::DeviceHandler* h ) { if( h->success() ) { m_dvd = h->diskInfo().isDvdMedia(); } else { // for now we just default to cd and go on with the detecting m_dvd = false; } if( m_dvd ) { if( h->diskInfo().mediaType() & (K3bDevice::MEDIA_DVD_PLUS_RW|K3bDevice::MEDIA_DVD_RW_OVWR) ) { // get info from iso filesystem K3bIso9660 iso( m_device, h->toc().last().firstSector().lba() ); if( iso.open() ) { unsigned long long nextSession = iso.primaryDescriptor().volumeSpaceSize; // pad to closest 32K boundary nextSession += 15; nextSession /= 16; nextSession *= 16; m_msInfo.sprintf( "16,%llu", nextSession ); jobFinished( true ); } else { emit infoMessage( i18n("Could not open Iso9660 filesystem in %1.") .arg( m_device->vendor() + " " + m_device->description() ), ERROR ); jobFinished( false ); } } else { unsigned int lastSessionStart, nextWritableAdress; if( m_device->getNextWritableAdress( lastSessionStart, nextWritableAdress ) ) { m_msInfo.sprintf( "%u,%u", lastSessionStart+16, nextWritableAdress ); jobFinished( true ); } else { emit infoMessage( i18n("Could not determine next writable address."), ERROR ); jobFinished( false ); } } } else // call cdrecord getMsInfo(); } void K3bMsInfoFetcher::slotProcessExited() { if( m_canceled ) return; kdDebug() << "(K3bMsInfoFetcher) msinfo fetched" << endl; // now parse the output TQString firstLine = m_collectedOutput.left( m_collectedOutput.find("\n") ); TQStringList list = TQStringList::split( ",", firstLine ); if( list.count() == 2 ) { bool ok1, ok2; m_lastSessionStart = list.first().toInt( &ok1 ); m_nextSessionStart = list[1].toInt( &ok2 ); if( ok1 && ok2 ) m_msInfo = firstLine.stripWhiteSpace(); else m_msInfo = TQString(); } else { m_msInfo = TQString(); } kdDebug() << "(K3bMsInfoFetcher) msinfo parsed: " << m_msInfo << endl; if( m_msInfo.isEmpty() ) { emit infoMessage( i18n("Could not retrieve multisession information from disk."), K3bJob::ERROR ); emit infoMessage( i18n("The disk is either empty or not appendable."), K3bJob::ERROR ); jobFinished(false); } else { jobFinished(true); } } void K3bMsInfoFetcher::slotCollectOutput( KProcess*, char* output, int len ) { emit debuggingOutput( "msinfo", TQString::fromLocal8Bit( output, len ) ); m_collectedOutput += TQString::fromLocal8Bit( output, len ); } void K3bMsInfoFetcher::cancel() { // FIXME: this does not work if the devicehandler is running if( m_process ) if( m_process->isRunning() ) { m_canceled = true; m_process->kill(); emit canceled(); jobFinished(false); } } #include "k3bmsinfofetcher.moc"