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:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40
41#include "qaudio.h"
42#include "qaudiodeviceinfo.h"
43#include "qaudiosystem.h"
44#include "qaudiooutput.h"
45
46#include "qaudiodevicefactory_p.h"
47
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class QAudioOutput
53 \brief The QAudioOutput class provides an interface for sending audio data to an audio output device.
54
55 \inmodule QtMultimedia
56 \ingroup multimedia
57 \ingroup multimedia_audio
58
59 You can construct an audio output with the system's
60 \l{QAudioDeviceInfo::defaultOutputDevice()}{default audio output
61 device}. It is also possible to create QAudioOutput with a
62 specific QAudioDeviceInfo. When you create the audio output, you
63 should also send in the QAudioFormat to be used for the playback
64 (see the QAudioFormat class description for details).
65
66 To play a file:
67
68 Starting to play an audio stream is simply a matter of calling
69 start() with a QIODevice. QAudioOutput will then fetch the data it
70 needs from the io device. So playing back an audio file is as
71 simple as:
72
73 \snippet multimedia-snippets/audio.cpp Audio output class members
74
75 \snippet multimedia-snippets/audio.cpp Audio output setup
76
77 The file will start playing assuming that the audio system and
78 output device support it. If you run out of luck, check what's
79 up with the error() function.
80
81 After the file has finished playing, we need to stop the device:
82
83 \snippet multimedia-snippets/audio.cpp Audio output state changed
84
85 At any given time, the QAudioOutput will be in one of four states:
86 active, suspended, stopped, or idle. These states are described
87 by the QAudio::State enum.
88 State changes are reported through the stateChanged() signal. You
89 can use this signal to, for instance, update the GUI of the
90 application; the mundane example here being changing the state of
91 a \c { play/pause } button. You request a state change directly
92 with suspend(), stop(), reset(), resume(), and start().
93
94 While the stream is playing, you can set a notify interval in
95 milliseconds with setNotifyInterval(). This interval specifies the
96 time between two emissions of the notify() signal. This is
97 relative to the position in the stream, i.e., if the QAudioOutput
98 is in the SuspendedState or the IdleState, the notify() signal is
99 not emitted. A typical use-case would be to update a
100 \l{QSlider}{slider} that allows seeking in the stream.
101 If you want the time since playback started regardless of which
102 states the audio output has been in, elapsedUSecs() is the function for you.
103
104 If an error occurs, you can fetch the \l{QAudio::Error}{error
105 type} with the error() function. Please see the QAudio::Error enum
106 for a description of the possible errors that are reported. When
107 an error is encountered, the state changes to QAudio::StoppedState.
108 You can check for errors by connecting to the stateChanged()
109 signal:
110
111 \snippet multimedia-snippets/audio.cpp Audio output state changed
112
113 \sa QAudioInput, QAudioDeviceInfo
114*/
115
116/*!
117 Construct a new audio output and attach it to \a parent.
118 The default audio output device is used with the output
119 \a format parameters.
120*/
121QAudioOutput::QAudioOutput(const QAudioFormat &format, QObject *parent):
122 QObject(parent)
123{
124 d = QAudioDeviceFactory::createDefaultOutputDevice(format);
125 connect(asender: d, SIGNAL(notify()), SIGNAL(notify()));
126 connect(asender: d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
127}
128
129/*!
130 Construct a new audio output and attach it to \a parent.
131 The device referenced by \a audioDevice is used with the output
132 \a format parameters.
133*/
134QAudioOutput::QAudioOutput(const QAudioDeviceInfo &audioDevice, const QAudioFormat &format, QObject *parent):
135 QObject(parent)
136{
137 d = QAudioDeviceFactory::createOutputDevice(device: audioDevice, format);
138 connect(asender: d, SIGNAL(notify()), SIGNAL(notify()));
139 connect(asender: d, SIGNAL(stateChanged(QAudio::State)), SIGNAL(stateChanged(QAudio::State)));
140}
141
142/*!
143 Destroys this audio output.
144
145 This will release any system resources used and free any buffers.
146*/
147QAudioOutput::~QAudioOutput()
148{
149 delete d;
150}
151
152/*!
153 Returns the QAudioFormat being used.
154
155*/
156QAudioFormat QAudioOutput::format() const
157{
158 return d->format();
159}
160
161/*!
162 Starts transferring audio data from the \a device to the system's audio output.
163 The \a device must have been opened in the \l{QIODevice::ReadOnly}{ReadOnly} or
164 \l{QIODevice::ReadWrite}{ReadWrite} modes.
165
166 If the QAudioOutput is able to successfully output audio data, state() returns
167 QAudio::ActiveState, error() returns QAudio::NoError
168 and the stateChanged() signal is emitted.
169
170 If a problem occurs during this process, error() returns QAudio::OpenError,
171 state() returns QAudio::StoppedState and the stateChanged() signal is emitted.
172
173 \sa QIODevice
174*/
175void QAudioOutput::start(QIODevice* device)
176{
177 d->start(device);
178}
179
180/*!
181 Returns a pointer to the internal QIODevice being used to transfer data to
182 the system's audio output. The device will already be open and
183 \l{QIODevice::write()}{write()} can write data directly to it.
184
185 \note The pointer will become invalid after the stream is stopped or
186 if you start another stream.
187
188 If the QAudioOutput is able to access the system's audio device, state() returns
189 QAudio::IdleState, error() returns QAudio::NoError
190 and the stateChanged() signal is emitted.
191
192 If a problem occurs during this process, error() returns QAudio::OpenError,
193 state() returns QAudio::StoppedState and the stateChanged() signal is emitted.
194
195 \sa QIODevice
196*/
197QIODevice* QAudioOutput::start()
198{
199 return d->start();
200}
201
202/*!
203 Stops the audio output, detaching from the system resource.
204
205 Sets error() to QAudio::NoError, state() to QAudio::StoppedState and
206 emit stateChanged() signal.
207*/
208void QAudioOutput::stop()
209{
210 d->stop();
211}
212
213/*!
214 Drops all audio data in the buffers, resets buffers to zero.
215
216*/
217void QAudioOutput::reset()
218{
219 d->reset();
220}
221
222/*!
223 Stops processing audio data, preserving buffered audio data.
224
225 Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
226 emits stateChanged() signal.
227*/
228void QAudioOutput::suspend()
229{
230 d->suspend();
231}
232
233/*!
234 Resumes processing audio data after a suspend().
235
236 Sets error() to QAudio::NoError.
237 Sets state() to QAudio::ActiveState if you previously called start(QIODevice*).
238 Sets state() to QAudio::IdleState if you previously called start().
239 emits stateChanged() signal.
240*/
241void QAudioOutput::resume()
242{
243 d->resume();
244}
245
246/*!
247 Returns the number of free bytes available in the audio buffer.
248
249 \note The returned value is only valid while in QAudio::ActiveState or QAudio::IdleState
250 state, otherwise returns zero.
251*/
252int QAudioOutput::bytesFree() const
253{
254 return d->bytesFree();
255}
256
257/*!
258 Returns the period size in bytes. This is the amount of data required each period
259 to prevent buffer underrun, and to ensure uninterrupted playback.
260
261 \note It is recommended to provide at least enough data for a full period with each
262 write operation.
263*/
264int QAudioOutput::periodSize() const
265{
266 return d->periodSize();
267}
268
269/*!
270 Sets the audio buffer size to \a value in bytes.
271
272 \note This function can be called anytime before start(). Calls to this
273 are ignored after start(). It should not be assumed that the buffer size
274 set is the actual buffer size used - call bufferSize() anytime after start()
275 to return the actual buffer size being used.
276*/
277void QAudioOutput::setBufferSize(int value)
278{
279 d->setBufferSize(value);
280}
281
282/*!
283 Returns the audio buffer size in bytes.
284
285 If called before start(), returns platform default value.
286 If called before start() but setBufferSize() was called prior, returns value set by setBufferSize().
287 If called after start(), returns the actual buffer size being used. This may not be what was set previously
288 by setBufferSize().
289
290*/
291int QAudioOutput::bufferSize() const
292{
293 return d->bufferSize();
294}
295
296/*!
297 Sets the interval for notify() signal to be emitted.
298 This is based on the \a ms of audio data processed,
299 not on wall clock time.
300 The minimum resolution of the timer is platform specific and values
301 should be checked with notifyInterval() to confirm the actual value
302 being used.
303*/
304void QAudioOutput::setNotifyInterval(int ms)
305{
306 d->setNotifyInterval(ms);
307}
308
309/*!
310 Returns the notify interval in milliseconds.
311*/
312int QAudioOutput::notifyInterval() const
313{
314 return d->notifyInterval();
315}
316
317/*!
318 Returns the amount of audio data processed since start()
319 was called (in microseconds).
320*/
321qint64 QAudioOutput::processedUSecs() const
322{
323 return d->processedUSecs();
324}
325
326/*!
327 Returns the microseconds since start() was called, including time in Idle and
328 Suspend states.
329*/
330qint64 QAudioOutput::elapsedUSecs() const
331{
332 return d->elapsedUSecs();
333}
334
335/*!
336 Returns the error state.
337*/
338QAudio::Error QAudioOutput::error() const
339{
340 return d->error();
341}
342
343/*!
344 Returns the state of audio processing.
345*/
346QAudio::State QAudioOutput::state() const
347{
348 return d->state();
349}
350
351/*!
352 Sets the output volume to \a volume.
353
354 The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
355 range will be clamped.
356
357 The default volume is \c 1.0.
358
359 Note: Adjustments to the volume will change the volume of this audio stream, not the global volume.
360
361 UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
362 will produce linear changes in perceived loudness, which is what a user would normally expect
363 from a volume control. See QAudio::convertVolume() for more details.
364*/
365void QAudioOutput::setVolume(qreal volume)
366{
367 qreal v = qBound(min: qreal(0.0), val: volume, max: qreal(1.0));
368 d->setVolume(v);
369}
370
371/*!
372 Returns the volume between 0.0 and 1.0 inclusive.
373*/
374qreal QAudioOutput::volume() const
375{
376 return d->volume();
377}
378
379/*!
380 Returns the audio category of this audio stream.
381
382 Some platforms can group audio streams into categories
383 and manage their volumes independently, or display them
384 in a system mixer control. You can set this property to
385 allow the platform to distinguish the purpose of your streams.
386
387 \sa setCategory()
388*/
389QString QAudioOutput::category() const
390{
391 return d->category();
392}
393
394/*!
395 Sets the audio category of this audio stream to \a category.
396
397 Some platforms can group audio streams into categories
398 and manage their volumes independently, or display them
399 in a system mixer control. You can set this property to
400 allow the platform to distinguish the purpose of your streams.
401
402 Not all platforms support audio stream categorization. In this
403 case, the function call will be ignored.
404
405 Changing an audio output stream's category while it is opened
406 will not take effect until it is reopened.
407 \sa category()
408*/
409void QAudioOutput::setCategory(const QString &category)
410{
411 d->setCategory(category);
412}
413
414/*!
415 \fn QAudioOutput::stateChanged(QAudio::State state)
416 This signal is emitted when the device \a state has changed.
417 This is the current state of the audio output.
418*/
419
420/*!
421 \fn QAudioOutput::notify()
422 This signal is emitted when a certain interval of milliseconds
423 of audio data has been processed. The interval is set by
424 setNotifyInterval().
425*/
426
427QT_END_NAMESPACE
428
429#include "moc_qaudiooutput.cpp"
430

source code of qtmultimedia/src/multimedia/audio/qaudiooutput.cpp