You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3b/libk3b/projects/datacd/k3bmsinfofetcher.cpp

244 lines
6.6 KiB

/*
*
* $Id: k3bmsinfofetcher.cpp 619556 2007-01-03 17:38:12Z 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 "k3bmsinfofetcher.h"
#include <k3bexternalbinmanager.h>
#include <k3bdevicemanager.h>
#include <k3bdevicehandler.h>
#include <k3bdevice.h>
#include <k3bcore.h>
#include <k3bglobals.h>
#include <k3biso9660.h>
#include <klocale.h>
#include <kprocess.h>
#include <kdebug.h>
#include <tqstringlist.h>
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<TQCString>& args = m_process->args();
TQString s;
for( TQValueList<TQCString>::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"