/* * * $Id: k3baudiosessionreadingjob.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 "k3baudiosessionreadingjob.h" #include #include #include #include #include #include #include #include #include #include class K3bAudioSessionReadingJob::WorkThread : public K3bThread { public: WorkThread(); ~WorkThread(); void init(); void run(); void cancel(); bool canceled; int fd; K3bCdparanoiaLib* paranoia; K3bDevice::Device* device; K3bDevice::Toc toc; K3bWaveFileWriter* waveFileWriter; TQStringList filenames; int paranoiaMode; int retries; bool neverSkip; }; K3bAudioSessionReadingJob::WorkThread::WorkThread() : K3bThread(), fd(-1), paranoia(0), waveFileWriter(0), paranoiaMode(0), retries(50), neverSkip(false) { } K3bAudioSessionReadingJob::WorkThread::~WorkThread() { delete waveFileWriter; delete paranoia; } void K3bAudioSessionReadingJob::WorkThread::init() { canceled = false; } void K3bAudioSessionReadingJob::WorkThread::run() { if( !paranoia ) paranoia = K3bCdparanoiaLib::create(); if( !paranoia ) { emitInfoMessage( i18n("Could not load libcdparanoia."), K3bJob::ERROR ); emitFinished(false); return; } if( toc.isEmpty() ) toc = device->readToc(); if( !paranoia->initParanoia( device, toc ) ) { emitInfoMessage( i18n("Could not open device %1").arg(device->blockDeviceName()), K3bJob::ERROR ); emitFinished(false); return; } if( !paranoia->initReading() ) { emitInfoMessage( i18n("Error while initializing audio ripping."), K3bJob::ERROR ); emitFinished(false); return; } device->block( true ); // init settings paranoia->setMaxRetries( retries ); paranoia->setParanoiaMode( paranoiaMode ); paranoia->setNeverSkip( neverSkip ); bool writeError = false; unsigned int trackNum = 1; unsigned int currentTrack = 0; unsigned long trackRead = 0; unsigned long totalRead = 0; unsigned int lastTrackPercent = 0; unsigned int lastTotalPercent = 0; bool newTrack = true; int status = 0; char* buffer = 0; while( !canceled && (buffer = paranoia->read( &status, &trackNum, fd == -1 /*when writing to a wav be want little endian */ )) ) { if( currentTrack != trackNum ) { emitNextTrack( trackNum, paranoia->toc().count() ); trackRead = 0; lastTrackPercent = 0; currentTrack = trackNum; newTrack = true; } if( fd > 0 ) { if( ::write( fd, buffer, CD_FRAMESIZE_RAW ) != CD_FRAMESIZE_RAW ) { kdDebug() << "(K3bAudioSessionCopyJob::WorkThread) error while writing to fd " << fd << endl; writeError = true; break; } } else { if( newTrack ) { newTrack = false; if( !waveFileWriter ) waveFileWriter = new K3bWaveFileWriter(); if( filenames.count() < currentTrack ) { kdDebug() << "(K3bAudioSessionCopyJob) not enough image filenames given: " << currentTrack << endl; writeError = true; break; } if( !waveFileWriter->open( filenames[currentTrack-1] ) ) { emitInfoMessage( i18n("Unable to open '%1' for writing.").arg(filenames[currentTrack-1]), K3bJob::ERROR ); writeError = true; break; } } waveFileWriter->write( buffer, CD_FRAMESIZE_RAW, K3bWaveFileWriter::LittleEndian ); } trackRead++; totalRead++; unsigned int trackPercent = 100 * trackRead / toc[currentTrack-1].length().lba(); if( trackPercent > lastTrackPercent ) { lastTrackPercent = trackPercent; emitSubPercent( lastTrackPercent ); } unsigned int totalPercent = 100 * totalRead / paranoia->rippedDataLength(); if( totalPercent > lastTotalPercent ) { lastTotalPercent = totalPercent; emitPercent( lastTotalPercent ); } } if( waveFileWriter ) waveFileWriter->close(); paranoia->close(); device->block( false ); if( status != K3bCdparanoiaLib::S_OK ) { emitInfoMessage( i18n("Unrecoverable error while ripping track %1.").arg(trackNum), K3bJob::ERROR ); emitFinished(false); return; } emitFinished( !writeError & !canceled ); } void K3bAudioSessionReadingJob::WorkThread::cancel() { canceled = true; // FIXME: add backup killing like in the audio ripping and make sure to close paranoia } K3bAudioSessionReadingJob::K3bAudioSessionReadingJob( K3bJobHandler* jh, TQObject* parent, const char* name ) : K3bThreadJob( jh, parent, name ) { m_thread = new WorkThread(); setThread( m_thread ); } K3bAudioSessionReadingJob::~K3bAudioSessionReadingJob() { delete m_thread; } void K3bAudioSessionReadingJob::setDevice( K3bDevice::Device* dev ) { m_thread->device = dev; m_thread->toc = K3bDevice::Toc(); } void K3bAudioSessionReadingJob::setToc( const K3bDevice::Toc& toc ) { m_thread->toc = toc; } void K3bAudioSessionReadingJob::writeToFd( int fd ) { m_thread->fd = fd; } void K3bAudioSessionReadingJob::setImageNames( const TQStringList& l ) { m_thread->filenames = l; m_thread->fd = -1; } void K3bAudioSessionReadingJob::setParanoiaMode( int m ) { m_thread->paranoiaMode = m; } void K3bAudioSessionReadingJob::setReadRetries( int r ) { m_thread->retries = r; } void K3bAudioSessionReadingJob::setNeverSkip( bool b ) { m_thread->neverSkip = b; } void K3bAudioSessionReadingJob::start() { k3bcore->blockDevice( m_thread->device ); K3bThreadJob::start(); } void K3bAudioSessionReadingJob::cleanupJob( bool success ) { Q_UNUSED( success ); k3bcore->unblockDevice( m_thread->device ); } #include "k3baudiosessionreadingjob.moc"