Revision control

++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "qmockaudiodecoder.h"
++
++ QT_BEGIN_NAMESPACE
++
++ QMockAudioDecoder::QMockAudioDecoder(QAudioDecoder *parent)
++ : QPlatformAudioDecoder(parent), mDevice(0), mSerial(0)
++ {
++ mFormat.setChannelCount(1);
++ mFormat.setSampleFormat(QAudioFormat::UInt8);
++ mFormat.setSampleRate(1000);
++ }
++
++ QUrl QMockAudioDecoder::source() const
++ {
++ return mSource;
++ }
++
++ void QMockAudioDecoder::setSource(const QUrl &fileName)
++ {
++ mSource = fileName;
++ mDevice = 0;
++ stop();
++ }
++
++ QIODevice *QMockAudioDecoder::sourceDevice() const
++ {
++ return mDevice;
++ }
++
++ void QMockAudioDecoder::setSourceDevice(QIODevice *device)
++ {
++ mDevice = device;
++ mSource.clear();
++ stop();
++ }
++
++ QAudioFormat QMockAudioDecoder::audioFormat() const
++ {
++ return mFormat;
++ }
++
++ void QMockAudioDecoder::setAudioFormat(const QAudioFormat &format)
++ {
++ if (mFormat != format) {
++ mFormat = format;
++ formatChanged(mFormat);
++ }
++ }
++
++ // When decoding we decode to first buffer, then second buffer
++ // we then stop until the first is read again and so on, for
++ // 5 buffers
++ void QMockAudioDecoder::start()
++ {
++ if (!isDecoding()) {
++ if (!mSource.isEmpty() || mDevice) {
++ setIsDecoding(true);
++ qint64 ms = (sizeof(mSerial) * MOCK_DECODER_MAX_BUFFERS * qint64(1000))
++ / (mFormat.sampleRate() * mFormat.channelCount());
++ durationChanged(std::chrono::milliseconds{ ms });
++
++ QTimer::singleShot(50, this, &QMockAudioDecoder::pretendDecode);
++ } else {
++ error(QAudioDecoder::ResourceError, "No source set");
++ }
++ }
++ }
++
++ void QMockAudioDecoder::stop()
++ {
++ if (isDecoding()) {
++ mSerial = 0;
++ mBuffers.clear();
++ setIsDecoding(false);
++ bufferAvailableChanged(false);
++ positionChanged(kInvalidPosition);
++ }
++ }
++
++ QAudioBuffer QMockAudioDecoder::read()
++ {
++ using namespace std::chrono;
++ QAudioBuffer a;
++ if (mBuffers.size() > 0) {
++ a = mBuffers.takeFirst();
++ // QAudioBuffer::startTime() is microseconds; store milliseconds
++ positionChanged(duration_cast<milliseconds>(microseconds{ a.startTime() }));
++
++ if (mBuffers.isEmpty())
++ bufferAvailableChanged(false);
++
++ if (mBuffers.isEmpty() && mSerial >= MOCK_DECODER_MAX_BUFFERS) {
++ finished();
++ } else
++ QTimer::singleShot(50, this, &QMockAudioDecoder::pretendDecode);
++ }
++
++ return a;
++ }
++
++ bool QMockAudioDecoder::bufferAvailable() const
++ {
++ return mBuffers.size() > 0;
++ }
++
++ void QMockAudioDecoder::pretendDecode()
++ {
++ // Check if we've reached end of stream
++ if (mSerial >= MOCK_DECODER_MAX_BUFFERS)
++ return;
++
++ // We just keep the length of mBuffers to 3 or less.
++ if (mBuffers.size() < 3) {
++ QByteArray b(sizeof(mSerial), 0);
++ memcpy(b.data(), &mSerial, sizeof(mSerial));
++ qint64 position = (sizeof(mSerial) * mSerial * qint64(1000000))
++ / (mFormat.sampleRate() * mFormat.channelCount());
++ mSerial++;
++ mBuffers.push_back(QAudioBuffer(b, mFormat, position));
++ bufferReady();
++ if (mBuffers.size() == 1)
++ bufferAvailableChanged(true);
++ }
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qmockaudiodecoder.cpp"