Revision control
++ // Copyright (C) 2017 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
++
++ #include "audiodecoder.h"
++
++ #include <QtCore/qdebug.h>
++ #include <QtCore/qfile.h>
++
++ AudioDecoder::AudioDecoder(bool isPlayback, bool isDelete, const QString &targetFileName)
++ : m_cout(stdout, QIODevice::WriteOnly), m_targetFilename(targetFileName)
++ {
++ m_isPlayback = isPlayback;
++ m_isDelete = isDelete;
++
++ connect(&m_decoder, &QAudioDecoder::bufferReady, this, &AudioDecoder::bufferReady);
++ connect(&m_decoder, QOverload<QAudioDecoder::Error>::of(&QAudioDecoder::error), this,
++ QOverload<QAudioDecoder::Error>::of(&AudioDecoder::error));
++ connect(&m_decoder, &QAudioDecoder::isDecodingChanged, this, &AudioDecoder::isDecodingChanged);
++ connect(&m_decoder, &QAudioDecoder::finished, this, &AudioDecoder::finished);
++ connect(&m_decoder, &QAudioDecoder::positionChanged, this, &AudioDecoder::updateProgress);
++ connect(&m_decoder, &QAudioDecoder::durationChanged, this, &AudioDecoder::updateProgress);
++
++ connect(&m_soundEffect, &QSoundEffect::statusChanged, this,
++ &AudioDecoder::playbackStatusChanged);
++ connect(&m_soundEffect, &QSoundEffect::playingChanged, this, &AudioDecoder::playingChanged);
++
++ m_progress = -1.0;
++ }
++
++ AudioDecoder::~AudioDecoder()
++ {
++ delete m_waveDecoder;
++ }
++
++ void AudioDecoder::setSource(const QString &fileName)
++ {
++ m_decoder.setSource(QUrl::fromLocalFile(fileName));
++ }
++
++ void AudioDecoder::start()
++ {
++ m_decoder.start();
++ }
++
++ void AudioDecoder::stop()
++ {
++ m_decoder.stop();
++ }
++
++ QAudioDecoder::Error AudioDecoder::getError()
++ {
++ return m_decoder.error();
++ }
++
++ void AudioDecoder::setTargetFilename(const QString &fileName)
++ {
++ m_targetFilename = fileName;
++ }
++
++ void AudioDecoder::bufferReady()
++ {
++ // read a buffer from audio decoder
++ QAudioBuffer buffer = m_decoder.read();
++ if (!buffer.isValid())
++ return;
++
++ if (!m_waveDecoder) {
++ QIODevice *target = new QFile(m_targetFilename, this);
++ if (!target->open(QIODevice::WriteOnly)) {
++ qWarning() << "target file is not writable";
++ m_decoder.stop();
++ return;
++ }
++ QT_WARNING_PUSH
++ QT_WARNING_DISABLE_DEPRECATED
++ m_waveDecoder = new QWaveDecoder(target, buffer.format());
++ QT_WARNING_POP
++ }
++
++ if (!m_waveDecoder
++ || (!m_waveDecoder->isOpen() && !m_waveDecoder->open(QIODevice::WriteOnly))) {
++ m_decoder.stop();
++ return;
++ }
++
++ m_waveDecoder->write(buffer.constData<char>(), buffer.byteCount());
++ }
++
++ void AudioDecoder::error(QAudioDecoder::Error error)
++ {
++ switch (error) {
++ case QAudioDecoder::NoError:
++ return;
++ case QAudioDecoder::ResourceError:
++ m_cout << "Resource error\n";
++ break;
++ case QAudioDecoder::FormatError:
++ m_cout << "Format error\n";
++ break;
++ case QAudioDecoder::AccessDeniedError:
++ m_cout << "Access denied error\n";
++ break;
++ case QAudioDecoder::NotSupportedError:
++ m_cout << "Service missing error\n";
++ break;
++ }
++
++ emit done();
++ }
++
++ void AudioDecoder::isDecodingChanged(bool isDecoding)
++ {
++ if (isDecoding)
++ m_cout << "Decoding...\n";
++ else
++ m_cout << "Decoding stopped\n";
++ }
++
++ void AudioDecoder::finished()
++ {
++ m_waveDecoder->close();
++ m_cout << "Decoding finished\n";
++
++ if (m_isPlayback) {
++ m_cout << "Starting playback\n";
++ m_soundEffect.setSource(QUrl::fromLocalFile(m_targetFilename));
++ m_soundEffect.play();
++ } else {
++ emit done();
++ }
++ }
++
++ void AudioDecoder::playbackStatusChanged()
++ {
++ if (m_soundEffect.status() == QSoundEffect::Error) {
++ m_cout << "Playback error\n";
++ emit done();
++ }
++ }
++
++ void AudioDecoder::playingChanged()
++ {
++ if (!m_soundEffect.isPlaying()) {
++ m_cout << "Playback finished\n";
++ if (m_isDelete)
++ QFile::remove(m_targetFilename);
++ emit done();
++ }
++ }
++
++ void AudioDecoder::updateProgress()
++ {
++ qint64 position = m_decoder.position();
++ qint64 duration = m_decoder.duration();
++ qreal progress = m_progress;
++ if (position >= 0 && duration > 0)
++ progress = position / (qreal)duration;
++
++ if (progress > m_progress + 0.1) {
++ m_cout << "Decoding progress: " << (int)(progress * 100.0) << "%\n";
++ m_progress = progress;
++ }
++ }
++