|
|
|
/*
|
|
|
|
*
|
|
|
|
* $Id: k3bcdda2wavreader.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 "k3bcdda2wavreader.h"
|
|
|
|
|
|
|
|
#include <k3bexternalbinmanager.h>
|
|
|
|
#include <k3bdevice.h>
|
|
|
|
#include <k3bdevicemanager.h>
|
|
|
|
#include <k3bcore.h>
|
|
|
|
#include <k3bprocess.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
|
|
|
|
#include <tqvaluevector.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
|
|
|
|
|
|
|
|
class K3bCdda2wavReader::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Private()
|
|
|
|
: cdda2wavBin(0),
|
|
|
|
process(0),
|
|
|
|
cancaled(false),
|
|
|
|
running(false),
|
|
|
|
fdToWriteTo(-1) {
|
|
|
|
}
|
|
|
|
|
|
|
|
const K3bExternalBin* cdda2wavBin;
|
|
|
|
K3bProcess* process;
|
|
|
|
|
|
|
|
bool cancaled;
|
|
|
|
bool running;
|
|
|
|
|
|
|
|
int fdToWriteTo;
|
|
|
|
|
|
|
|
int currentTrack;
|
|
|
|
TQValueVector<int> trackOffsets;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
K3bCdda2wavReader::K3bCdda2wavReader( TQObject* parent, const char* name )
|
|
|
|
: K3bJob( parent, name )
|
|
|
|
{
|
|
|
|
d = new Private();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
K3bCdda2wavReader::~K3bCdda2wavReader()
|
|
|
|
{
|
|
|
|
delete d->process;
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool K3bCdda2wavReader::active() const
|
|
|
|
{
|
|
|
|
return d->running;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::writeToFd( int fd )
|
|
|
|
{
|
|
|
|
d->fdToWriteTo = fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::start()
|
|
|
|
{
|
|
|
|
start( false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::start( bool onlyInfo )
|
|
|
|
{
|
|
|
|
d->running = true;
|
|
|
|
d->cancaled = false;
|
|
|
|
d->currentTrack = 1;
|
|
|
|
d->trackOffsets.clear();
|
|
|
|
|
|
|
|
jobStarted();
|
|
|
|
|
|
|
|
d->cdda2wavBin = k3bcore->externalBinManager()->binObject( "cdda2wav" );
|
|
|
|
if( !d->cdda2wavBin ) {
|
|
|
|
emit infoMessage( i18n("Could not find %1 executable.").tqarg("cdda2wav"), ERROR );
|
|
|
|
jobFinished(false);
|
|
|
|
d->running = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// prepare the process
|
|
|
|
delete d->process;
|
|
|
|
d->process = new K3bProcess();
|
|
|
|
d->process->setSplitStdout(true);
|
|
|
|
d->process->setSuppressEmptyLines(true);
|
|
|
|
d->process->setWorkingDirectory( m_imagePath );
|
|
|
|
connect( d->process, TQT_SIGNAL(stdoutLine(const TQString&)), this, TQT_SLOT(slotProcessLine(const TQString&)) );
|
|
|
|
connect( d->process, TQT_SIGNAL(stderrLine(const TQString&)), this, TQT_SLOT(slotProcessLine(const TQString&)) );
|
|
|
|
connect( d->process, TQT_SIGNAL(processExited(KProcess*)), this, TQT_SLOT(slotProcessExited(KProcess*)) );
|
|
|
|
|
|
|
|
// create the command line
|
|
|
|
*d->process << d->cdda2wavBin->path;
|
|
|
|
*d->process << "-vall" << ( d->cdda2wavBin->hasFeature( "gui" ) ? "-gui" : "-g" );
|
|
|
|
if( d->cdda2wavBin->hasFeature( "dev" ) )
|
|
|
|
*d->process << TQString("dev=%1").tqarg(K3bDevice::externalBinDeviceParameter(m_device, d->cdda2wavBin));
|
|
|
|
else
|
|
|
|
*d->process << "-D" << K3bDevice::externalBinDeviceParameter(m_device, d->cdda2wavBin);
|
|
|
|
*d->process << ( d->cdda2wavBin->hasFeature( "bulk" ) ? "-bulk" : "-B" );
|
|
|
|
if( onlyInfo )
|
|
|
|
*d->process << ( d->cdda2wavBin->hasFeature( "info-only" ) ? "-info-only" : "-J" );
|
|
|
|
else if( d->fdToWriteTo != -1 )
|
|
|
|
*d->process << ( d->cdda2wavBin->hasFeature( "no-infofile" ) ? "-no-infofile" : "-H" );
|
|
|
|
|
|
|
|
// additional user parameters from config
|
|
|
|
const TQStringList& params = d->cdda2wavBin->userParameters();
|
|
|
|
for( TQStringList::const_iterator it = params.begin(); it != params.end(); ++it )
|
|
|
|
*d->process << *it;
|
|
|
|
|
|
|
|
// start the thing
|
|
|
|
if( !d->process->start( KProcess::NotifyOnExit, KProcess::All ) ) {
|
|
|
|
// something went wrong when starting the program
|
|
|
|
// it "should" be the executable
|
|
|
|
kdDebug() << "(K3bCdda2wavReader) could not start cdda2wav" << endl;
|
|
|
|
emit infoMessage( i18n("Could not start %1.").tqarg("cdda2wav"), K3bJob::ERROR );
|
|
|
|
d->running = false;
|
|
|
|
jobFinished(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::cancel()
|
|
|
|
{
|
|
|
|
if( d->running ) {
|
|
|
|
d->cancaled = true;
|
|
|
|
if( d->process )
|
|
|
|
if( d->process->isRunning() )
|
|
|
|
d->process->kill();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::slotProcessLine( const TQString& line )
|
|
|
|
{
|
|
|
|
// Tracks:11 44:37.30
|
|
|
|
// CDINDEX discid: ZvzBXv614ACgzn1bWWy107cs0nA-
|
|
|
|
// CDDB discid: 0x8a0a730b
|
|
|
|
// CD-Text: not detected
|
|
|
|
// CD-Extra: not detected
|
|
|
|
// Album title: '' from ''
|
|
|
|
// T01: 0 3:39.70 audio linear copydenied stereo title '' from ''
|
|
|
|
// T02: 16495 3:10.47 audio linear copydenied stereo title '' from ''
|
|
|
|
// T03: 30792 3:30.00 audio linear copydenied stereo title '' from ''
|
|
|
|
// T04: 46542 4:05.05 audio linear copydenied stereo title '' from ''
|
|
|
|
// T05: 64922 3:44.35 audio linear copydenied stereo title '' from ''
|
|
|
|
// T06: 81757 4:36.45 audio linear copydenied stereo title '' from ''
|
|
|
|
// T07: 102502 3:59.30 audio linear copydenied stereo title '' from ''
|
|
|
|
// T08: 120457 5:24.30 audio linear copydenied stereo title '' from ''
|
|
|
|
// T09: 144787 3:26.28 audio linear copydenied stereo title '' from ''
|
|
|
|
// T10: 160265 4:07.20 audio linear copydenied stereo title '' from ''
|
|
|
|
// T11: 178810 4:51.20 audio linear copydenied stereo title '' from ''
|
|
|
|
|
|
|
|
// percent_done:
|
|
|
|
// 100% track 1 successfully recorded
|
|
|
|
// 100% track 2 successfully recorded
|
|
|
|
// 100% track 3 successfully recorded
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static TQRegExp rx( "T\\d\\d:" );
|
|
|
|
if( rx.exactMatch( line.left(4) ) || line.startsWith( "Leadout" ) ) {
|
|
|
|
int pos = line.find( " " );
|
|
|
|
int endpos = line.find( TQRegExp( "\\d" ), pos );
|
|
|
|
endpos = line.find( " ", endpos );
|
|
|
|
bool ok;
|
|
|
|
int offset = line.mid( pos, endpos-pos ).toInt(&ok);
|
|
|
|
if( ok )
|
|
|
|
d->trackOffsets.append( offset );
|
|
|
|
else
|
|
|
|
kdDebug() << "(K3bCdda2wavReader) track offset parsing error: '" << line.mid( pos, endpos-pos ) << "'" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( line.startsWith( "percent_done" ) ) {
|
|
|
|
// the reading starts
|
|
|
|
d->currentTrack = 1;
|
|
|
|
emit nextTrack( d->currentTrack, d->trackOffsets.count() );
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( line.contains("successfully recorded") ) {
|
|
|
|
d->currentTrack++;
|
|
|
|
emit nextTrack( d->currentTrack, d->trackOffsets.count() );
|
|
|
|
}
|
|
|
|
|
|
|
|
else if( line.contains("%") ) {
|
|
|
|
// parse progress
|
|
|
|
bool ok;
|
|
|
|
int p = line.left(3).toInt(&ok);
|
|
|
|
if( ok ) {
|
|
|
|
emit subPercent( p );
|
|
|
|
|
|
|
|
int overall = d->trackOffsets[d->currentTrack-1];
|
|
|
|
int tSize = d->trackOffsets[d->currentTrack] - d->trackOffsets[d->currentTrack-1];
|
|
|
|
overall += (tSize*p/100);
|
|
|
|
|
|
|
|
emit percent( overall*100/d->trackOffsets[d->trackOffsets.count()-1] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug() << "(K3bCdda2wavReader) track progress parsing error: '" << line.left(3) << "'" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void K3bCdda2wavReader::slotProcessExited( KProcess* p )
|
|
|
|
{
|
|
|
|
d->running = false;
|
|
|
|
|
|
|
|
if( d->cancaled ) {
|
|
|
|
emit canceled();
|
|
|
|
jobFinished(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( p->normalExit() ) {
|
|
|
|
// TODO: improve this
|
|
|
|
|
|
|
|
if( p->exitStatus() == 0 ) {
|
|
|
|
jobFinished( true );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
emit infoMessage( i18n("%1 returned an unknown error (code %2).")
|
|
|
|
.tqarg("Cdda2wav").tqarg(p->exitStatus()), ERROR );
|
|
|
|
jobFinished( false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
emit infoMessage( i18n("%1 did not exit cleanly.").tqarg("Cdda2wav"),
|
|
|
|
ERROR );
|
|
|
|
jobFinished( false );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "k3bcdda2wavreader.moc"
|