File indexing completed on 2024-06-16 07:42:02

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "k3baudiosessionreadingjob.h"
0008 
0009 #include "k3bthread.h"
0010 #include "k3btoc.h"
0011 #include "k3bcdparanoialib.h"
0012 #include "k3bwavefilewriter.h"
0013 #include "k3bglobals.h"
0014 #include "k3bdevice.h"
0015 #include "k3bcore.h"
0016 #include "k3b_i18n.h"
0017 
0018 #include <QDebug>
0019 
0020 #include <unistd.h>
0021 
0022 
0023 class K3b::AudioSessionReadingJob::Private
0024 {
0025 public:
0026     Private();
0027     ~Private();
0028 
0029     QIODevice* ioDev;
0030     K3b::CdparanoiaLib* paranoia;
0031     K3b::Device::Device* device;
0032     K3b::Device::Toc toc;
0033     K3b::WaveFileWriter* waveFileWriter;
0034     QStringList filenames;
0035     int paranoiaMode;
0036     int retries;
0037     bool neverSkip;
0038 };
0039 
0040 
0041 K3b::AudioSessionReadingJob::Private::Private()
0042     : ioDev( 0 ),
0043       paranoia(0),
0044       waveFileWriter(0),
0045       paranoiaMode(0),
0046       retries(50),
0047       neverSkip(false)
0048 {
0049 }
0050 
0051 
0052 K3b::AudioSessionReadingJob::Private::~Private()
0053 {
0054     delete waveFileWriter;
0055     delete paranoia;
0056 }
0057 
0058 
0059 K3b::AudioSessionReadingJob::AudioSessionReadingJob( K3b::JobHandler* jh, QObject* parent )
0060     : K3b::ThreadJob( jh, parent ),
0061       d( new Private() )
0062 {
0063 }
0064 
0065 
0066 K3b::AudioSessionReadingJob::~AudioSessionReadingJob()
0067 {
0068     delete d;
0069 }
0070 
0071 
0072 void K3b::AudioSessionReadingJob::setDevice( K3b::Device::Device* dev )
0073 {
0074     d->device = dev;
0075     d->toc = K3b::Device::Toc();
0076 }
0077 
0078 
0079 void K3b::AudioSessionReadingJob::setToc( const K3b::Device::Toc& toc )
0080 {
0081     d->toc = toc;
0082 }
0083 
0084 
0085 void K3b::AudioSessionReadingJob::writeTo( QIODevice* ioDev )
0086 {
0087     d->ioDev = ioDev;
0088 }
0089 
0090 void K3b::AudioSessionReadingJob::setImageNames( const QStringList& l )
0091 {
0092     d->filenames = l;
0093     d->ioDev = 0;
0094 }
0095 
0096 
0097 void K3b::AudioSessionReadingJob::setParanoiaMode( int m )
0098 {
0099     d->paranoiaMode = m;
0100 }
0101 
0102 
0103 void K3b::AudioSessionReadingJob::setReadRetries( int r )
0104 {
0105     d->retries = r;
0106 }
0107 
0108 void K3b::AudioSessionReadingJob::setNeverSkip( bool b )
0109 {
0110     d->neverSkip = b;
0111 }
0112 
0113 
0114 void K3b::AudioSessionReadingJob::start()
0115 {
0116     k3bcore->blockDevice( d->device );
0117     K3b::ThreadJob::start();
0118 }
0119 
0120 
0121 void K3b::AudioSessionReadingJob::jobFinished( bool success )
0122 {
0123     k3bcore->unblockDevice( d->device );
0124     K3b::ThreadJob::jobFinished( success );
0125 }
0126 
0127 
0128 bool K3b::AudioSessionReadingJob::run()
0129 {
0130     if( !d->paranoia )
0131         d->paranoia = K3b::CdparanoiaLib::create();
0132 
0133     if( !d->paranoia ) {
0134         emit infoMessage( i18n("Could not load libcdparanoia."), K3b::Job::MessageError );
0135         return false;
0136     }
0137 
0138     if( d->toc.isEmpty() )
0139         d->toc = d->device->readToc();
0140 
0141     if( !d->paranoia->initParanoia( d->device, d->toc ) ) {
0142         emit infoMessage( i18n("Could not open device %1", d->device->blockDeviceName()),
0143                           K3b::Job::MessageError );
0144         return false;
0145     }
0146 
0147     if( !d->paranoia->initReading() ) {
0148         emit infoMessage( i18n("Error while initializing audio ripping."), K3b::Job::MessageError );
0149         return false;
0150     }
0151 
0152     d->device->block( true );
0153 
0154     // init settings
0155     d->paranoia->setMaxRetries( d->retries );
0156     d->paranoia->setParanoiaMode( d->paranoiaMode );
0157     d->paranoia->setNeverSkip( d->neverSkip );
0158 
0159     bool writeError = false;
0160     unsigned int trackNum = 1;
0161     unsigned int currentTrack = 0;
0162     unsigned long trackRead = 0;
0163     unsigned long totalRead = 0;
0164     unsigned int lastTrackPercent = 0;
0165     unsigned int lastTotalPercent = 0;
0166     bool newTrack = true;
0167     int status = 0;
0168     char* buffer = 0;
0169     while( !canceled() && (buffer = d->paranoia->read( &status, &trackNum, !d->ioDev /*when writing to a wav be want little endian */ )) ) {
0170 
0171         if( currentTrack != trackNum ) {
0172             emit nextTrack( trackNum, d->paranoia->toc().count() );
0173             trackRead = 0;
0174             lastTrackPercent = 0;
0175 
0176             currentTrack = trackNum;
0177             newTrack = true;
0178         }
0179 
0180         if( d->ioDev ) {
0181             if( d->ioDev->write( buffer, CD_FRAMESIZE_RAW ) != CD_FRAMESIZE_RAW ) {
0182                 qDebug() << "(K3b::AudioSessionCopyJob::WorkThread) error while writing to device " << d->ioDev;
0183                 writeError = true;
0184                 break;
0185             }
0186         }
0187         else {
0188             if( newTrack ) {
0189                 newTrack = false;
0190 
0191                 if( !d->waveFileWriter )
0192                     d->waveFileWriter = new K3b::WaveFileWriter();
0193 
0194                 if( d->filenames.count() < ( int )currentTrack ) {
0195                     qDebug() << "(K3b::AudioSessionCopyJob) not enough image filenames given: " << currentTrack;
0196                     writeError = true;
0197                     break;
0198                 }
0199 
0200                 if( !d->waveFileWriter->open( d->filenames[currentTrack-1] ) ) {
0201                     emit infoMessage( i18n("Unable to open '%1' for writing.", d->filenames[currentTrack-1]), K3b::Job::MessageError );
0202                     writeError = true;
0203                     break;
0204                 }
0205             }
0206 
0207             d->waveFileWriter->write( buffer,
0208                                       CD_FRAMESIZE_RAW,
0209                                       K3b::WaveFileWriter::LittleEndian );
0210         }
0211 
0212         trackRead++;
0213         totalRead++;
0214 
0215         unsigned int trackPercent = 100 * trackRead / d->toc[currentTrack-1].length().lba();
0216         if( trackPercent > lastTrackPercent ) {
0217             lastTrackPercent = trackPercent;
0218             emit subPercent( lastTrackPercent );
0219         }
0220         unsigned int totalPercent = 100 * totalRead / d->paranoia->rippedDataLength();
0221         if( totalPercent > lastTotalPercent ) {
0222             lastTotalPercent = totalPercent;
0223             emit percent( lastTotalPercent );
0224         }
0225     }
0226 
0227     if( d->waveFileWriter )
0228         d->waveFileWriter->close();
0229 
0230     d->paranoia->close();
0231 
0232     d->device->block( false );
0233 
0234     if( status != K3b::CdparanoiaLib::S_OK ) {
0235         emit infoMessage( i18n("Unrecoverable error while ripping track %1.", trackNum), K3b::Job::MessageError );
0236         return false;
0237     }
0238 
0239     return !writeError && !canceled();
0240 }
0241 
0242 #include "moc_k3baudiosessionreadingjob.cpp"