1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#ifndef MOCKAUDIODECODERCONTROL_H
30#define MOCKAUDIODECODERCONTROL_H
31
32#include "qmediacontrol.h"
33#include "qaudiodecodercontrol.h"
34
35#include <QtCore/qpair.h>
36
37#include "qaudiobuffer.h"
38#include <QTimer>
39#include <QIODevice>
40
41#define MOCK_DECODER_MAX_BUFFERS 10
42
43QT_BEGIN_NAMESPACE
44
45class MockAudioDecoderControl : public QAudioDecoderControl
46{
47 Q_OBJECT
48
49public:
50 MockAudioDecoderControl(QObject *parent = 0)
51 : QAudioDecoderControl(parent)
52 , mState(QAudioDecoder::StoppedState)
53 , mDevice(0)
54 , mPosition(-1)
55 , mSerial(0)
56 {
57 mFormat.setChannelCount(1);
58 mFormat.setSampleSize(8);
59 mFormat.setSampleRate(1000);
60 mFormat.setCodec("audio/x-raw");
61 mFormat.setSampleType(QAudioFormat::UnSignedInt);
62 }
63
64 QAudioDecoder::State state() const
65 {
66 return mState;
67 }
68
69 QString sourceFilename() const
70 {
71 return mSource;
72 }
73
74 QAudioFormat audioFormat() const
75 {
76 return mFormat;
77 }
78
79 void setAudioFormat(const QAudioFormat &format)
80 {
81 if (mFormat != format) {
82 mFormat = format;
83 emit formatChanged(format: mFormat);
84 }
85 }
86
87 void setSourceFilename(const QString &fileName)
88 {
89 mSource = fileName;
90 mDevice = 0;
91 stop();
92 }
93
94 QIODevice* sourceDevice() const
95 {
96 return mDevice;
97 }
98
99 void setSourceDevice(QIODevice *device)
100 {
101 mDevice = device;
102 mSource.clear();
103 stop();
104 }
105
106 // When decoding we decode to first buffer, then second buffer
107 // we then stop until the first is read again and so on, for
108 // 5 buffers
109 void start()
110 {
111 if (mState == QAudioDecoder::StoppedState) {
112 if (!mSource.isEmpty()) {
113 mState = QAudioDecoder::DecodingState;
114 emit stateChanged(newState: mState);
115 emit durationChanged(duration: duration());
116
117 QTimer::singleShot(msec: 50, receiver: this, SLOT(pretendDecode()));
118 } else {
119 emit error(error: QAudioDecoder::ResourceError, errorString: "No source set");
120 }
121 }
122 }
123
124 void stop()
125 {
126 if (mState != QAudioDecoder::StoppedState) {
127 mState = QAudioDecoder::StoppedState;
128 mSerial = 0;
129 mPosition = 0;
130 mBuffers.clear();
131 emit stateChanged(newState: mState);
132 emit bufferAvailableChanged(available: false);
133 }
134 }
135
136 QAudioBuffer read()
137 {
138 QAudioBuffer a;
139 if (mBuffers.length() > 0) {
140 a = mBuffers.takeFirst();
141 mPosition = a.startTime() / 1000;
142 emit positionChanged(position: mPosition);
143
144 if (mBuffers.isEmpty())
145 emit bufferAvailableChanged(available: false);
146
147 if (mBuffers.isEmpty() && mSerial >= MOCK_DECODER_MAX_BUFFERS) {
148 mState = QAudioDecoder::StoppedState;
149 emit finished();
150 emit stateChanged(newState: mState);
151 } else
152 QTimer::singleShot(msec: 50, receiver: this, SLOT(pretendDecode()));
153 }
154
155 return a;
156 }
157
158 bool bufferAvailable() const
159 {
160 return mBuffers.length() > 0;
161 }
162
163 qint64 position() const
164 {
165 return mPosition;
166 }
167
168 qint64 duration() const
169 {
170 return (sizeof(mSerial) * MOCK_DECODER_MAX_BUFFERS * qint64(1000)) / (mFormat.sampleRate() * mFormat.channelCount());
171 }
172
173private slots:
174 void pretendDecode()
175 {
176 // Check if we've reached end of stream
177 if (mSerial >= MOCK_DECODER_MAX_BUFFERS)
178 return;
179
180 // We just keep the length of mBuffers to 3 or less.
181 if (mBuffers.length() < 3) {
182 QByteArray b(sizeof(mSerial), 0);
183 memcpy(dest: b.data(), src: &mSerial, n: sizeof(mSerial));
184 qint64 position = (sizeof(mSerial) * mSerial * qint64(1000000)) / (mFormat.sampleRate() * mFormat.channelCount());
185 mSerial++;
186 mBuffers.push_back(t: QAudioBuffer(b, mFormat, position));
187 emit bufferReady();
188 if (mBuffers.count() == 1)
189 emit bufferAvailableChanged(available: true);
190 }
191 }
192
193public:
194 QAudioDecoder::State mState;
195 QString mSource;
196 QIODevice *mDevice;
197 QAudioFormat mFormat;
198 qint64 mPosition;
199
200 int mSerial;
201 QList<QAudioBuffer> mBuffers;
202};
203
204QT_END_NAMESPACE
205
206#endif // QAUDIODECODERCONTROL_H
207

source code of qtmultimedia/tests/auto/unit/qmultimedia_common/mockaudiodecodercontrol.h