File indexing completed on 2025-02-16 07:39:26
0001 /* 0002 SPDX-FileCopyrightText: 2005-2009 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 2011 Michal Malek <michalm@jabster.pl> 0004 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "k3baudiocuefilewritingjob.h" 0010 #include "k3baudiofileanalyzerjob.h" 0011 0012 #include "k3baudiodoc.h" 0013 #include "k3baudiojob.h" 0014 #include "k3bdevice.h" 0015 #include "k3baudiodecoder.h" 0016 #include "k3baudiotrack.h" 0017 #include "k3baudiofile.h" 0018 #include "k3bcuefileparser.h" 0019 #include "k3bthread.h" 0020 #include "k3bthreadjob.h" 0021 #include "k3b_i18n.h" 0022 0023 #include <QDebug> 0024 0025 0026 class K3b::AudioCueFileWritingJob::Private 0027 { 0028 public: 0029 Private() 0030 : device( 0 ), 0031 audioDoc( 0 ), 0032 audioJob( 0 ), 0033 decoder( 0 ), 0034 analyserJob( 0 ) { 0035 } 0036 0037 K3b::Device::Device* device; 0038 0039 QString cueFile; 0040 K3b::AudioDoc* audioDoc; 0041 K3b::AudioJob* audioJob; 0042 K3b::AudioDecoder* decoder; 0043 0044 K3b::AudioFileAnalyzerJob* analyserJob; 0045 0046 bool audioJobRunning; 0047 bool canceled; 0048 }; 0049 0050 0051 0052 K3b::AudioCueFileWritingJob::AudioCueFileWritingJob( K3b::JobHandler* jh, QObject* parent ) 0053 : K3b::BurnJob( jh, parent ), 0054 d( new Private() ) 0055 { 0056 d->analyserJob = new K3b::AudioFileAnalyzerJob( this, this ); 0057 connect( d->analyserJob, SIGNAL(finished(bool)), 0058 this, SLOT(slotAnalyserJobFinished(bool)) ); 0059 0060 d->audioDoc = new K3b::AudioDoc( this ); 0061 d->audioDoc->newDocument(); 0062 d->audioJob = new K3b::AudioJob( d->audioDoc, this, this ); 0063 0064 // just loop all through 0065 connect( d->audioJob, SIGNAL(newTask(QString)), this, SIGNAL(newTask(QString)) ); 0066 connect( d->audioJob, SIGNAL(newSubTask(QString)), this, SIGNAL(newSubTask(QString)) ); 0067 connect( d->audioJob, SIGNAL(debuggingOutput(QString,QString)), 0068 this, SIGNAL(debuggingOutput(QString,QString)) ); 0069 connect( d->audioJob, SIGNAL(infoMessage(QString,int)), 0070 this, SIGNAL(infoMessage(QString,int)) ); 0071 connect( d->audioJob, SIGNAL(finished(bool)), this, SIGNAL(finished(bool)) ); 0072 connect( d->audioJob, SIGNAL(canceled()), this, SIGNAL(canceled()) ); 0073 connect( d->audioJob, SIGNAL(percent(int)), this, SIGNAL(percent(int)) ); 0074 connect( d->audioJob, SIGNAL(subPercent(int)), this, SIGNAL(subPercent(int)) ); 0075 connect( d->audioJob, SIGNAL(processedSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); 0076 connect( d->audioJob, SIGNAL(processedSubSize(int,int)), this, SIGNAL(processedSubSize(int,int)) ); 0077 connect( d->audioJob, SIGNAL(burning(bool)), this, SIGNAL(burning(bool)) ); 0078 connect( d->audioJob, SIGNAL(bufferStatus(int)), this, SIGNAL(bufferStatus(int)) ); 0079 connect( d->audioJob, SIGNAL(deviceBuffer(int)), this, SIGNAL(deviceBuffer(int)) ); 0080 connect( d->audioJob, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)), this, SIGNAL(writeSpeed(int,K3b::Device::SpeedMultiplicator)) ); 0081 0082 d->canceled = false; 0083 d->audioJobRunning = false; 0084 } 0085 0086 0087 K3b::AudioCueFileWritingJob::~AudioCueFileWritingJob() 0088 { 0089 delete d; 0090 } 0091 0092 0093 K3b::Device::Device* K3b::AudioCueFileWritingJob::writer() const 0094 { 0095 return d->audioDoc->burner(); 0096 } 0097 0098 0099 QString K3b::AudioCueFileWritingJob::cueFile() const 0100 { 0101 return d->cueFile; 0102 } 0103 0104 0105 QString K3b::AudioCueFileWritingJob::jobDescription() const 0106 { 0107 return i18n("Writing Audio Cue File"); 0108 } 0109 0110 0111 QString K3b::AudioCueFileWritingJob::jobDetails() const 0112 { 0113 return d->cueFile.section( '/', -1 ); 0114 } 0115 0116 0117 QString K3b::AudioCueFileWritingJob::jobSource() const 0118 { 0119 return d->cueFile; 0120 } 0121 0122 0123 QString K3b::AudioCueFileWritingJob::jobTarget() const 0124 { 0125 if( Device::Device* device = writer() ) 0126 return device->vendor() + ' ' + device->description(); 0127 else 0128 return QString(); 0129 } 0130 0131 0132 void K3b::AudioCueFileWritingJob::start() 0133 { 0134 // FIXME: here we trust that a job won't be started twice :( 0135 jobStarted(); 0136 d->canceled = false; 0137 d->audioJobRunning = false; 0138 importCueInProject(); 0139 } 0140 0141 0142 void K3b::AudioCueFileWritingJob::cancel() 0143 { 0144 d->canceled = true; 0145 0146 // the AudioJob cancel method is very stupid. It emits the canceled signal even if it was never running :( 0147 if( d->audioJobRunning ) 0148 d->audioJob->cancel(); 0149 d->analyserJob->cancel(); 0150 } 0151 0152 0153 void K3b::AudioCueFileWritingJob::setCueFile( const QString& s ) 0154 { 0155 d->cueFile = s; 0156 } 0157 0158 0159 void K3b::AudioCueFileWritingJob::setOnTheFly( bool b ) 0160 { 0161 d->audioDoc->setOnTheFly( b ); 0162 } 0163 0164 0165 void K3b::AudioCueFileWritingJob::setSpeed( int s ) 0166 { 0167 d->audioDoc->setSpeed( s ); 0168 } 0169 0170 0171 void K3b::AudioCueFileWritingJob::setBurnDevice( K3b::Device::Device* dev ) 0172 { 0173 d->audioDoc->setBurner( dev ); 0174 } 0175 0176 0177 void K3b::AudioCueFileWritingJob::setWritingMode( K3b::WritingMode mode ) 0178 { 0179 d->audioDoc->setWritingMode( mode ); 0180 } 0181 0182 0183 void K3b::AudioCueFileWritingJob::setSimulate( bool b ) 0184 { 0185 d->audioDoc->setDummy( b ); 0186 } 0187 0188 0189 void K3b::AudioCueFileWritingJob::setCopies( int c ) 0190 { 0191 d->audioDoc->setCopies( c ); 0192 } 0193 0194 0195 void K3b::AudioCueFileWritingJob::setTempDir( const QString& s ) 0196 { 0197 d->audioDoc->setTempDir( s ); 0198 } 0199 0200 0201 void K3b::AudioCueFileWritingJob::slotAnalyserJobFinished( bool ) 0202 { 0203 if( !d->canceled ) { 0204 if( d->audioDoc->lastTrack()->length() == 0 ) { 0205 emit infoMessage( i18n("Analysing the audio file failed. Corrupt file?"), MessageError ); 0206 jobFinished(false); 0207 } 0208 else { 0209 // FIXME: d->audioJobRunning is never reset 0210 d->audioJobRunning = true; 0211 d->audioJob->start(); // from here on the audio job takes over completely 0212 } 0213 } 0214 else { 0215 emit canceled(); 0216 jobFinished(false); 0217 } 0218 } 0219 0220 0221 void K3b::AudioCueFileWritingJob::importCueInProject() 0222 { 0223 // cleanup the project (this wil also delete the decoder) 0224 // we do not use newDocument as that would overwrite the settings already made 0225 while( d->audioDoc->firstTrack() ) 0226 delete d->audioDoc->firstTrack()->take(); 0227 0228 d->decoder = 0; 0229 0230 K3b::CueFileParser parser( d->cueFile ); 0231 if( parser.isValid() && parser.toc().contentType() == K3b::Device::AUDIO ) { 0232 0233 qDebug() << "(K3b::AudioCueFileWritingJob::importCueFile) parsed with image: " << parser.imageFilename(); 0234 0235 // global cd-text 0236 d->audioDoc->setTitle( parser.cdText().title() ); 0237 d->audioDoc->setPerformer( parser.cdText().performer() ); 0238 d->audioDoc->writeCdText( !parser.cdText().title().isEmpty() ); 0239 0240 d->decoder = K3b::AudioDecoderFactory::createDecoder( QUrl::fromLocalFile(parser.imageFilename()) ); 0241 if( d->decoder ) { 0242 d->decoder->setFilename( parser.imageFilename() ); 0243 0244 K3b::AudioTrack* after = 0; 0245 K3b::AudioFile* newFile = 0; 0246 unsigned int i = 0; 0247 for( K3b::Device::Toc::const_iterator it = parser.toc().constBegin(); 0248 it != parser.toc().constEnd(); ++it ) { 0249 const K3b::Device::Track& track = *it; 0250 0251 newFile = new K3b::AudioFile( d->decoder, d->audioDoc ); 0252 newFile->setStartOffset( track.firstSector() ); 0253 newFile->setEndOffset( track.lastSector()+1 ); 0254 0255 K3b::AudioTrack* newTrack = new K3b::AudioTrack( d->audioDoc ); 0256 newTrack->addSource( newFile ); 0257 newTrack->moveAfter( after ); 0258 0259 // cd-text 0260 newTrack->setTitle( parser.cdText()[i].title() ); 0261 newTrack->setPerformer( parser.cdText()[i].performer() ); 0262 0263 // add the next track after this one 0264 after = newTrack; 0265 ++i; 0266 } 0267 0268 // let the last source use the data up to the end of the file 0269 if( newFile ) 0270 newFile->setEndOffset(0); 0271 0272 // now analyze the source 0273 emit newTask( i18n("Analysing the audio file") ); 0274 emit newSubTask( i18n("Analysing %1", parser.imageFilename() ) ); 0275 0276 // start the analyser job 0277 d->analyserJob->setDecoder( d->decoder ); 0278 d->analyserJob->start(); 0279 } 0280 else { 0281 emit infoMessage( i18n("Unable to handle '%1' due to an unsupported format.", d->cueFile ), MessageError ); 0282 jobFinished(false); 0283 } 0284 } 0285 else { 0286 emit infoMessage( i18n("No valid audio cue file: '%1'", d->cueFile ), MessageError ); 0287 jobFinished(false); 0288 } 0289 } 0290 0291 #include "moc_k3baudiocuefilewritingjob.cpp"