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#include <QtMultimedia/private/qtmultimediaglobal_p.h>
41#include "qsoundeffect.h"
42
43#if QT_CONFIG(pulseaudio)
44#include "qsoundeffect_pulse_p.h"
45#else
46#include "qsoundeffect_qaudio_p.h"
47#endif
48
49QT_BEGIN_NAMESPACE
50
51/*!
52 \class QSoundEffect
53 \brief The QSoundEffect class provides a way to play low latency sound effects.
54
55 \ingroup multimedia
56 \ingroup multimedia_audio
57 \inmodule QtMultimedia
58
59 This class allows you to play uncompressed audio files (typically WAV files) in
60 a generally lower latency way, and is suitable for "feedback" type sounds in
61 response to user actions (e.g. virtual keyboard sounds, positive or negative
62 feedback for popup dialogs, or game sounds). If low latency is not important,
63 consider using the QMediaPlayer class instead, since it supports a wider
64 variety of media formats and is less resource intensive.
65
66 This example shows how a looping, somewhat quiet sound effect
67 can be played:
68
69 \snippet multimedia-snippets/qsound.cpp 2
70
71 Typically the sound effect should be reused, which allows all the
72 parsing and preparation to be done ahead of time, and only triggered
73 when necessary. This assists with lower latency audio playback.
74
75 \snippet multimedia-snippets/qsound.cpp 3
76
77 Since QSoundEffect requires slightly more resources to achieve lower
78 latency playback, the platform may limit the number of simultaneously playing
79 sound effects.
80*/
81
82
83/*!
84 \qmltype SoundEffect
85 \instantiates QSoundEffect
86 \brief The SoundEffect type provides a way to play sound effects in QML.
87
88 \inmodule QtMultimedia
89 \ingroup multimedia_qml
90 \ingroup multimedia_audio_qml
91 \inqmlmodule QtMultimedia
92
93 This type allows you to play uncompressed audio files (typically WAV files) in
94 a generally lower latency way, and is suitable for "feedback" type sounds in
95 response to user actions (e.g. virtual keyboard sounds, positive or negative
96 feedback for popup dialogs, or game sounds). If low latency is not important,
97 consider using the MediaPlayer or Audio types instead, since they support a wider
98 variety of media formats and are less resource intensive.
99
100 Typically the sound effect should be reused, which allows all the
101 parsing and preparation to be done ahead of time, and only triggered
102 when necessary. This is easy to achieve with QML, since you can declare your
103 SoundEffect instance and refer to it elsewhere.
104
105 The following example plays a WAV file on mouse click.
106
107 \snippet multimedia-snippets/soundeffect.qml complete snippet
108
109 Since SoundEffect requires slightly more resources to achieve lower
110 latency playback, the platform may limit the number of simultaneously playing
111 sound effects.
112*/
113
114static QSoundEffectPrivate *initPrivate(QSoundEffect *self, QSoundEffectPrivate *d)
115{
116 QObject::connect(d, &QSoundEffectPrivate::loopsRemainingChanged, self, &QSoundEffect::loopsRemainingChanged);
117 QObject::connect(d, &QSoundEffectPrivate::volumeChanged, self, &QSoundEffect::volumeChanged);
118 QObject::connect(d, &QSoundEffectPrivate::mutedChanged, self, &QSoundEffect::mutedChanged);
119 QObject::connect(d, &QSoundEffectPrivate::loadedChanged, self, &QSoundEffect::loadedChanged);
120 QObject::connect(d, &QSoundEffectPrivate::playingChanged, self, &QSoundEffect::playingChanged);
121 QObject::connect(d, &QSoundEffectPrivate::statusChanged, self, &QSoundEffect::statusChanged);
122 QObject::connect(d, &QSoundEffectPrivate::categoryChanged, self, &QSoundEffect::categoryChanged);
123
124 return d;
125}
126/*!
127 Creates a QSoundEffect with the given \a parent.
128*/
129QSoundEffect::QSoundEffect(QObject *parent)
130 : QObject(parent)
131 , d(initPrivate(this, new QSoundEffectPrivate(this)))
132{
133}
134
135/*!
136 Creates a QSoundEffect with the given \a audioDevice and \a parent.
137*/
138QSoundEffect::QSoundEffect(const QAudioDeviceInfo &audioDevice, QObject *parent)
139 : QObject(parent)
140 , d(initPrivate(this, new QSoundEffectPrivate(audioDevice, this)))
141{
142}
143
144/*!
145 Destroys this sound effect.
146 */
147QSoundEffect::~QSoundEffect()
148{
149 d->release();
150}
151
152/*!
153 \fn QSoundEffect::supportedMimeTypes()
154
155 Returns a list of the supported mime types for this platform.
156*/
157QStringList QSoundEffect::supportedMimeTypes()
158{
159 return QSoundEffectPrivate::supportedMimeTypes();
160}
161
162/*!
163 \qmlproperty url QtMultimedia::SoundEffect::source
164
165 This property holds the url for the sound to play. For the SoundEffect
166 to attempt to load the source, the URL must exist and the application must have read permission
167 in the specified directory. If the desired source is a local file the URL may be specified
168 using either absolute or relative (to the file that declared the SoundEffect) pathing.
169*/
170/*!
171 \property QSoundEffect::source
172
173 This property holds the url for the sound to play. For the SoundEffect
174 to attempt to load the source, the URL must exist and the application must have read permission
175 in the specified directory.
176*/
177
178/*! Returns the URL of the current source to play */
179QUrl QSoundEffect::source() const
180{
181 return d->source();
182}
183
184/*! Set the current URL to play to \a url. */
185void QSoundEffect::setSource(const QUrl &url)
186{
187 if (d->source() == url)
188 return;
189
190 d->setSource(url);
191
192 emit sourceChanged();
193}
194
195/*!
196 \qmlproperty int QtMultimedia::SoundEffect::loops
197
198 This property holds the number of times the sound is played. A value of 0 or 1 means
199 the sound will be played only once; set to SoundEffect.Infinite to enable infinite looping.
200
201 The value can be changed while the sound effect is playing, in which case it will update
202 the remaining loops to the new value.
203*/
204
205/*!
206 \property QSoundEffect::loops
207 This property holds the number of times the sound is played. A value of 0 or 1 means
208 the sound will be played only once; set to SoundEffect.Infinite to enable infinite looping.
209
210 The value can be changed while the sound effect is playing, in which case it will update
211 the remaining loops to the new value.
212*/
213
214/*!
215 Returns the total number of times that this sound effect will be played before stopping.
216
217 See the \l loopsRemaining() method for the number of loops currently remaining.
218 */
219int QSoundEffect::loopCount() const
220{
221 return d->loopCount();
222}
223
224/*!
225 \enum QSoundEffect::Loop
226
227 \value Infinite Used as a parameter to \l setLoopCount() for infinite looping
228*/
229
230/*!
231 Set the total number of times to play this sound effect to \a loopCount.
232
233 Setting the loop count to 0 or 1 means the sound effect will be played only once;
234 pass \c QSoundEffect::Infinite to repeat indefinitely. The loop count can be changed while
235 the sound effect is playing, in which case it will update the remaining loops to
236 the new \a loopCount.
237
238 \sa loopsRemaining()
239*/
240void QSoundEffect::setLoopCount(int loopCount)
241{
242 if (loopCount < 0 && loopCount != Infinite) {
243 qWarning("SoundEffect: loops should be SoundEffect.Infinite, 0 or positive integer");
244 return;
245 }
246 if (loopCount == 0)
247 loopCount = 1;
248 if (d->loopCount() == loopCount)
249 return;
250
251 d->setLoopCount(loopCount);
252 emit loopCountChanged();
253}
254
255/*!
256 \qmlproperty int QtMultimedia::SoundEffect::loopsRemaining
257
258 This property contains the number of loops remaining before the sound effect
259 stops by itself, or SoundEffect.Infinite if that's what has been set in \l loops.
260*/
261/*!
262 \property QSoundEffect::loopsRemaining
263
264 This property contains the number of loops remaining before the sound effect
265 stops by itself, or QSoundEffect::Infinite if that's what has been set in \l loops.
266*/
267int QSoundEffect::loopsRemaining() const
268{
269 return d->loopsRemaining();
270}
271
272
273/*!
274 \qmlproperty qreal QtMultimedia::SoundEffect::volume
275
276 This property holds the volume of the sound effect playback.
277
278 The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
279 range will be clamped.
280
281 The default volume is \c 1.0.
282
283 UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
284 will produce linear changes in perceived loudness, which is what a user would normally expect
285 from a volume control. See \l {QtMultimedia::QtMultimedia::convertVolume()}{QtMultimedia.convertVolume()}
286 for more details.
287*/
288/*!
289 \property QSoundEffect::volume
290
291 This property holds the volume of the sound effect playback, from 0.0 (silence) to 1.0 (full volume).
292*/
293
294/*!
295 Returns the current volume of this sound effect, from 0.0 (silent) to 1.0 (maximum volume).
296 */
297qreal QSoundEffect::volume() const
298{
299 return d->volume();
300}
301
302/*!
303 Sets the sound effect volume to \a volume.
304
305 The volume is scaled linearly from \c 0.0 (silence) to \c 1.0 (full volume). Values outside this
306 range will be clamped.
307
308 The default volume is \c 1.0.
309
310 UI volume controls should usually be scaled nonlinearly. For example, using a logarithmic scale
311 will produce linear changes in perceived loudness, which is what a user would normally expect
312 from a volume control. See QAudio::convertVolume() for more details.
313 */
314void QSoundEffect::setVolume(qreal volume)
315{
316 volume = qBound(qreal(0.0), volume, qreal(1.0));
317 if (qFuzzyCompare(d->volume(), volume))
318 return;
319
320 d->setVolume(volume);
321}
322
323/*!
324 \qmlproperty bool QtMultimedia::SoundEffect::muted
325
326 This property provides a way to control muting. A value of \c true will mute this effect.
327 Otherwise, playback will occur with the currently specified \l volume.
328*/
329/*!
330 \property QSoundEffect::muted
331
332 This property provides a way to control muting. A value of \c true will mute this effect.
333*/
334
335/*! Returns whether this sound effect is muted */
336bool QSoundEffect::isMuted() const
337{
338 return d->isMuted();
339}
340
341/*!
342 Sets whether to mute this sound effect's playback.
343
344 If \a muted is true, playback will be muted (silenced),
345 and otherwise playback will occur with the currently
346 specified volume().
347*/
348void QSoundEffect::setMuted(bool muted)
349{
350 if (d->isMuted() == muted)
351 return;
352
353 d->setMuted(muted);
354}
355
356/*!
357 \fn QSoundEffect::isLoaded() const
358
359 Returns whether the sound effect has finished loading the \l source().
360*/
361/*!
362 \qmlmethod bool QtMultimedia::SoundEffect::isLoaded()
363
364 Returns whether the sound effect has finished loading the \l source.
365*/
366bool QSoundEffect::isLoaded() const
367{
368 return d->isLoaded();
369}
370
371/*!
372 \qmlmethod QtMultimedia::SoundEffect::play()
373
374 Start playback of the sound effect, looping the effect for the number of
375 times as specified in the loops property.
376
377 This is the default method for SoundEffect.
378
379 \snippet multimedia-snippets/soundeffect.qml play sound on click
380*/
381/*!
382 \fn QSoundEffect::play()
383
384 Start playback of the sound effect, looping the effect for the number of
385 times as specified in the loops property.
386*/
387void QSoundEffect::play()
388{
389 d->play();
390}
391
392/*!
393 \qmlproperty bool QtMultimedia::SoundEffect::playing
394
395 This property indicates whether the sound effect is playing or not.
396*/
397/*!
398 \property QSoundEffect::playing
399
400 This property indicates whether the sound effect is playing or not.
401*/
402
403/*! Returns true if the sound effect is currently playing, or false otherwise */
404bool QSoundEffect::isPlaying() const
405{
406 return d->isPlaying();
407}
408
409/*!
410 \enum QSoundEffect::Status
411
412 \value Null No source has been set or the source is null.
413 \value Loading The SoundEffect is trying to load the source.
414 \value Ready The source is loaded and ready for play.
415 \value Error An error occurred during operation, such as failure of loading the source.
416
417*/
418
419/*!
420 \qmlproperty enumeration QtMultimedia::SoundEffect::status
421
422 This property indicates the current status of the SoundEffect
423 as enumerated within SoundEffect.
424 Possible statuses are listed below.
425
426 \table
427 \header \li Value \li Description
428 \row \li SoundEffect.Null \li No source has been set or the source is null.
429 \row \li SoundEffect.Loading \li The SoundEffect is trying to load the source.
430 \row \li SoundEffect.Ready \li The source is loaded and ready for play.
431 \row \li SoundEffect.Error \li An error occurred during operation, such as failure of loading the source.
432 \endtable
433*/
434/*!
435 \property QSoundEffect::status
436
437 This property indicates the current status of the sound effect
438 from the \l QSoundEffect::Status enumeration.
439*/
440
441/*!
442 Returns the current status of this sound effect.
443 */
444QSoundEffect::Status QSoundEffect::status() const
445{
446 return d->status();
447}
448
449/*!
450 \qmlproperty string QtMultimedia::SoundEffect::category
451
452 This property contains the \e category of this sound effect.
453
454 Some platforms can perform different audio routing
455 for different categories, or may allow the user to
456 set different volume levels for different categories.
457
458 This setting will be ignored on platforms that do not
459 support audio categories.
460*/
461/*!
462 \property QSoundEffect::category
463
464 This property contains the \e category of this sound effect.
465
466 Some platforms can perform different audio routing
467 for different categories, or may allow the user to
468 set different volume levels for different categories.
469
470 This setting will be ignored on platforms that do not
471 support audio categories.
472*/
473/*!
474 Returns the current \e category for this sound effect.
475
476 Some platforms can perform different audio routing
477 for different categories, or may allow the user to
478 set different volume levels for different categories.
479
480 This setting will be ignored on platforms that do not
481 support audio categories.
482
483 \sa setCategory()
484*/
485QString QSoundEffect::category() const
486{
487 return d->category();
488}
489
490/*!
491 Sets the \e category of this sound effect to \a category.
492
493 Some platforms can perform different audio routing
494 for different categories, or may allow the user to
495 set different volume levels for different categories.
496
497 This setting will be ignored on platforms that do not
498 support audio categories.
499
500 If this setting is changed while a sound effect is playing
501 it will only take effect when the sound effect has stopped
502 playing.
503
504 \sa category()
505 */
506void QSoundEffect::setCategory(const QString &category)
507{
508 d->setCategory(category);
509}
510
511
512/*!
513 \qmlmethod QtMultimedia::SoundEffect::stop()
514
515 Stop current playback.
516
517 */
518/*!
519 \fn QSoundEffect::stop()
520
521 Stop current playback.
522
523 */
524void QSoundEffect::stop()
525{
526 d->stop();
527}
528
529/* Signals */
530
531/*!
532 \fn void QSoundEffect::sourceChanged()
533
534 The \c sourceChanged signal is emitted when the source has been changed.
535*/
536/*!
537 \qmlsignal QtMultimedia::SoundEffect::sourceChanged()
538
539 The \c sourceChanged signal is emitted when the source has been changed.
540
541 The corresponding handler is \c onSourceChanged.
542*/
543/*!
544 \fn void QSoundEffect::loadedChanged()
545
546 The \c loadedChanged signal is emitted when the loading state has changed.
547*/
548/*!
549 \qmlsignal QtMultimedia::SoundEffect::loadedChanged()
550
551 The \c loadedChanged signal is emitted when the loading state has changed.
552
553 The corresponding handler is \c onLoadedChanged.
554*/
555
556/*!
557 \fn void QSoundEffect::loopCountChanged()
558
559 The \c loopCountChanged signal is emitted when the initial number of loops has changed.
560*/
561/*!
562 \qmlsignal QtMultimedia::SoundEffect::loopCountChanged()
563
564 The \c loopCountChanged signal is emitted when the initial number of loops has changed.
565
566 The corresponding handler is \c onLoopCountChanged.
567*/
568
569/*!
570 \fn void QSoundEffect::loopsRemainingChanged()
571
572 The \c loopsRemainingChanged signal is emitted when the remaining number of loops has changed.
573*/
574/*!
575 \qmlsignal QtMultimedia::SoundEffect::loopsRemainingChanged()
576
577 The \c loopsRemainingChanged signal is emitted when the remaining number of loops has changed.
578
579 The corresponding handler is \c onLoopsRemainingChanged.
580*/
581
582/*!
583 \fn void QSoundEffect::volumeChanged()
584
585 The \c volumeChanged signal is emitted when the volume has changed.
586*/
587/*!
588 \qmlsignal QtMultimedia::SoundEffect::volumeChanged()
589
590 The \c volumeChanged signal is emitted when the volume has changed.
591
592 The corresponding handler is \c onVolumeChanged.
593*/
594
595/*!
596 \fn void QSoundEffect::mutedChanged()
597
598 The \c mutedChanged signal is emitted when the mute state has changed.
599*/
600/*!
601 \qmlsignal QtMultimedia::SoundEffect::mutedChanged()
602
603 The \c mutedChanged signal is emitted when the mute state has changed.
604
605 The corresponding handler is \c onMutedChanged.
606*/
607
608/*!
609 \fn void QSoundEffect::playingChanged()
610
611 The \c playingChanged signal is emitted when the playing property has changed.
612*/
613/*!
614 \qmlsignal QtMultimedia::SoundEffect::playingChanged()
615
616 The \c playingChanged signal is emitted when the playing property has changed.
617
618 The corresponding handler is \c onPlayingChanged.
619*/
620
621/*!
622 \fn void QSoundEffect::statusChanged()
623
624 The \c statusChanged signal is emitted when the status property has changed.
625*/
626/*!
627 \qmlsignal QtMultimedia::SoundEffect::statusChanged()
628
629 The \c statusChanged signal is emitted when the status property has changed.
630
631 The corresponding handler is \c onStatusChanged.
632*/
633
634/*!
635 \fn void QSoundEffect::categoryChanged()
636
637 The \c categoryChanged signal is emitted when the category property has changed.
638*/
639/*!
640 \qmlsignal QtMultimedia::SoundEffect::categoryChanged()
641
642 The \c categoryChanged signal is emitted when the category property has changed.
643
644 The corresponding handler is \c onCategoryChanged.
645*/
646
647
648QT_END_NAMESPACE
649
650#include "moc_qsoundeffect.cpp"
651