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 | |
49 | QT_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 | */ |
121 | QAudioOutput::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 | */ |
134 | QAudioOutput::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 | */ |
147 | QAudioOutput::~QAudioOutput() |
148 | { |
149 | delete d; |
150 | } |
151 | |
152 | /*! |
153 | Returns the QAudioFormat being used. |
154 | |
155 | */ |
156 | QAudioFormat 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 | */ |
175 | void 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 | */ |
197 | QIODevice* 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 | */ |
208 | void QAudioOutput::stop() |
209 | { |
210 | d->stop(); |
211 | } |
212 | |
213 | /*! |
214 | Drops all audio data in the buffers, resets buffers to zero. |
215 | |
216 | */ |
217 | void 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 | */ |
228 | void 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 | */ |
241 | void 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 | */ |
252 | int 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 | */ |
264 | int 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 | */ |
277 | void 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 | */ |
291 | int 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 | */ |
304 | void QAudioOutput::setNotifyInterval(int ms) |
305 | { |
306 | d->setNotifyInterval(ms); |
307 | } |
308 | |
309 | /*! |
310 | Returns the notify interval in milliseconds. |
311 | */ |
312 | int 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 | */ |
321 | qint64 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 | */ |
330 | qint64 QAudioOutput::elapsedUSecs() const |
331 | { |
332 | return d->elapsedUSecs(); |
333 | } |
334 | |
335 | /*! |
336 | Returns the error state. |
337 | */ |
338 | QAudio::Error QAudioOutput::error() const |
339 | { |
340 | return d->error(); |
341 | } |
342 | |
343 | /*! |
344 | Returns the state of audio processing. |
345 | */ |
346 | QAudio::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 | */ |
365 | void 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 | */ |
374 | qreal 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 | */ |
389 | QString 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 | */ |
409 | void 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 | |
427 | QT_END_NAMESPACE |
428 | |
429 | #include "moc_qaudiooutput.cpp" |
430 | |