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//TESTED_COMPONENT=plugins/declarative/multimedia
30
31#include <QtTest/QtTest>
32
33#include "qdeclarativeaudio_p.h"
34#include "qdeclarativemediametadata_p.h"
35
36#include "mockmediaserviceprovider.h"
37#include "mockmediaplayerservice.h"
38
39#include <QtMultimedia/qmediametadata.h>
40#include <qmediaplayercontrol.h>
41#include <qmediaservice.h>
42#include <private/qmediaserviceprovider_p.h>
43#include <private/qdeclarativevideooutput_p.h>
44#include <qmetadatareadercontrol.h>
45#include <QAbstractVideoSurface>
46
47#include <QtGui/qguiapplication.h>
48#include <QtQml/qqmlengine.h>
49#include <QtQml/qqmlcomponent.h>
50
51class tst_QDeclarativeAudio : public QObject
52{
53 Q_OBJECT
54public slots:
55 void initTestCase();
56
57private slots:
58 void nullPlayerControl();
59 void nullMetaDataControl();
60 void nullService();
61
62 void source();
63 void autoLoad();
64 void playing();
65 void paused();
66 void duration();
67 void position();
68 void volume();
69 void muted();
70 void bufferProgress();
71 void seekable();
72 void playbackRate();
73 void status();
74 void metaData_data();
75 void metaData();
76 void error();
77 void loops();
78 void audioRole();
79 void customAudioRole();
80 void videoOutput();
81
82private:
83 void enumerator(const QMetaObject *object, const char *name, QMetaEnum *result);
84 QMetaEnum enumerator(const QMetaObject *object, const char *name);
85 void keyToValue(const QMetaEnum &enumeration, const char *key, int *result);
86 int keyToValue(const QMetaEnum &enumeration, const char *key);
87};
88
89Q_DECLARE_METATYPE(QDeclarativeAudio::Error);
90Q_DECLARE_METATYPE(QDeclarativeAudio::AudioRole);
91
92class QtTestMediaPlayerControl : public QMediaPlayerControl
93{
94 Q_OBJECT
95public:
96 QtTestMediaPlayerControl(QObject *parent = 0)
97 : QMediaPlayerControl(parent)
98 , m_state(QMediaPlayer::StoppedState)
99 , m_mediaStatus(QMediaPlayer::NoMedia)
100 , m_duration(0)
101 , m_position(0)
102 , m_playbackRate(1.0)
103 , m_volume(100)
104 , m_bufferStatus(0)
105 , m_muted(false)
106 , m_audioAvailable(false)
107 , m_videoAvailable(false)
108 , m_seekable(false)
109 {
110 }
111
112 QMediaPlayer::State state() const { return m_state; }
113 void updateState(QMediaPlayer::State state) { emit stateChanged(newState: m_state = state); }
114
115 QMediaPlayer::MediaStatus mediaStatus() const { return m_mediaStatus; }
116 void updateMediaStatus(QMediaPlayer::MediaStatus status) {
117 emit mediaStatusChanged(status: m_mediaStatus = status); }
118 void updateMediaStatus(QMediaPlayer::MediaStatus status, QMediaPlayer::State state)
119 {
120 m_mediaStatus = status;
121 m_state = state;
122
123 emit mediaStatusChanged(status: m_mediaStatus);
124 emit stateChanged(newState: m_state);
125 }
126
127 qint64 duration() const { return m_duration; }
128 void setDuration(qint64 duration) { emit durationChanged(duration: m_duration = duration); }
129
130 qint64 position() const { return m_position; }
131 void setPosition(qint64 position) { emit positionChanged(position: m_position = position); }
132
133 int volume() const { return m_volume; }
134 void setVolume(int volume) { emit volumeChanged(volume: m_volume = volume); }
135
136 bool isMuted() const { return m_muted; }
137 void setMuted(bool muted) { emit mutedChanged(mute: m_muted = muted); }
138
139 int bufferStatus() const { return m_bufferStatus; }
140 void setBufferStatus(int status) { emit bufferStatusChanged(percentFilled: m_bufferStatus = status); }
141
142 bool isAudioAvailable() const { return m_audioAvailable; }
143 void setAudioAvailable(bool available) {
144 emit audioAvailableChanged(audioAvailable: m_audioAvailable = available); }
145 bool isVideoAvailable() const { return m_videoAvailable; }
146 void setVideoAvailable(bool available) {
147 emit videoAvailableChanged(videoAvailable: m_videoAvailable = available); }
148
149 bool isSeekable() const { return m_seekable; }
150 void setSeekable(bool seekable) { emit seekableChanged(seekable: m_seekable = seekable); }
151
152 QMediaTimeRange availablePlaybackRanges() const { return QMediaTimeRange(); }
153
154 qreal playbackRate() const { return m_playbackRate; }
155 void setPlaybackRate(qreal rate) { emit playbackRateChanged(rate: m_playbackRate = rate); }
156
157 QMediaContent media() const { return m_media; }
158 const QIODevice *mediaStream() const { return 0; }
159 void setMedia(const QMediaContent &media, QIODevice *)
160 {
161 m_media = media;
162
163 m_mediaStatus = m_media.isNull()
164 ? QMediaPlayer::NoMedia
165 : QMediaPlayer::LoadingMedia;
166
167 emit mediaChanged(content: m_media);
168 emit mediaStatusChanged(status: m_mediaStatus);
169 }
170
171 void play()
172 {
173 m_state = QMediaPlayer::PlayingState;
174 if (m_mediaStatus == QMediaPlayer::EndOfMedia)
175 updateMediaStatus(status: QMediaPlayer::LoadedMedia);
176 emit stateChanged(newState: m_state);
177 }
178 void pause() { emit stateChanged(newState: m_state = QMediaPlayer::PausedState); }
179 void stop() { emit stateChanged(newState: m_state = QMediaPlayer::StoppedState); }
180
181 void emitError(QMediaPlayer::Error err, const QString &errorString) {
182 emit error(error: err, errorString); }
183
184private:
185 QMediaPlayer::State m_state;
186 QMediaPlayer::MediaStatus m_mediaStatus;
187 qint64 m_duration;
188 qint64 m_position;
189 qreal m_playbackRate;
190 int m_volume;
191 int m_bufferStatus;
192 bool m_muted;
193 bool m_audioAvailable;
194 bool m_videoAvailable;
195 bool m_seekable;
196 QMediaContent m_media;
197};
198
199class QtTestMetaDataControl : public QMetaDataReaderControl
200{
201 Q_OBJECT
202public:
203 QtTestMetaDataControl(QObject *parent = 0)
204 : QMetaDataReaderControl(parent)
205 {
206 }
207
208 bool isMetaDataAvailable() const { return true; }
209
210 QVariant metaData(const QString &key) const { return m_metaData.value(akey: key); }
211 void setMetaData(const QString &key, const QVariant &value) {
212 m_metaData.insert(key, value); emit metaDataChanged(); }
213
214 QStringList availableMetaData() const { return m_metaData.keys(); }
215
216private:
217 QMap<QString, QVariant> m_metaData;
218};
219
220class QtTestMediaService : public QMediaService
221{
222 Q_OBJECT
223public:
224 QtTestMediaService(
225 QtTestMediaPlayerControl *playerControl,
226 QtTestMetaDataControl *metaDataControl,
227 QObject *parent)
228 : QMediaService(parent)
229 , playerControl(playerControl)
230 , metaDataControl(metaDataControl)
231 {
232 }
233
234 QMediaControl *requestControl(const char *name)
235 {
236 if (qstrcmp(str1: name, QMediaPlayerControl_iid) == 0)
237 return playerControl;
238 else if (qstrcmp(str1: name, QMetaDataReaderControl_iid) == 0)
239 return metaDataControl;
240 else
241 return 0;
242 }
243
244 void releaseControl(QMediaControl *) {}
245
246 QtTestMediaPlayerControl *playerControl;
247 QtTestMetaDataControl *metaDataControl;
248};
249
250class QtTestMediaServiceProvider : public QMediaServiceProvider
251{
252 Q_OBJECT
253public:
254 QtTestMediaServiceProvider()
255 : service(new QtTestMediaService(
256 new QtTestMediaPlayerControl(this), new QtTestMetaDataControl(this), this))
257 {
258 setDefaultServiceProvider(this);
259 }
260
261 QtTestMediaServiceProvider(QtTestMediaService *service)
262 : service(service)
263 {
264 setDefaultServiceProvider(this);
265 }
266
267 QtTestMediaServiceProvider(
268 QtTestMediaPlayerControl *playerControl, QtTestMetaDataControl *metaDataControl)
269 : service(new QtTestMediaService(playerControl, metaDataControl, this))
270 {
271 setDefaultServiceProvider(this);
272 }
273
274 ~QtTestMediaServiceProvider()
275 {
276 setDefaultServiceProvider(0);
277 }
278
279 QMediaService *requestService(
280 const QByteArray &type,
281 const QMediaServiceProviderHint & = QMediaServiceProviderHint())
282 {
283 requestedService = type;
284
285 return service;
286 }
287
288 void releaseService(QMediaService *) {}
289
290 inline QtTestMediaPlayerControl *playerControl() { return service->playerControl; }
291 inline QtTestMetaDataControl *metaDataControl() { return service->metaDataControl; }
292
293 QtTestMediaService *service;
294 QByteArray requestedService;
295};
296
297void tst_QDeclarativeAudio::initTestCase()
298{
299 qRegisterMetaType<QDeclarativeAudio::Error>();
300 qRegisterMetaType<QDeclarativeAudio::AudioRole>();
301}
302
303void tst_QDeclarativeAudio::nullPlayerControl()
304{
305 QtTestMetaDataControl metaDataControl;
306 QtTestMediaServiceProvider provider(0, &metaDataControl);
307
308 QDeclarativeAudio audio;
309 audio.classBegin();
310
311 QCOMPARE(audio.source(), QUrl());
312 audio.setSource(QUrl("http://example.com"));
313 QCOMPARE(audio.source(), QUrl("http://example.com"));
314
315 QCOMPARE(audio.playbackState(), audio.StoppedState);
316 audio.play();
317 QCOMPARE(audio.playbackState(), audio.StoppedState);
318 audio.pause();
319 QCOMPARE(audio.playbackState(), audio.StoppedState);
320
321 QCOMPARE(audio.duration(), 0);
322
323 QCOMPARE(audio.position(), 0);
324 audio.seek(position: 10000);
325 QCOMPARE(audio.position(), 10000);
326
327 QCOMPARE(audio.volume(), qreal(1.0));
328 audio.setVolume(0.5);
329 QCOMPARE(audio.volume(), qreal(0.5));
330
331 QCOMPARE(audio.isMuted(), false);
332 audio.setMuted(true);
333 QCOMPARE(audio.isMuted(), true);
334
335 QCOMPARE(audio.bufferProgress(), qreal(0));
336
337 QCOMPARE(audio.isSeekable(), false);
338
339 QCOMPARE(audio.playbackRate(), qreal(1.0));
340
341 QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
342
343 QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing);
344}
345
346void tst_QDeclarativeAudio::nullMetaDataControl()
347{
348 QtTestMediaPlayerControl playerControl;
349 QtTestMediaServiceProvider provider(&playerControl, 0);
350
351 QDeclarativeAudio audio;
352 audio.classBegin();
353 audio.componentComplete();
354
355 QVERIFY(audio.metaData());
356}
357
358void tst_QDeclarativeAudio::nullService()
359{
360 QtTestMediaServiceProvider provider(0);
361
362 QDeclarativeAudio audio;
363 audio.classBegin();
364
365 QCOMPARE(audio.source(), QUrl());
366 audio.setSource(QUrl("http://example.com"));
367 QCOMPARE(audio.source(), QUrl("http://example.com"));
368
369 QCOMPARE(audio.playbackState(), audio.StoppedState);
370 audio.play();
371 QCOMPARE(audio.playbackState(), audio.StoppedState);
372 audio.pause();
373 QCOMPARE(audio.playbackState(), audio.StoppedState);
374
375 QCOMPARE(audio.duration(), 0);
376
377 QCOMPARE(audio.position(), 0);
378 audio.seek(position: 10000);
379 QCOMPARE(audio.position(), 10000);
380
381 QCOMPARE(audio.volume(), qreal(1.0));
382 audio.setVolume(0.5);
383 QCOMPARE(audio.volume(), qreal(0.5));
384
385 QCOMPARE(audio.isMuted(), false);
386 audio.setMuted(true);
387 QCOMPARE(audio.isMuted(), true);
388
389 QCOMPARE(audio.bufferProgress(), qreal(0));
390
391 QCOMPARE(audio.isSeekable(), false);
392
393 QCOMPARE(audio.playbackRate(), qreal(1.0));
394
395 QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
396
397 QCOMPARE(audio.error(), QDeclarativeAudio::ServiceMissing);
398
399 QVERIFY(audio.metaData());
400}
401
402void tst_QDeclarativeAudio::source()
403{
404 const QUrl url1("http://example.com");
405 const QUrl url2("file:///local/path");
406 const QUrl url3;
407
408 QtTestMediaServiceProvider provider;
409 QDeclarativeAudio audio;
410 audio.classBegin();
411 audio.componentComplete();
412
413 QSignalSpy spy(&audio, SIGNAL(sourceChanged()));
414
415 audio.setSource(url1);
416 QCOMPARE(audio.source(), url1);
417 QCOMPARE(provider.playerControl()->media().request().url(), url1);
418 QCOMPARE(spy.count(), 1);
419
420 audio.setSource(url2);
421 QCOMPARE(audio.source(), url2);
422 QCOMPARE(provider.playerControl()->media().request().url(), url2);
423 QCOMPARE(spy.count(), 2);
424
425 audio.setSource(url3);
426 QCOMPARE(audio.source(), url3);
427 QCOMPARE(provider.playerControl()->media().request().url(), url3);
428 QCOMPARE(spy.count(), 3);
429}
430
431void tst_QDeclarativeAudio::autoLoad()
432{
433 QtTestMediaServiceProvider provider;
434 QDeclarativeAudio audio;
435 audio.classBegin();
436 audio.componentComplete();
437
438 QSignalSpy spy(&audio, SIGNAL(autoLoadChanged()));
439
440 QCOMPARE(audio.isAutoLoad(), true);
441
442 audio.setAutoLoad(false);
443 QCOMPARE(audio.isAutoLoad(), false);
444 QCOMPARE(spy.count(), 1);
445
446 audio.setSource(QUrl("http://example.com"));
447 QCOMPARE(audio.source(), QUrl("http://example.com"));
448 audio.play();
449 QCOMPARE(audio.playbackState(), audio.PlayingState);
450 audio.stop();
451
452 audio.setAutoLoad(true);
453 audio.setSource(QUrl("http://example.com"));
454 audio.pause();
455 QCOMPARE(spy.count(), 2);
456 QCOMPARE(audio.playbackState(), audio.PausedState);
457}
458
459void tst_QDeclarativeAudio::playing()
460{
461 QtTestMediaServiceProvider provider;
462 QDeclarativeAudio audio;
463 audio.classBegin();
464
465 QSignalSpy stateChangedSpy(&audio, SIGNAL(playbackStateChanged()));
466 QSignalSpy playingSpy(&audio, SIGNAL(playing()));
467 QSignalSpy stoppedSpy(&audio, SIGNAL(stopped()));
468
469 int stateChanged = 0;
470 int playing = 0;
471 int stopped = 0;
472
473 audio.componentComplete();
474 audio.setSource(QUrl("http://example.com"));
475
476 QCOMPARE(audio.playbackState(), audio.StoppedState);
477
478 // play() when stopped.
479 audio.play();
480 QCOMPARE(audio.playbackState(), audio.PlayingState);
481 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
482 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
483 QCOMPARE(playingSpy.count(), ++playing);
484 QCOMPARE(stoppedSpy.count(), stopped);
485
486 // stop() when playing.
487 audio.stop();
488 QCOMPARE(audio.playbackState(), audio.StoppedState);
489 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
490 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
491 QCOMPARE(playingSpy.count(), playing);
492 QCOMPARE(stoppedSpy.count(), ++stopped);
493
494 // stop() when stopped.
495 audio.stop();
496 QCOMPARE(audio.playbackState(), audio.StoppedState);
497 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
498 QCOMPARE(stateChangedSpy.count(), stateChanged);
499 QCOMPARE(playingSpy.count(), playing);
500 QCOMPARE(stoppedSpy.count(), stopped);
501
502 audio.play();
503 QCOMPARE(audio.playbackState(), audio.PlayingState);
504 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
505 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
506 QCOMPARE(playingSpy.count(), ++playing);
507 QCOMPARE(stoppedSpy.count(), stopped);
508
509 // play() when playing.
510 audio.play();
511 QCOMPARE(audio.playbackState(), audio.PlayingState);
512 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
513 QCOMPARE(stateChangedSpy.count(), stateChanged);
514 QCOMPARE(playingSpy.count(), playing);
515 QCOMPARE(stoppedSpy.count(), stopped);
516}
517
518void tst_QDeclarativeAudio::paused()
519{
520 QtTestMediaServiceProvider provider;
521 QDeclarativeAudio audio;
522 audio.classBegin();
523
524 QSignalSpy stateChangedSpy(&audio, SIGNAL(playbackStateChanged()));
525 QSignalSpy pausedSpy(&audio, SIGNAL(paused()));
526 int stateChanged = 0;
527 int pausedCount = 0;
528
529 audio.componentComplete();
530 audio.setSource(QUrl("http://example.com"));
531
532 QCOMPARE(audio.playbackState(), audio.StoppedState);
533
534 // play() when stopped.
535 audio.play();
536 QCOMPARE(audio.playbackState(), audio.PlayingState);
537 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
538 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
539 QCOMPARE(pausedSpy.count(), pausedCount);
540
541 // pause() when playing.
542 audio.pause();
543 QCOMPARE(audio.playbackState(), audio.PausedState);
544 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
545 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
546 QCOMPARE(pausedSpy.count(), ++pausedCount);
547
548 // pause() when paused.
549 audio.pause();
550 QCOMPARE(audio.playbackState(), audio.PausedState);
551 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
552 QCOMPARE(stateChangedSpy.count(), stateChanged);
553 QCOMPARE(pausedSpy.count(), pausedCount);
554
555 // stop() when paused.
556 audio.stop();
557 QCOMPARE(audio.playbackState(), audio.StoppedState);
558 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
559 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
560 QCOMPARE(pausedSpy.count(), pausedCount);
561
562 // pause() when stopped.
563 audio.pause();
564 QCOMPARE(audio.playbackState(), audio.PausedState);
565 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PausedState);
566 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
567 QCOMPARE(pausedSpy.count(), ++pausedCount);
568
569 // play() when paused.
570 audio.play();
571 QCOMPARE(audio.playbackState(), audio.PlayingState);
572 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
573 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
574 QCOMPARE(pausedSpy.count(), pausedCount);
575}
576
577void tst_QDeclarativeAudio::duration()
578{
579 QtTestMediaServiceProvider provider;
580 QDeclarativeAudio audio;
581 audio.classBegin();
582 audio.componentComplete();
583
584 QSignalSpy spy(&audio, SIGNAL(durationChanged()));
585
586 QCOMPARE(audio.duration(), 0);
587
588 provider.playerControl()->setDuration(4040);
589 QCOMPARE(audio.duration(), 4040);
590 QCOMPARE(spy.count(), 1);
591
592 provider.playerControl()->setDuration(-129);
593 QCOMPARE(audio.duration(), -129);
594 QCOMPARE(spy.count(), 2);
595
596 provider.playerControl()->setDuration(0);
597 QCOMPARE(audio.duration(), 0);
598 QCOMPARE(spy.count(), 3);
599
600 // Unnecessary duration changed signals aren't filtered.
601 provider.playerControl()->setDuration(0);
602 QCOMPARE(audio.duration(), 0);
603 QCOMPARE(spy.count(), 4);
604}
605
606void tst_QDeclarativeAudio::position()
607{
608 QtTestMediaServiceProvider provider;
609 QDeclarativeAudio audio;
610 audio.classBegin();
611 audio.componentComplete();
612
613 QSignalSpy spy(&audio, SIGNAL(positionChanged()));
614
615 QCOMPARE(audio.position(), 0);
616
617 // QDeclarativeAudio won't bound set positions to the duration. A media service may though.
618 QCOMPARE(audio.duration(), 0);
619
620 audio.seek(position: 450);
621 QCOMPARE(audio.position(), 450);
622 QCOMPARE(provider.playerControl()->position(), qint64(450));
623 QCOMPARE(spy.count(), 1);
624
625 audio.seek(position: -5403);
626 QCOMPARE(audio.position(), 0);
627 QCOMPARE(provider.playerControl()->position(), qint64(0));
628 QCOMPARE(spy.count(), 2);
629
630 audio.seek(position: -5403);
631 QCOMPARE(audio.position(), 0);
632 QCOMPARE(provider.playerControl()->position(), qint64(0));
633 QCOMPARE(spy.count(), 2);
634
635 // Check the signal change signal is emitted if the change originates from the media service.
636 provider.playerControl()->setPosition(450);
637 QCOMPARE(audio.position(), 450);
638 QCOMPARE(spy.count(), 3);
639
640 connect(sender: &audio, SIGNAL(positionChanged()), receiver: &QTestEventLoop::instance(), SLOT(exitLoop()));
641
642 provider.playerControl()->updateState(state: QMediaPlayer::PlayingState);
643 QTestEventLoop::instance().enterLoop(secs: 2);
644 QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5
645
646 provider.playerControl()->updateState(state: QMediaPlayer::PausedState);
647 QTestEventLoop::instance().enterLoop(secs: 1);
648 QVERIFY(spy.count() < 6);
649}
650
651void tst_QDeclarativeAudio::volume()
652{
653 QtTestMediaServiceProvider provider;
654 QDeclarativeAudio audio;
655 audio.classBegin();
656 audio.componentComplete();
657
658 QSignalSpy spy(&audio, SIGNAL(volumeChanged()));
659
660 QCOMPARE(audio.volume(), qreal(1.0));
661
662 audio.setVolume(0.7);
663 QCOMPARE(audio.volume(), qreal(0.7));
664 QCOMPARE(provider.playerControl()->volume(), 70);
665 QCOMPARE(spy.count(), 1);
666
667 audio.setVolume(0.7);
668 QCOMPARE(audio.volume(), qreal(0.7));
669 QCOMPARE(provider.playerControl()->volume(), 70);
670 QCOMPARE(spy.count(), 1);
671
672 provider.playerControl()->setVolume(30);
673 QCOMPARE(audio.volume(), qreal(0.3));
674 QCOMPARE(spy.count(), 2);
675}
676
677void tst_QDeclarativeAudio::muted()
678{
679 QtTestMediaServiceProvider provider;
680 QDeclarativeAudio audio;
681 audio.classBegin();
682 audio.componentComplete();
683
684 QSignalSpy spy(&audio, SIGNAL(mutedChanged()));
685
686 QCOMPARE(audio.isMuted(), false);
687
688 audio.setMuted(true);
689 QCOMPARE(audio.isMuted(), true);
690 QCOMPARE(provider.playerControl()->isMuted(), true);
691 QCOMPARE(spy.count(), 1);
692
693 provider.playerControl()->setMuted(false);
694 QCOMPARE(audio.isMuted(), false);
695 QCOMPARE(spy.count(), 2);
696
697 audio.setMuted(false);
698 QCOMPARE(audio.isMuted(), false);
699 QCOMPARE(provider.playerControl()->isMuted(), false);
700 QCOMPARE(spy.count(), 2);
701}
702
703void tst_QDeclarativeAudio::bufferProgress()
704{
705 QtTestMediaServiceProvider provider;
706 QDeclarativeAudio audio;
707 audio.classBegin();
708 audio.componentComplete();
709
710 QSignalSpy spy(&audio, SIGNAL(bufferProgressChanged()));
711
712 QCOMPARE(audio.bufferProgress(), qreal(0.0));
713
714 provider.playerControl()->setBufferStatus(20);
715 QCOMPARE(audio.bufferProgress(), qreal(0.2));
716 QCOMPARE(spy.count(), 1);
717
718 provider.playerControl()->setBufferStatus(20);
719 QCOMPARE(audio.bufferProgress(), qreal(0.2));
720 QCOMPARE(spy.count(), 2);
721
722 provider.playerControl()->setBufferStatus(40);
723 QCOMPARE(audio.bufferProgress(), qreal(0.4));
724 QCOMPARE(spy.count(), 3);
725
726 connect(sender: &audio, SIGNAL(positionChanged()), receiver: &QTestEventLoop::instance(), SLOT(exitLoop()));
727
728 provider.playerControl()->updateMediaStatus(
729 status: QMediaPlayer::BufferingMedia, state: QMediaPlayer::PlayingState);
730 QTestEventLoop::instance().enterLoop(secs: 2);
731 QVERIFY(spy.count() > 3 && spy.count() < 6); // 4 or 5
732
733 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferedMedia);
734 QTestEventLoop::instance().enterLoop(secs: 1);
735 QVERIFY(spy.count() < 6);
736}
737
738void tst_QDeclarativeAudio::seekable()
739{
740 QtTestMediaServiceProvider provider;
741 QDeclarativeAudio audio;
742 audio.classBegin();
743 audio.componentComplete();
744
745 QSignalSpy spy(&audio, SIGNAL(seekableChanged()));
746
747 QCOMPARE(audio.isSeekable(), false);
748
749 provider.playerControl()->setSeekable(true);
750 QCOMPARE(audio.isSeekable(), true);
751 QCOMPARE(spy.count(), 1);
752
753 provider.playerControl()->setSeekable(true);
754 QCOMPARE(audio.isSeekable(), true);
755 QCOMPARE(spy.count(), 2);
756
757 provider.playerControl()->setSeekable(false);
758 QCOMPARE(audio.isSeekable(), false);
759 QCOMPARE(spy.count(), 3);
760}
761
762void tst_QDeclarativeAudio::playbackRate()
763{
764 QtTestMediaServiceProvider provider;
765 QDeclarativeAudio audio;
766 audio.classBegin();
767 audio.componentComplete();
768
769 QSignalSpy spy(&audio, SIGNAL(playbackRateChanged()));
770
771 QCOMPARE(audio.playbackRate(), qreal(1.0));
772
773 audio.setPlaybackRate(0.5);
774 QCOMPARE(audio.playbackRate(), qreal(0.5));
775 QCOMPARE(provider.playerControl()->playbackRate(), qreal(0.5));
776 QCOMPARE(spy.count(), 1);
777
778 provider.playerControl()->setPlaybackRate(2.0);
779 QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0));
780 QCOMPARE(spy.count(), 2);
781
782 audio.setPlaybackRate(2.0);
783 QCOMPARE(audio.playbackRate(), qreal(2.0));
784 QCOMPARE(provider.playerControl()->playbackRate(), qreal(2.0));
785 QCOMPARE(spy.count(), 2);
786}
787
788void tst_QDeclarativeAudio::status()
789{
790 QtTestMediaServiceProvider provider;
791 QDeclarativeAudio audio;
792 audio.classBegin();
793 audio.componentComplete();
794
795 QSignalSpy statusChangedSpy(&audio, SIGNAL(statusChanged()));
796
797 QCOMPARE(audio.status(), QDeclarativeAudio::NoMedia);
798
799 // Set media, start loading.
800 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::LoadingMedia);
801 QCOMPARE(audio.status(), QDeclarativeAudio::Loading);
802 QCOMPARE(statusChangedSpy.count(), 1);
803
804 // Finish loading.
805 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::LoadedMedia);
806 QCOMPARE(audio.status(), QDeclarativeAudio::Loaded);
807 QCOMPARE(statusChangedSpy.count(), 2);
808
809 // Play, start buffering.
810 provider.playerControl()->updateMediaStatus(
811 status: QMediaPlayer::StalledMedia, state: QMediaPlayer::PlayingState);
812 QCOMPARE(audio.status(), QDeclarativeAudio::Stalled);
813 QCOMPARE(statusChangedSpy.count(), 3);
814
815 // Enough data buffered to proceed.
816 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferingMedia);
817 QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
818 QCOMPARE(statusChangedSpy.count(), 4);
819
820 // Errant second buffering status changed.
821 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferingMedia);
822 QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
823 QCOMPARE(statusChangedSpy.count(), 4);
824
825 // Buffer full.
826 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferedMedia);
827 QCOMPARE(audio.status(), QDeclarativeAudio::Buffered);
828 QCOMPARE(statusChangedSpy.count(), 5);
829
830 // Buffer getting low.
831 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferingMedia);
832 QCOMPARE(audio.status(), QDeclarativeAudio::Buffering);
833 QCOMPARE(statusChangedSpy.count(), 6);
834
835 // Buffer full.
836 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::BufferedMedia);
837 QCOMPARE(audio.status(), QDeclarativeAudio::Buffered);
838 QCOMPARE(statusChangedSpy.count(), 7);
839
840 // Finished.
841 provider.playerControl()->updateMediaStatus(
842 status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
843 QCOMPARE(audio.status(), QDeclarativeAudio::EndOfMedia);
844 QCOMPARE(statusChangedSpy.count(), 8);
845}
846
847void tst_QDeclarativeAudio::metaData_data()
848{
849 QTest::addColumn<QByteArray>(name: "propertyName");
850 QTest::addColumn<QString>(name: "propertyKey");
851 QTest::addColumn<QVariant>(name: "value");
852
853 QTest::newRow(dataTag: "title")
854 << QByteArray("title")
855 << QMediaMetaData::Title
856 << QVariant(QString::fromLatin1(str: "This is a title"));
857
858 QTest::newRow(dataTag: "genre")
859 << QByteArray("genre")
860 << QMediaMetaData::Genre
861 << QVariant(QString::fromLatin1(str: "rock"));
862
863 QTest::newRow(dataTag: "trackNumber")
864 << QByteArray("trackNumber")
865 << QMediaMetaData::TrackNumber
866 << QVariant(8);
867}
868
869void tst_QDeclarativeAudio::metaData()
870{
871 QFETCH(QByteArray, propertyName);
872 QFETCH(QString, propertyKey);
873 QFETCH(QVariant, value);
874
875 QtTestMediaServiceProvider provider;
876 QDeclarativeAudio audio;
877 audio.classBegin();
878 audio.componentComplete();
879
880 QSignalSpy spy(audio.metaData(), SIGNAL(metaDataChanged()));
881
882 const int index = audio.metaData()->metaObject()->indexOfProperty(name: propertyName.constData());
883 QVERIFY(index != -1);
884
885 QMetaProperty property = audio.metaData()->metaObject()->property(index);
886 QCOMPARE(property.read(&audio), QVariant());
887
888 property.write(obj: audio.metaData(), value);
889 QCOMPARE(property.read(audio.metaData()), QVariant());
890 QCOMPARE(provider.metaDataControl()->metaData(propertyKey), QVariant());
891 QCOMPARE(spy.count(), 0);
892
893 provider.metaDataControl()->setMetaData(key: propertyKey, value);
894 QCOMPARE(property.read(audio.metaData()), value);
895 QCOMPARE(spy.count(), 1);
896}
897
898void tst_QDeclarativeAudio::error()
899{
900 const QString errorString = QLatin1String("Failed to open device.");
901
902 QtTestMediaServiceProvider provider;
903 QDeclarativeAudio audio;
904 audio.classBegin();
905 audio.componentComplete();
906
907 QSignalSpy errorSpy(&audio, SIGNAL(error(QDeclarativeAudio::Error,QString)));
908 QSignalSpy errorChangedSpy(&audio, SIGNAL(errorChanged()));
909
910 QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
911 QCOMPARE(audio.errorString(), QString());
912
913 provider.playerControl()->emitError(err: QMediaPlayer::ResourceError, errorString);
914
915 QCOMPARE(audio.error(), QDeclarativeAudio::ResourceError);
916 QCOMPARE(audio.errorString(), errorString);
917 QCOMPARE(errorSpy.count(), 1);
918 QCOMPARE(errorChangedSpy.count(), 1);
919
920 // Changing the source resets the error properties.
921 audio.setSource(QUrl("http://example.com"));
922 QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
923 QCOMPARE(audio.errorString(), QString());
924 QCOMPARE(errorSpy.count(), 1);
925 QCOMPARE(errorChangedSpy.count(), 2);
926
927 // But isn't noisy.
928 audio.setSource(QUrl("file:///file/path"));
929 QCOMPARE(audio.error(), QDeclarativeAudio::NoError);
930 QCOMPARE(audio.errorString(), QString());
931 QCOMPARE(errorSpy.count(), 1);
932 QCOMPARE(errorChangedSpy.count(), 2);
933}
934
935void tst_QDeclarativeAudio::loops()
936{
937 QtTestMediaServiceProvider provider;
938 QDeclarativeAudio audio;
939
940 QSignalSpy loopsChangedSpy(&audio, SIGNAL(loopCountChanged()));
941 QSignalSpy stateChangedSpy(&audio, SIGNAL(playbackStateChanged()));
942 QSignalSpy stoppedSpy(&audio, SIGNAL(stopped()));
943
944 int stateChanged = 0;
945 int loopsChanged = 0;
946 int stoppedCount = 0;
947
948 audio.classBegin();
949 audio.componentComplete();
950
951 QCOMPARE(audio.playbackState(), audio.StoppedState);
952
953 //setLoopCount(3) when stopped.
954 audio.setLoopCount(3);
955 QCOMPARE(audio.loopCount(), 3);
956 QCOMPARE(loopsChangedSpy.count(), ++loopsChanged);
957
958 //play till end
959 audio.play();
960 QCOMPARE(audio.playbackState(), audio.PlayingState);
961 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
962 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
963 QCOMPARE(stoppedSpy.count(), stoppedCount);
964
965 // play() when playing.
966 audio.play();
967 QCOMPARE(audio.playbackState(), audio.PlayingState);
968 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
969 QCOMPARE(stateChangedSpy.count(), stateChanged);
970 QCOMPARE(stoppedSpy.count(), stoppedCount);
971
972 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
973 QCOMPARE(audio.playbackState(), audio.PlayingState);
974 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
975 QCOMPARE(stateChangedSpy.count(), stateChanged);
976 QCOMPARE(stoppedSpy.count(), stoppedCount);
977
978 //play to end
979 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
980 QCOMPARE(stoppedSpy.count(), stoppedCount);
981 //play to end
982 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
983 QCOMPARE(audio.playbackState(), audio.StoppedState);
984 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
985 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
986 QCOMPARE(stoppedSpy.count(), ++stoppedCount);
987
988 // stop when playing
989 audio.play();
990 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
991 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
992 QCOMPARE(stoppedSpy.count(), stoppedCount);
993 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
994 audio.stop();
995 QCOMPARE(audio.playbackState(), audio.StoppedState);
996 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
997 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
998 QCOMPARE(stoppedSpy.count(), ++stoppedCount);
999
1000 //play() with infinite loop
1001 audio.setLoopCount(-1);
1002 QCOMPARE(audio.loopCount(), -1);
1003 QCOMPARE(loopsChangedSpy.count(), ++loopsChanged);
1004 audio.play();
1005 QCOMPARE(audio.playbackState(), audio.PlayingState);
1006 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
1007 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
1008 provider.playerControl()->updateMediaStatus(status: QMediaPlayer::EndOfMedia, state: QMediaPlayer::StoppedState);
1009 QCOMPARE(audio.playbackState(), audio.PlayingState);
1010 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::PlayingState);
1011 QCOMPARE(stateChangedSpy.count(), stateChanged);
1012
1013 // stop() when playing in infinite loop.
1014 audio.stop();
1015 QCOMPARE(audio.playbackState(), audio.StoppedState);
1016 QCOMPARE(provider.playerControl()->state(), QMediaPlayer::StoppedState);
1017 QCOMPARE(stateChangedSpy.count(), ++stateChanged);
1018 QCOMPARE(stoppedSpy.count(), ++stoppedCount);
1019
1020 qDebug() << "Testing version 5";
1021}
1022
1023void tst_QDeclarativeAudio::audioRole()
1024{
1025 MockMediaPlayerService mockService;
1026 MockMediaServiceProvider mockProvider(&mockService);
1027 QMediaServiceProvider::setDefaultServiceProvider(&mockProvider);
1028
1029 QQmlEngine engine;
1030 QQmlComponent component(&engine);
1031 component.setData("import QtQuick 2.0 \n import QtMultimedia 5.6 \n Audio { }", baseUrl: QUrl());
1032
1033 {
1034 mockService.setHasAudioRole(false);
1035 QDeclarativeAudio *audio = static_cast<QDeclarativeAudio*>(component.create());
1036
1037 QCOMPARE(audio->audioRole(), QDeclarativeAudio::UnknownRole);
1038 QVERIFY(audio->supportedAudioRoles().isArray());
1039 QVERIFY(audio->supportedAudioRoles().toVariant().toList().isEmpty());
1040
1041 QSignalSpy spy(audio, SIGNAL(audioRoleChanged()));
1042 audio->setAudioRole(QDeclarativeAudio::MusicRole);
1043 QCOMPARE(audio->audioRole(), QDeclarativeAudio::UnknownRole);
1044 QCOMPARE(spy.count(), 0);
1045 }
1046
1047 {
1048 mockService.reset();
1049 mockService.setHasAudioRole(true);
1050 QDeclarativeAudio *audio = static_cast<QDeclarativeAudio*>(component.create());
1051 QSignalSpy spy(audio, SIGNAL(audioRoleChanged()));
1052
1053 QCOMPARE(audio->audioRole(), QDeclarativeAudio::UnknownRole);
1054 QVERIFY(audio->supportedAudioRoles().isArray());
1055 QVERIFY(!audio->supportedAudioRoles().toVariant().toList().isEmpty());
1056
1057 audio->setAudioRole(QDeclarativeAudio::MusicRole);
1058 QCOMPARE(audio->audioRole(), QDeclarativeAudio::MusicRole);
1059 QCOMPARE(mockService.mockAudioRoleControl->audioRole(), QAudio::MusicRole);
1060 QCOMPARE(spy.count(), 1);
1061 }
1062}
1063
1064void tst_QDeclarativeAudio::customAudioRole()
1065{
1066 MockMediaPlayerService mockService;
1067 MockMediaServiceProvider mockProvider(&mockService);
1068 QMediaServiceProvider::setDefaultServiceProvider(&mockProvider);
1069
1070 QQmlEngine engine;
1071 QQmlComponent component(&engine);
1072 component.setData("import QtQuick 2.0 \n import QtMultimedia 5.11 \n Audio { }", baseUrl: QUrl());
1073
1074 {
1075 mockService.setHasCustomAudioRole(false);
1076 QObject *audio = component.create();
1077 QVERIFY(audio);
1078
1079 QMetaEnum audioRoleEnum = enumerator(object: audio->metaObject(), name: "AudioRole");
1080 int AudioRole_UnknownRoleValue = keyToValue(enumeration: audioRoleEnum, key: "UnknownRole");
1081 QVERIFY(!QTest::currentTestFailed());
1082
1083 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1084
1085 QSignalSpy spyRole(audio, SIGNAL(audioRoleChanged()));
1086 QSignalSpy spyCustomRole(audio, SIGNAL(customAudioRoleChanged()));
1087 audio->setProperty(name: "customAudioRole", QStringLiteral("customRole"));
1088 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_UnknownRoleValue);
1089 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1090 QCOMPARE(spyRole.count(), 0);
1091 QCOMPARE(spyCustomRole.count(), 0);
1092 }
1093
1094 {
1095 mockService.reset();
1096 mockService.setHasAudioRole(false);
1097
1098 QObject *audio = component.create();
1099 QVERIFY(audio);
1100
1101 QMetaEnum audioRoleEnum = enumerator(object: audio->metaObject(), name: "AudioRole");
1102 int AudioRole_UnknownRoleValue = keyToValue(enumeration: audioRoleEnum, key: "UnknownRole");
1103 QVERIFY(!QTest::currentTestFailed());
1104
1105 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1106
1107 QSignalSpy spyRole(audio, SIGNAL(audioRoleChanged()));
1108 QSignalSpy spyCustomRole(audio, SIGNAL(customAudioRoleChanged()));
1109 audio->setProperty(name: "customAudioRole", QStringLiteral("customRole"));
1110 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_UnknownRoleValue);
1111 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1112 QCOMPARE(spyRole.count(), 0);
1113 QCOMPARE(spyCustomRole.count(), 0);
1114 }
1115
1116 {
1117 mockService.reset();
1118
1119 QObject *audio = component.create();
1120 QVERIFY(audio);
1121
1122 QMetaEnum audioRoleEnum = enumerator(object: audio->metaObject(), name: "AudioRole");
1123 int AudioRole_UnknownRoleValue = keyToValue(enumeration: audioRoleEnum, key: "UnknownRole");
1124 int AudioRole_CustomRoleValue = keyToValue(enumeration: audioRoleEnum, key: "CustomRole");
1125 int AudioRole_MusicRoleValue = keyToValue(enumeration: audioRoleEnum, key: "MusicRole");
1126 QVERIFY(!QTest::currentTestFailed());
1127
1128 QSignalSpy spyRole(audio, SIGNAL(audioRoleChanged()));
1129 QSignalSpy spyCustomRole(audio, SIGNAL(customAudioRoleChanged()));
1130
1131 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_UnknownRoleValue);
1132 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1133
1134 QString customRole(QStringLiteral("customRole"));
1135 audio->setProperty(name: "customAudioRole", value: customRole);
1136 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_CustomRoleValue);
1137 QCOMPARE(audio->property("customAudioRole").toString(), customRole);
1138 QCOMPARE(mockService.mockAudioRoleControl->audioRole(), QAudio::CustomRole);
1139 QCOMPARE(mockService.mockCustomAudioRoleControl->customAudioRole(), customRole);
1140 QCOMPARE(spyRole.count(), 1);
1141 QCOMPARE(spyCustomRole.count(), 1);
1142
1143 spyRole.clear();
1144 spyCustomRole.clear();
1145
1146 QString customRole2(QStringLiteral("customRole2"));
1147 audio->setProperty(name: "customAudioRole", value: customRole2);
1148 QCOMPARE(audio->property("customAudioRole").toString(), customRole2);
1149 QCOMPARE(mockService.mockCustomAudioRoleControl->customAudioRole(), customRole2);
1150 QCOMPARE(spyRole.count(), 0);
1151 QCOMPARE(spyCustomRole.count(), 1);
1152
1153 spyRole.clear();
1154 spyCustomRole.clear();
1155
1156 audio->setProperty(name: "audioRole", value: AudioRole_MusicRoleValue);
1157 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_MusicRoleValue);
1158 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1159 QCOMPARE(mockService.mockAudioRoleControl->audioRole(), QAudio::MusicRole);
1160 QVERIFY(mockService.mockCustomAudioRoleControl->customAudioRole().isEmpty());
1161 QCOMPARE(spyRole.count(), 1);
1162 QCOMPARE(spyCustomRole.count(), 1);
1163
1164 spyRole.clear();
1165 spyCustomRole.clear();
1166
1167 audio->setProperty(name: "audioRole", value: AudioRole_CustomRoleValue);
1168 QCOMPARE(audio->property("audioRole").toInt(), AudioRole_CustomRoleValue);
1169 QVERIFY(audio->property("customAudioRole").toString().isEmpty());
1170 QCOMPARE(mockService.mockAudioRoleControl->audioRole(), QAudio::CustomRole);
1171 QVERIFY(mockService.mockCustomAudioRoleControl->customAudioRole().isEmpty());
1172 QCOMPARE(spyRole.count(), 1);
1173 QCOMPARE(spyCustomRole.count(), 0);
1174 }
1175}
1176
1177void tst_QDeclarativeAudio::enumerator(const QMetaObject *object,
1178 const char *name,
1179 QMetaEnum *result)
1180{
1181 int index = object->indexOfEnumerator(name);
1182 QVERIFY(index >= 0);
1183 *result = object->enumerator(index);
1184}
1185
1186QMetaEnum tst_QDeclarativeAudio::enumerator(const QMetaObject *object, const char *name)
1187{
1188 QMetaEnum result;
1189 enumerator(object, name, result: &result);
1190 return result;
1191}
1192
1193void tst_QDeclarativeAudio::keyToValue(const QMetaEnum &enumeration, const char *key, int *result)
1194{
1195 bool ok = false;
1196 *result = enumeration.keyToValue(key, ok: &ok);
1197 QVERIFY(ok);
1198}
1199
1200int tst_QDeclarativeAudio::keyToValue(const QMetaEnum &enumeration, const char *key)
1201{
1202 int result;
1203 keyToValue(enumeration, key, result: &result);
1204 return result;
1205}
1206
1207struct Surface : QAbstractVideoSurface
1208{
1209 Surface(QObject *parent = nullptr) : QAbstractVideoSurface(parent) { }
1210 QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType) const override
1211 {
1212 return QList<QVideoFrame::PixelFormat>() << QVideoFrame::Format_RGB32;
1213 }
1214
1215 bool present(const QVideoFrame &) override { return true; }
1216};
1217
1218void tst_QDeclarativeAudio::videoOutput()
1219{
1220 QtTestMediaPlayerControl playerControl;
1221 QtTestMediaServiceProvider provider(&playerControl, 0);
1222
1223 QDeclarativeAudio audio;
1224 QSignalSpy spy(&audio, &QDeclarativeAudio::videoOutputChanged);
1225
1226 audio.classBegin();
1227 audio.componentComplete();
1228
1229 QVERIFY(audio.videoOutput().isNull());
1230
1231 QVariant surface;
1232 surface.setValue(new Surface(this));
1233 audio.setVideoOutput(surface);
1234 QCOMPARE(audio.videoOutput(), surface);
1235 QCOMPARE(spy.count(), 1);
1236
1237 QQmlEngine engine;
1238 QJSValue jsArray = engine.newArray(length: 5);
1239 jsArray.setProperty(arrayIndex: 0, value: engine.newQObject(object: new Surface(this)));
1240 jsArray.setProperty(arrayIndex: 1, value: engine.newQObject(object: new Surface(this)));
1241 QDeclarativeVideoOutput output;
1242 jsArray.setProperty(arrayIndex: 2, value: engine.newQObject(object: &output));
1243 jsArray.setProperty(arrayIndex: 3, value: 123);
1244 jsArray.setProperty(arrayIndex: 4, value: QLatin1String("ignore this"));
1245
1246 QVariant surfaces;
1247 surfaces.setValue(jsArray);
1248 audio.setVideoOutput(surfaces);
1249 QCOMPARE(audio.videoOutput(), surfaces);
1250 QCOMPARE(spy.count(), 2);
1251}
1252
1253QTEST_MAIN(tst_QDeclarativeAudio)
1254
1255#include "tst_qdeclarativeaudio.moc"
1256

source code of qtmultimedia/tests/auto/unit/qdeclarativeaudio/tst_qdeclarativeaudio.cpp