File indexing completed on 2024-05-12 04:51:01

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3baudiomaxspeedjob.h"
0007 #include "k3baudiotrack.h"
0008 #include "k3baudiodatasource.h"
0009 #include "k3baudiodoc.h"
0010 #include "k3baudiocdtracksource.h"
0011 #include "k3baudiodatasourceiterator.h"
0012 #include "k3bdevice.h"
0013 #include "k3bthread.h"
0014 #include "k3b_i18n.h"
0015 
0016 #include <QDateTime>
0017 #include <QDebug>
0018 #include <QIODevice>
0019 #include <QScopedPointer>
0020 #include <QElapsedTimer>
0021 
0022 
0023 class K3b::AudioMaxSpeedJob::Private
0024 {
0025 public:
0026     int speedTest( K3b::AudioDataSource* source, QIODevice& sourceReader );
0027     int maxSpeedByMedia() const;
0028 
0029     int maxSpeed;
0030     K3b::AudioDoc* doc;
0031     char* buffer;
0032 };
0033 
0034 
0035 // returns the amount of data read from this source
0036 int K3b::AudioMaxSpeedJob::Private::speedTest( K3b::AudioDataSource* source, QIODevice& sourceReader )
0037 {
0038     //
0039     // in case of an audio track source we only test when the cd is inserted since asking the user would
0040     // confuse him a lot.
0041     //
0042     // FIXME: there is still the problem of the spin up time.
0043     //
0044     if( K3b::AudioCdTrackSource* cdts = dynamic_cast<K3b::AudioCdTrackSource*>( source ) ) {
0045         if( K3b::Device::Device* dev = cdts->searchForAudioCD() ) {
0046             cdts->setDevice( dev );
0047         }
0048         else {
0049             qDebug() << "(K3b::AudioMaxSpeedJob) ignoring audio cd track source.";
0050             return 0;
0051         }
0052     }
0053 
0054     QElapsedTimer t;
0055     qint64 dataRead = 0;
0056     qint64 r = 0;
0057 
0058     // start the timer
0059     t.start();
0060 
0061     // read ten seconds of audio data. This is some value which seemed about right. :)
0062     while( dataRead < 2352*75*10 && (r = sourceReader.read( buffer, 2352LL*10LL )) > 0 ) {
0063         dataRead += r;
0064     }
0065 
0066     // elapsed millisec
0067     int usedT = t.elapsed();
0068 
0069     if( r < 0 ) {
0070         qDebug() << "(K3b::AudioMaxSpeedJob) read failure.";
0071         return -1;
0072     }
0073 
0074     // KB/sec (add 1 millisecond to avoid division by 0)
0075     int throughput = (dataRead*1000+usedT)/(usedT+1)/1024;
0076     qDebug() << "(K3b::AudioMaxSpeedJob) throughput: " << throughput
0077              << " (" << dataRead << "/" << usedT << ")" << Qt::endl;
0078 
0079 
0080     return throughput;
0081 }
0082 
0083 
0084 int K3b::AudioMaxSpeedJob::Private::maxSpeedByMedia() const
0085 {
0086     int s = 0;
0087 
0088     QList<int> speeds = doc->burner()->determineSupportedWriteSpeeds();
0089     // simply use what we have and let the writer decide if the speeds are empty
0090     if( !speeds.isEmpty() ) {
0091         // start with the highest speed and go down the list until we are below our max
0092         QList<int>::const_iterator it = speeds.constEnd();
0093         --it;
0094         while( *it > maxSpeed && it != speeds.constBegin() )
0095             --it;
0096 
0097         // this is the first valid speed or the lowest supported one
0098         s = *it;
0099         qDebug() << "(K3b::AudioMaxSpeedJob) using speed factor: " << (s/175);
0100     }
0101 
0102     return s;
0103 }
0104 
0105 
0106 
0107 
0108 K3b::AudioMaxSpeedJob::AudioMaxSpeedJob( K3b::AudioDoc* doc, K3b::JobHandler* jh, QObject* parent )
0109     : K3b::ThreadJob( jh, parent ),
0110       d( new Private() )
0111 {
0112     d->doc = doc;
0113     d->buffer = new char[2352*10];
0114 }
0115 
0116 
0117 K3b::AudioMaxSpeedJob::~AudioMaxSpeedJob()
0118 {
0119     delete [] d->buffer;
0120     delete d;
0121 }
0122 
0123 
0124 int K3b::AudioMaxSpeedJob::maxSpeed() const
0125 {
0126     return d->maxSpeedByMedia();
0127 }
0128 
0129 
0130 bool K3b::AudioMaxSpeedJob::run()
0131 {
0132     qDebug();
0133 
0134     K3b::AudioDataSourceIterator it( d->doc );
0135 
0136     // count sources for minimal progress info
0137     int numSources = 0;
0138     int sourcesDone = 0;
0139     while( it.current() ) {
0140         ++numSources;
0141         it.next();
0142     }
0143 
0144     bool success = true;
0145     d->maxSpeed = 175*1000;
0146     it.first();
0147 
0148     while( it.current() && !canceled() ) {
0149         QScopedPointer<QIODevice> sourceReader( it.current()->createReader() );
0150 
0151         if( !sourceReader->open( QIODevice::ReadOnly ) ) {
0152             qDebug() << "Cannot open source reader!";
0153             success = false;
0154             break;
0155         }
0156 
0157         // read some data
0158         int speed = d->speedTest( it.current(), *sourceReader );
0159 
0160         ++sourcesDone;
0161         emit percent( 100*numSources/sourcesDone );
0162 
0163         if( speed < 0 ) {
0164             success = false;
0165             break;
0166         }
0167         else if( speed > 0 ) {
0168             // update the max speed
0169             d->maxSpeed = qMin( d->maxSpeed, speed );
0170         }
0171 
0172         it.next();
0173     }
0174 
0175     if( canceled() ) {
0176         success = false;
0177     }
0178 
0179     if( success )
0180         qDebug() << "(K3b::AudioMaxSpeedJob) max speed: " << d->maxSpeed;
0181 
0182     return success;
0183 }
0184 
0185 #include "moc_k3baudiomaxspeedjob.cpp"