1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qmediaplayer_p.h"
5
6#include <private/qplatformmediaintegration_p.h>
7#include <qvideosink.h>
8#include <qaudiooutput.h>
9
10#include <QtCore/qcoreevent.h>
11#include <QtCore/qmetaobject.h>
12#include <QtCore/qtimer.h>
13#include <QtCore/qdebug.h>
14#include <QtCore/qpointer.h>
15#include <QtCore/qfileinfo.h>
16#include <QtCore/qtemporaryfile.h>
17#include <QtCore/qdir.h>
18#include <QtCore/qcoreapplication.h>
19
20#if defined(Q_OS_ANDROID)
21# include <QtCore/qjniobject.h>
22#endif
23
24QT_BEGIN_NAMESPACE
25
26/*!
27 \class QMediaPlayer
28 \brief The QMediaPlayer class allows the playing of a media files.
29 \inmodule QtMultimedia
30 \ingroup multimedia
31 \ingroup multimedia_playback
32 \ingroup multimedia_video
33
34 The QMediaPlayer class is a high level media playback class. It can be used
35 to playback audio of video media files. The content
36 to playback is specified as a QUrl object.
37
38 \snippet multimedia-snippets/media.cpp Player
39
40 QVideoWidget can be used with QMediaPlayer for video rendering.
41
42 \sa QVideoWidget
43*/
44
45/*!
46 \qmltype MediaPlayer
47 \instantiates QMediaPlayer
48 \brief Adds media playback to a scene.
49
50 \inqmlmodule QtMultimedia
51 \ingroup multimedia_qml
52 \ingroup multimedia_audio_qml
53 \ingroup multimedia_video_qml
54
55 \qml
56 Text {
57 text: "Click Me!";
58 font.pointSize: 24;
59 width: 150; height: 50;
60
61 MediaPlayer {
62 id: playMusic
63 source: "music.wav"
64 audioOutput: AudioOutput {}
65 }
66 MouseArea {
67 anchors.fill: parent
68 onPressed: { playMusic.play() }
69 }
70 }
71 \endqml
72
73 You can use MediaPlayer together with a MultiMedia::AudioOutput to play audio content, or you can use it
74 in conjunction with a Multimedia::VideoOutput for rendering video.
75
76 \qml
77 Item {
78 MediaPlayer {
79 id: mediaplayer
80 source: "groovy_video.mp4"
81 audioOutput: AudioOutput {}
82 videoOutput: videoOutput
83 }
84
85 VideoOutput {
86 id: videoOutput
87 anchors.fill: parent
88 }
89
90 MouseArea {
91 anchors.fill: parent
92 onPressed: mediaplayer.play();
93 }
94 }
95 \endqml
96
97 \sa AudioOutput, VideoOutput
98*/
99
100void QMediaPlayerPrivate::setState(QMediaPlayer::PlaybackState ps)
101{
102 Q_Q(QMediaPlayer);
103
104 if (ps != state) {
105 if (ps == QMediaPlayer::PlayingState || state == QMediaPlayer::PlayingState)
106 emit q->playingChanged(playing: ps == QMediaPlayer::PlayingState);
107 state = ps;
108 emit q->playbackStateChanged(newState: ps);
109 }
110}
111
112void QMediaPlayerPrivate::setStatus(QMediaPlayer::MediaStatus s)
113{
114 Q_Q(QMediaPlayer);
115
116 emit q->mediaStatusChanged(status: s);
117}
118
119void QMediaPlayerPrivate::setError(QMediaPlayer::Error error, const QString &errorString)
120{
121 Q_Q(QMediaPlayer);
122
123 auto prevError = std::exchange(obj&: this->error, new_val&: error);
124 auto prevErrorString = std::exchange(obj&: this->errorString, new_val: errorString);
125
126 if (prevError != error || prevErrorString != errorString)
127 emit q->errorChanged();
128
129 if (error != QMediaPlayer::NoError)
130 emit q->errorOccurred(error, errorString);
131}
132
133void QMediaPlayerPrivate::setMedia(const QUrl &media, QIODevice *stream)
134{
135 if (!control)
136 return;
137
138 std::unique_ptr<QFile> file;
139
140 // Back ends can't play qrc files directly.
141 // If the back end supports StreamPlayback, we pass a QFile for that resource.
142 // If it doesn't, we copy the data to a temporary file and pass its path.
143 if (!media.isEmpty() && !stream && media.scheme() == QLatin1String("qrc")) {
144 qrcMedia = media;
145
146 file.reset(p: new QFile(QLatin1Char(':') + media.path()));
147 if (!file->open(flags: QFile::ReadOnly)) {
148 file.reset();
149 control->setMedia(media: QUrl(), stream: nullptr);
150 control->mediaStatusChanged(status: QMediaPlayer::InvalidMedia);
151 control->error(error: QMediaPlayer::ResourceError, errorString: QMediaPlayer::tr(s: "Attempting to play invalid Qt resource"));
152
153 } else if (control->streamPlaybackSupported()) {
154 control->setMedia(media, stream: file.get());
155 } else {
156#if QT_CONFIG(temporaryfile)
157#if defined(Q_OS_ANDROID)
158 QString tempFileName = QDir::tempPath() + media.path();
159 QDir().mkpath(QFileInfo(tempFileName).path());
160 QTemporaryFile *tempFile = QTemporaryFile::createNativeFile(*file);
161 if (!tempFile->rename(tempFileName))
162 qWarning() << "Could not rename temporary file to:" << tempFileName;
163#else
164 QTemporaryFile *tempFile = new QTemporaryFile;
165
166 // Preserve original file extension, some back ends might not load the file if it doesn't
167 // have an extension.
168 const QString suffix = QFileInfo(*file).suffix();
169 if (!suffix.isEmpty())
170 tempFile->setFileTemplate(tempFile->fileTemplate() + QLatin1Char('.') + suffix);
171
172 // Copy the qrc data into the temporary file
173 if (!tempFile->open()) {
174 control->setMedia(media: QUrl(), stream: nullptr);
175 control->mediaStatusChanged(status: QMediaPlayer::InvalidMedia);
176 control->error(error: QMediaPlayer::ResourceError, errorString: tempFile->errorString());
177 delete tempFile;
178 qrcFile.reset();
179 return;
180 }
181 char buffer[4096];
182 while (true) {
183 qint64 len = file->read(data: buffer, maxlen: sizeof(buffer));
184 if (len < 1)
185 break;
186 tempFile->write(data: buffer, len);
187 }
188 tempFile->close();
189#endif
190 file.reset(p: tempFile);
191 control->setMedia(media: QUrl(QUrl::fromLocalFile(localfile: file->fileName())), stream: nullptr);
192#else
193 qWarning("Qt was built with -no-feature-temporaryfile: playback from resource file is not supported!");
194#endif
195 }
196 } else {
197 qrcMedia = QUrl();
198 QUrl url = media;
199 if (url.scheme().isEmpty() || url.scheme() == QLatin1String("file"))
200 url = QUrl::fromUserInput(userInput: media.toString(), workingDirectory: QDir::currentPath(), options: QUrl::AssumeLocalFile);
201 if (url.scheme() == QLatin1String("content") && !stream) {
202 file.reset(p: new QFile(media.url()));
203 stream = file.get();
204 }
205
206 control->setMedia(media: url, stream);
207 }
208
209 qrcFile.swap(u&: file); // Cleans up any previous file
210}
211
212QList<QMediaMetaData> QMediaPlayerPrivate::trackMetaData(QPlatformMediaPlayer::TrackType s) const
213{
214 QList<QMediaMetaData> tracks;
215 if (control) {
216 int count = control->trackCount(s);
217 for (int i = 0; i < count; ++i) {
218 tracks.append(t: control->trackMetaData(s, i));
219 }
220 }
221 return tracks;
222}
223
224/*!
225 Constructs a QMediaPlayer instance as a child of \a{parent}.
226*/
227
228QMediaPlayer::QMediaPlayer(QObject *parent)
229 : QObject(*new QMediaPlayerPrivate, parent)
230{
231 Q_D(QMediaPlayer);
232
233 auto maybeControl = QPlatformMediaIntegration::instance()->createPlayer(this);
234 if (maybeControl) {
235 d->control = maybeControl.value();
236 d->state = d->control->state();
237 } else {
238 qWarning() << "Failed to initialize QMediaPlayer" << maybeControl.error();
239 d->setError(error: QMediaPlayer::ResourceError, errorString: maybeControl.error());
240 }
241}
242
243
244/*!
245 Destroys the player object.
246*/
247
248QMediaPlayer::~QMediaPlayer()
249{
250 Q_D(QMediaPlayer);
251
252 // Disconnect everything to prevent notifying
253 // when a receiver is already destroyed.
254 disconnect();
255 setAudioOutput(nullptr);
256
257 d->setVideoSink(nullptr);
258 delete d->control;
259}
260
261QUrl QMediaPlayer::source() const
262{
263 Q_D(const QMediaPlayer);
264
265 return d->source;
266}
267
268/*!
269 Returns the stream source of media data.
270
271 This is only valid if a stream was passed to setSource().
272
273 \sa setSource()
274*/
275
276const QIODevice *QMediaPlayer::sourceDevice() const
277{
278 Q_D(const QMediaPlayer);
279
280 return d->stream;
281}
282
283/*!
284 \property QMediaPlayer::playbackState
285
286 Returns the \l{QMediaPlayer::}{PlaybackState}.
287
288 \sa playing
289*/
290QMediaPlayer::PlaybackState QMediaPlayer::playbackState() const
291{
292 Q_D(const QMediaPlayer);
293
294 // In case if EndOfMedia status is already received
295 // but state is not.
296 if (d->control
297 && d->control->mediaStatus() == QMediaPlayer::EndOfMedia
298 && d->state != d->control->state()) {
299 return d->control->state();
300 }
301
302 return d->state;
303}
304
305QMediaPlayer::MediaStatus QMediaPlayer::mediaStatus() const
306{
307 Q_D(const QMediaPlayer);
308 return d->control ? d->control->mediaStatus() : NoMedia;
309}
310
311/*!
312 Returns the duration of the current media in ms.
313
314 Returns 0 if the media player doesn't have a valid media file or stream.
315 For live streams, the duration usually changes during playback as more
316 data becomes available.
317*/
318qint64 QMediaPlayer::duration() const
319{
320 Q_D(const QMediaPlayer);
321 return d->control ? d->control->duration() : 0;
322}
323
324/*!
325 Returns the current position inside the media being played back in ms.
326
327 Returns 0 if the media player doesn't have a valid media file or stream.
328 For live streams, the duration usually changes during playback as more
329 data becomes available.
330*/
331qint64 QMediaPlayer::position() const
332{
333 Q_D(const QMediaPlayer);
334 return d->control ? d->control->position() : 0;
335}
336
337/*!
338 Returns a number between 0 and 1 when buffering data.
339
340 0 means that there is no buffered data available, playback is usually
341 stalled in this case. Playback will resume once the buffer reaches 1,
342 meaning enough data has been buffered to be able to resume playback.
343
344 bufferProgress() will always return 1 for local files.
345*/
346float QMediaPlayer::bufferProgress() const
347{
348 Q_D(const QMediaPlayer);
349 return d->control ? d->control->bufferProgress() : 0;
350}
351
352/*!
353 Returns a QMediaTimeRange describing the currently buffered data.
354
355 When streaming media from a remote source, different parts of the media
356 file can be available locally. The returned QMediaTimeRange object describes
357 the time ranges that are buffered and available for immediate playback.
358
359 \sa QMediaTimeRange
360*/
361QMediaTimeRange QMediaPlayer::bufferedTimeRange() const
362{
363 Q_D(const QMediaPlayer);
364 return d->control ? d->control->availablePlaybackRanges() : QMediaTimeRange{};
365}
366
367/*!
368 \qmlproperty bool QtMultimedia::MediaPlayer::hasAudio
369
370 This property holds whether the media contains audio.
371*/
372
373/*!
374 \property QMediaPlayer::hasAudio
375 \brief This property holds whether the media contains audio.
376*/
377bool QMediaPlayer::hasAudio() const
378{
379 Q_D(const QMediaPlayer);
380 return d->control && d->control->isAudioAvailable();
381}
382
383/*!
384 \qmlproperty bool QtMultimedia::MediaPlayer::hasVideo
385
386 This property holds whether the media contains video.
387*/
388
389/*!
390 \property QMediaPlayer::hasVideo
391 \brief This property holds whether the media contains video.
392*/
393bool QMediaPlayer::hasVideo() const
394{
395 Q_D(const QMediaPlayer);
396 return d->control && d->control->isVideoAvailable();
397}
398
399/*!
400 Returns true if the media is seekable. Most file based media files are seekable,
401 but live streams usually are not.
402
403 \sa position
404*/
405bool QMediaPlayer::isSeekable() const
406{
407 Q_D(const QMediaPlayer);
408 return d->control && d->control->isSeekable();
409}
410
411bool QMediaPlayer::isPlaying() const
412{
413 Q_D(const QMediaPlayer);
414 return d->state == QMediaPlayer::PlayingState;
415}
416
417/*!
418 Returns the current playback rate.
419*/
420qreal QMediaPlayer::playbackRate() const
421{
422 Q_D(const QMediaPlayer);
423 return d->control ? d->control->playbackRate() : 0.;
424}
425
426/*!
427 \enum QMediaPlayer::Loops
428
429 Some predefined constants for the \l loops property.
430
431 \value Infinite Loop forever.
432 \value Once Play the media once (the default).
433*/
434
435/*!
436 \property QMediaPlayer::loops
437
438 Determines how often the media is played before the player stops.
439 Set to QMediaPlayer::Infinite to loop the current media file forever.
440
441 The default value is \c 1. Setting this property to \c 0 has no effect.
442*/
443
444/*!
445 \qmlproperty int QtMultimedia::MediaPlayer::loops
446
447 Determines how often the media is played before the player stops.
448 Set to MediaPlayer::Infinite to loop the current media file forever.
449
450 The default value is \c 1. Setting this property to \c 0 has no effect.
451*/
452int QMediaPlayer::loops() const
453{
454 Q_D(const QMediaPlayer);
455 return d->control ? d->control->loops() : 1;
456}
457
458void QMediaPlayer::setLoops(int loops)
459{
460 Q_D(QMediaPlayer);
461 if (loops == 0)
462 return;
463 if (d->control)
464 d->control->setLoops(loops);
465}
466
467/*!
468 Returns the current error state.
469*/
470QMediaPlayer::Error QMediaPlayer::error() const
471{
472 return d_func()->error;
473}
474
475/*!
476 \qmlproperty string QtMultimedia::MediaPlayer::errorString
477
478 This property holds a string describing the current error condition in more
479 detail.
480*/
481
482/*!
483 \property QMediaPlayer::errorString
484 \brief This property holds a string describing the current error condition in
485 more detail.
486*/
487QString QMediaPlayer::errorString() const
488{
489 return d_func()->errorString;
490}
491
492/*!
493 \qmlmethod QtMultimedia::MediaPlayer::play()
494
495 Starts or resumes playback of the media.
496
497 Sets the \l playbackState property to PlayingState, and changes
498 \l playing to \c true.
499*/
500
501/*!
502 Start or resume playing the current source.
503
504 \sa pause(), stop()
505*/
506void QMediaPlayer::play()
507{
508 Q_D(QMediaPlayer);
509
510 if (!d->control)
511 return;
512
513 // Reset error conditions
514 d->setError(error: NoError, errorString: QString());
515
516 d->control->play();
517}
518
519/*!
520 \qmlmethod QtMultimedia::MediaPlayer::pause()
521
522 Pauses playback of the media.
523
524 Sets the \l playbackState property to PausedState,
525 and changes \l playing to \c false.
526*/
527
528/*!
529 Pause playing the current source.
530
531 \sa play(), stop()
532*/
533void QMediaPlayer::pause()
534{
535 Q_D(QMediaPlayer);
536
537 if (d->control)
538 d->control->pause();
539}
540
541/*!
542 \qmlmethod QtMultimedia::MediaPlayer::stop()
543
544 Stops playback of the media.
545
546 Sets the \l playbackState property to StoppedState,
547 and changes \l playing to \c false.
548*/
549
550/*!
551 Stop playing, and reset the play position to the beginning.
552
553 \sa play(), pause()
554*/
555void QMediaPlayer::stop()
556{
557 Q_D(QMediaPlayer);
558
559 if (d->control)
560 d->control->stop();
561}
562
563void QMediaPlayer::setPosition(qint64 position)
564{
565 Q_D(QMediaPlayer);
566
567 if (!d->control)
568 return;
569 if (!d->control->isSeekable())
570 return;
571 d->control->setPosition(qMax(a: position, b: 0ll));
572}
573
574void QMediaPlayer::setPlaybackRate(qreal rate)
575{
576 Q_D(QMediaPlayer);
577
578 if (d->control)
579 d->control->setPlaybackRate(rate);
580}
581
582/*!
583 \qmlproperty url QtMultimedia::MediaPlayer::source
584
585 This property holds the source URL of the media.
586
587 \snippet multimedia-snippets/qtvideosink.qml complete
588
589 \sa QMediaPlayer::setSource()
590*/
591
592/*!
593 Sets the current \a source.
594
595 Setting the media to a null QUrl will cause the player to discard all
596 information relating to the current media source and to cease all I/O operations related
597 to that media.
598
599 \note This function returns immediately after recording the specified source of the media.
600 It does not wait for the media to finish loading and does not check for errors. Listen for
601 the mediaStatusChanged() and error() signals to be notified when the media is loaded and
602 when an error occurs during loading.
603*/
604
605void QMediaPlayer::setSource(const QUrl &source)
606{
607 Q_D(QMediaPlayer);
608 stop();
609
610 if (d->source == source && d->stream == nullptr)
611 return;
612
613 d->source = source;
614 d->stream = nullptr;
615
616 d->setMedia(media: source, stream: nullptr);
617 emit sourceChanged(media: d->source);
618}
619
620/*!
621 Sets the current source \a device.
622
623 The media data will be read from \a device. The \a sourceUrl can be provided
624 to resolve additional information about the media, mime type etc. The
625 \a device must be open and readable.
626
627 For macOS the \a device should also be seek-able.
628
629 \note This function returns immediately after recording the specified source
630 of the media. It does not wait for the media to finish loading and does not
631 check for errors. Listen for the mediaStatusChanged() and error() signals to
632 be notified when the media is loaded, and if an error occurs during loading.
633*/
634void QMediaPlayer::setSourceDevice(QIODevice *device, const QUrl &sourceUrl)
635{
636 Q_D(QMediaPlayer);
637 stop();
638
639 if (d->source == sourceUrl && d->stream == device)
640 return;
641
642 d->source = sourceUrl;
643 d->stream = device;
644
645 d->setMedia(media: d->source, stream: device);
646 emit sourceChanged(media: d->source);
647}
648
649/*!
650 \qmlproperty AudioOutput QtMultimedia::MediaPlayer::audioOutput
651
652 This property holds the target audio output.
653 Accepts one AudioOutput elements.
654
655 \sa QMediaPlayer::setAudioOutput()
656*/
657
658
659/*!
660 \property QMediaPlayer::audioOutput
661 \brief The audio output device used by the media player.
662
663 The current audio output to be used when playing back media. Setting
664 a new audio output will replace the currently used output.
665
666 Setting this property to \c nullptr will disable any audio output.
667*/
668void QMediaPlayer::setAudioOutput(QAudioOutput *output)
669{
670 Q_D(QMediaPlayer);
671 auto oldOutput = d->audioOutput;
672 if (oldOutput == output)
673 return;
674 d->audioOutput = output;
675 if (d->control)
676 d->control->setAudioOutput(nullptr);
677 if (oldOutput)
678 oldOutput->setDisconnectFunction({});
679 if (output) {
680 output->setDisconnectFunction([this](){ setAudioOutput(nullptr); });
681 if (d->control)
682 d->control->setAudioOutput(output->handle());
683 }
684 emit audioOutputChanged();
685}
686
687QAudioOutput *QMediaPlayer::audioOutput() const
688{
689 Q_D(const QMediaPlayer);
690 return d->audioOutput;
691}
692
693/*!
694 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::audioTracks
695
696 This property holds a list of metadata.
697 Each index refers to an audio track.
698
699 The metadata holds properties describing the individual tracks. For
700 audio tracks the \l{QMediaMetaData}{Language} is usually the most
701 important property.
702
703 \sa mediaMetaData
704*/
705
706/*!
707 \property QMediaPlayer::audioTracks
708
709 Lists the set of available audio tracks inside the media.
710
711 The QMediaMetaData returned describes the properties of individual
712 tracks.
713
714 Different audio tracks can for example contain audio in different languages.
715*/
716QList<QMediaMetaData> QMediaPlayer::audioTracks() const
717{
718 Q_D(const QMediaPlayer);
719 return d->trackMetaData(s: QPlatformMediaPlayer::AudioStream);
720}
721
722/*!
723 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::videoTracks
724
725 This property holds a list of metadata.
726 Each index refers to a video track.
727
728 The metadata holds properties describing the individual tracks.
729
730 \sa mediaMetaData
731*/
732
733/*!
734 \property QMediaPlayer::videoTracks
735
736 Lists the set of available video tracks inside the media.
737
738 The QMediaMetaData returned describes the properties of individual
739 tracks.
740*/
741QList<QMediaMetaData> QMediaPlayer::videoTracks() const
742{
743 Q_D(const QMediaPlayer);
744 return d->trackMetaData(s: QPlatformMediaPlayer::VideoStream);
745}
746
747/*!
748 \qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::subtitleTracks
749
750 This property holds a list of metadata.
751 Each index refers to a subtitle track.
752
753 The metadata holds properties describing the individual tracks. For
754 subtitle tracks the \l{QMediaMetaData}{Language} is usually the most
755 important property.
756
757 \sa mediaMetaData
758*/
759
760/*!
761 \property QMediaPlayer::subtitleTracks
762
763 Lists the set of available subtitle tracks inside the media.
764
765 The QMediaMetaData returned describes the properties of individual
766 tracks.
767*/
768QList<QMediaMetaData> QMediaPlayer::subtitleTracks() const
769{
770 Q_D(const QMediaPlayer);
771 return d->trackMetaData(s: QPlatformMediaPlayer::SubtitleStream);
772}
773
774/*!
775 \qmlproperty int QtMultimedia::MediaPlayer::activeAudioTrack
776
777 This property holds the track number of the currently active audio track.
778 Set to \c{-1} to disable audio track.
779
780 The default property value is \c{0}: the first audio track.
781*/
782
783/*!
784 \property QMediaPlayer::activeAudioTrack
785 \brief Returns the currently active audio track.
786
787 By default, the first available audio track will be chosen.
788
789 Set \a index to \c -1 to disable all audio tracks.
790*/
791int QMediaPlayer::activeAudioTrack() const
792{
793 Q_D(const QMediaPlayer);
794 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::AudioStream) : 0;
795}
796
797/*!
798 \since 6.2
799 \qmlproperty int QtMultimedia::MediaPlayer::activeVideoTrack
800
801 This property holds the track number of the currently active video audio track.
802 Set to \c{-1} to disable video track.
803
804 The default property value is \c{0}: the first video track.
805*/
806
807/*!
808 \property QMediaPlayer::activeVideoTrack
809 \brief Returns the currently active video track.
810
811 By default, the first available audio track will be chosen.
812
813 Set \a index to \c -1 to disable all video tracks.
814*/
815int QMediaPlayer::activeVideoTrack() const
816{
817 Q_D(const QMediaPlayer);
818 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::VideoStream) : -1;
819}
820
821/*!
822 \since 6.2
823 \qmlproperty int QtMultimedia::MediaPlayer::activeSubtitleTrack
824
825 This property holds the track number of the currently active subtitle track.
826 Set to \c{-1} to disable subtitle track.
827
828 The default property value is \c{-1}: no subtitles active.
829*/
830
831/*!
832 \property QMediaPlayer::activeSubtitleTrack
833 \brief Returns the currently active subtitle track.
834
835 Set \a index to \c -1 to disable subtitles.
836
837 Subtitles are disabled by default.
838*/
839int QMediaPlayer::activeSubtitleTrack() const
840{
841 Q_D(const QMediaPlayer);
842 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::SubtitleStream) : -1;
843}
844
845void QMediaPlayer::setActiveAudioTrack(int index)
846{
847 Q_D(QMediaPlayer);
848 if (!d->control)
849 return;
850
851 if (activeAudioTrack() == index)
852 return;
853 d->control->setActiveTrack(QPlatformMediaPlayer::AudioStream, index);
854}
855
856void QMediaPlayer::setActiveVideoTrack(int index)
857{
858 Q_D(QMediaPlayer);
859 if (!d->control)
860 return;
861
862 if (activeVideoTrack() == index)
863 return;
864 d->control->setActiveTrack(QPlatformMediaPlayer::VideoStream, index);
865}
866
867void QMediaPlayer::setActiveSubtitleTrack(int index)
868{
869 Q_D(QMediaPlayer);
870 if (!d->control)
871 return;
872
873 if (activeSubtitleTrack() == index)
874 return;
875 d->control->setActiveTrack(QPlatformMediaPlayer::SubtitleStream, index);
876}
877
878/*!
879 \qmlproperty VideoOutput QtMultimedia::MediaPlayer::videoOutput
880
881 This property holds the target video output.
882 Accepts one VideoOutput elements.
883
884 \sa QMediaPlayer::setVideoOutput()
885*/
886
887/*!
888 \property QMediaPlayer::videoOutput
889 \brief The video output to be used by the media player.
890
891 A media player can only have one video output attached, so
892 setting this property will replace the previously connected
893 video output.
894
895 Setting this property to \c nullptr will disable video output.
896*/
897QObject *QMediaPlayer::videoOutput() const
898{
899 Q_D(const QMediaPlayer);
900 return d->videoOutput;
901}
902
903void QMediaPlayer::setVideoOutput(QObject *output)
904{
905 Q_D(QMediaPlayer);
906 if (d->videoOutput == output)
907 return;
908
909 auto *sink = qobject_cast<QVideoSink *>(object: output);
910 if (!sink && output) {
911 auto *mo = output->metaObject();
912 mo->invokeMethod(obj: output, member: "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
913 }
914 d->videoOutput = output;
915 d->setVideoSink(sink);
916}
917
918/*!
919 Sets \a sink to be the QVideoSink instance to
920 retrieve video data.
921*/
922void QMediaPlayer::setVideoSink(QVideoSink *sink)
923{
924 Q_D(QMediaPlayer);
925 d->videoOutput = nullptr;
926 d->setVideoSink(sink);
927}
928
929/*!
930 Returns the QVideoSink instance.
931*/
932QVideoSink *QMediaPlayer::videoSink() const
933{
934 Q_D(const QMediaPlayer);
935 return d->videoSink;
936}
937
938
939#if 0
940/*
941 \since 5.15
942 Sets multiple video sinks as the video output of a media player.
943 This allows the media player to render video frames on several outputs.
944
945 If a video output has already been set on the media player the new surfaces
946 will replace it.
947*/
948void QMediaPlayer::setVideoOutput(const QList<QVideoSink *> &sinks)
949{
950 // ### IMPLEMENT ME
951 Q_UNUSED(sinks);
952// setVideoOutput(!surfaces.empty() ? new QVideoSurfaces(surfaces, this) : nullptr);
953}
954#endif
955
956/*!
957 Returns true if the media player is supported on this platform.
958*/
959bool QMediaPlayer::isAvailable() const
960{
961 Q_D(const QMediaPlayer);
962 return bool(d->control);
963}
964
965/*!
966 \qmlproperty mediaMetaData QtMultimedia::MediaPlayer::metaData
967
968 Returns meta data for the current media used by the media player.
969
970 Meta data can contain information such as the title of the video or its creation date.
971
972 \note The Windows implementation provides metadata only for media located on the local file
973 system.
974*/
975
976/*!
977 \property QMediaPlayer::metaData
978
979 Returns meta data for the current media used by the media player.
980
981 Meta data can contain information such as the title of the video or its creation date.
982
983 \note The Windows implementation provides metadata only for media located on the local file
984 system.
985*/
986QMediaMetaData QMediaPlayer::metaData() const
987{
988 Q_D(const QMediaPlayer);
989 return d->control ? d->control->metaData() : QMediaMetaData{};
990}
991
992// Enums
993/*!
994 \enum QMediaPlayer::PlaybackState
995
996 Defines the current state of a media player.
997
998 \value StoppedState The media player is not playing content, playback will begin from the start
999 of the current track.
1000 \value PlayingState The media player is currently playing content. This indicates the same as the \l playing property.
1001 \value PausedState The media player has paused playback, playback of the current track will
1002 resume from the position the player was paused at.
1003*/
1004
1005/*!
1006 \qmlproperty enumeration QtMultimedia::MediaPlayer::playbackState
1007
1008 This property holds the state of media playback. It can be one of the following:
1009
1010 \table
1011 \header \li Property value
1012 \li Description
1013 \row \li PlayingState
1014 \li The media is currently playing. This indicates the same as the \l playing property.
1015 \row \li PausedState
1016 \li Playback of the media has been suspended.
1017 \row \li StoppedState
1018 \li Playback of the media is yet to begin.
1019 \endtable
1020*/
1021
1022/*!
1023 \qmlsignal QtMultimedia::MediaPlayer::playbackStateChanged()
1024
1025 This signal is emitted when the \l playbackState property is altered.
1026*/
1027
1028/*!
1029 \enum QMediaPlayer::MediaStatus
1030
1031 Defines the status of a media player's current media.
1032
1033 \value NoMedia The is no current media. The player is in the StoppedState.
1034 \value LoadingMedia The current media is being loaded. The player may be in any state.
1035 \value LoadedMedia The current media has been loaded. The player is in the StoppedState.
1036 \value StalledMedia Playback of the current media has stalled due to insufficient buffering or
1037 some other temporary interruption. The player is in the PlayingState or PausedState.
1038 \value BufferingMedia The player is buffering data but has enough data buffered for playback to
1039 continue for the immediate future. The player is in the PlayingState or PausedState.
1040 \value BufferedMedia The player has fully buffered the current media. The player is in the
1041 PlayingState or PausedState.
1042 \value EndOfMedia Playback has reached the end of the current media. The player is in the
1043 StoppedState.
1044 \value InvalidMedia The current media cannot be played. The player is in the StoppedState.
1045*/
1046
1047/*!
1048 \qmlproperty enumeration QtMultimedia::MediaPlayer::mediaStatus
1049
1050 This property holds the status of media loading. It can be one of the following:
1051
1052 \table
1053 \header
1054 \li Property value
1055 \li Description
1056 \row \li NoMedia
1057 \li No media has been set.
1058 \row \li LoadingMedia
1059 \li The media is currently being loaded.
1060 \row \li LoadedMedia
1061 \li The media has been loaded.
1062 \row \li BufferingMedia
1063 \li The media is buffering data.
1064 \row \li StalledMedia
1065 \li Playback has been interrupted while the media is buffering data.
1066 \row \li BufferedMedia
1067 \li The media has buffered data.
1068 \row \li EndOfMedia
1069 \li The media has played to the end.
1070 \row \li InvalidMedia
1071 \li The media cannot be played.
1072 \endtable
1073*/
1074
1075/*!
1076 \qmlproperty enumeration QtMultimedia::MediaPlayer::error
1077
1078 This property holds the error state of the audio. It can be one of the following.
1079
1080 \table
1081 \header \li Value \li Description
1082 \row \li NoError
1083 \li There is no current error.
1084 \row \li ResourceError
1085 \li The audio cannot be played due to a problem allocating resources.
1086 \row \li FormatError
1087 \li The audio format is not supported.
1088 \row \li NetworkError
1089 \li The audio cannot be played due to network issues.
1090 \row \li AccessDeniedError
1091 \li The audio cannot be played due to insufficient permissions.
1092 \endtable
1093*/
1094
1095/*!
1096 \enum QMediaPlayer::Error
1097
1098 Defines a media player error condition.
1099
1100 \value NoError No error has occurred.
1101 \value ResourceError A media resource couldn't be resolved.
1102 \value FormatError The format of a media resource isn't (fully) supported. Playback may still
1103 be possible, but without an audio or video component.
1104 \value NetworkError A network error occurred.
1105 \value AccessDeniedError There are not the appropriate permissions to play a media resource.
1106*/
1107
1108/*!
1109 \qmlsignal QtMultimedia::MediaPlayer::errorOccurred(error, errorString)
1110
1111 This signal is emitted when an \a error has occurred. The \a errorString
1112 parameter may contain more detailed information about the error.
1113
1114 \sa QMediaPlayer::Error
1115*/
1116
1117/*!
1118 \fn QMediaPlayer::errorOccurred(QMediaPlayer::Error error, const QString &errorString)
1119
1120 Signals that an \a error condition has occurred, with \a errorString
1121 containing a description of the error.
1122
1123 \sa errorString()
1124*/
1125
1126/*!
1127 \fn QMediaPlayer::mediaStatusChanged(QMediaPlayer::MediaStatus status)
1128
1129 Signals that the \a status of the current media has changed.
1130
1131 \sa mediaStatus()
1132*/
1133
1134/*!
1135 \fn void QMediaPlayer::sourceChanged(const QUrl &media);
1136
1137 Signals that the media source has been changed to \a media.
1138*/
1139
1140/*!
1141 \fn void QMediaPlayer::playbackRateChanged(qreal rate);
1142
1143 Signals the playbackRate has changed to \a rate.
1144*/
1145
1146/*!
1147 \fn void QMediaPlayer::seekableChanged(bool seekable);
1148
1149 Signals the \a seekable status of the player object has changed.
1150*/
1151
1152// Properties
1153/*!
1154 \property QMediaPlayer::error
1155 \brief a string describing the last error condition.
1156
1157 \sa error()
1158*/
1159
1160/*!
1161 \property QMediaPlayer::source
1162 \brief the active media source being used by the player object.
1163
1164 The player object will use the QUrl for selection of the content to
1165 be played.
1166
1167 By default this property has a null QUrl.
1168
1169 Setting this property to a null QUrl will cause the player to discard all
1170 information relating to the current media source and to cease all I/O operations related
1171 to that media.
1172
1173 \sa QUrl
1174*/
1175
1176/*!
1177 \property QMediaPlayer::mediaStatus
1178 \brief the status of the current media stream.
1179
1180 The stream status describes how the playback of the current stream is
1181 progressing.
1182
1183 By default this property is QMediaPlayer::NoMedia
1184
1185*/
1186
1187/*!
1188 \qmlproperty int QtMultimedia::MediaPlayer::duration
1189
1190 This property holds the duration of the media in milliseconds.
1191
1192 If the media doesn't have a fixed duration (a live stream for example) this
1193 will be set to \c{0}.
1194*/
1195
1196/*!
1197 \property QMediaPlayer::duration
1198 \brief the duration of the current media.
1199
1200 The value is the total playback time in milliseconds of the current media.
1201 The value may change across the life time of the QMediaPlayer object and
1202 may not be available when initial playback begins, connect to the
1203 durationChanged() signal to receive status notifications.
1204*/
1205
1206/*!
1207 \qmlproperty int QtMultimedia::MediaPlayer::position
1208
1209 The value is the current playback position, expressed in milliseconds since
1210 the beginning of the media. Periodically changes in the position will be
1211 indicated with the positionChanged() signal.
1212
1213 If the \l seekable property is true, this property can be set to milliseconds.
1214*/
1215
1216/*!
1217 \property QMediaPlayer::position
1218 \brief the playback position of the current media.
1219
1220 The value is the current playback position, expressed in milliseconds since
1221 the beginning of the media. Periodically changes in the position will be
1222 indicated with the positionChanged() signal.
1223
1224 If the \l seekable property is true, this property can be set to milliseconds.
1225*/
1226
1227/*!
1228 \qmlproperty real QtMultimedia::MediaPlayer::bufferProgress
1229
1230 This property holds how much of the data buffer is currently filled,
1231 from \c 0.0 (empty) to \c 1.0 (full).
1232
1233 Playback can start or resume only when the buffer is entirely filled.
1234 When the buffer is filled, \c MediaPlayer.Buffered is true.
1235 When buffer progress is between \c 0.0 and \c 0.1, \c MediaPlayer.Buffering
1236 is set to \c{true}.
1237
1238 A value lower than \c 1.0 implies that the property \c MediaPlayer.StalledMedia
1239 is \c{true}.
1240
1241 \sa mediaStatus
1242 */
1243
1244/*!
1245 \property QMediaPlayer::bufferProgress
1246 \brief the percentage of the temporary buffer filled before playback begins or resumes, from
1247 \c 0. (empty) to \c 1. (full).
1248
1249 When the player object is buffering; this property holds the percentage of
1250 the temporary buffer that is filled. The buffer will need to reach 100%
1251 filled before playback can start or resume, at which time mediaStatus() will return
1252 BufferedMedia or BufferingMedia. If the value is anything lower than \c 100, mediaStatus() will
1253 return StalledMedia.
1254
1255 \sa mediaStatus()
1256*/
1257
1258/*!
1259 \qmlproperty bool QtMultimedia::MediaPlayer::seekable
1260
1261 This property holds whether the \l position of the media can be changed.
1262*/
1263
1264/*!
1265 \property QMediaPlayer::seekable
1266 \brief the seek-able status of the current media
1267
1268 If seeking is supported this property will be true; false otherwise. The
1269 status of this property may change across the life time of the QMediaPlayer
1270 object, use the seekableChanged signal to monitor changes.
1271*/
1272
1273/*!
1274 \qmlproperty bool QtMultimedia::MediaPlayer::playing
1275 \since 6.5
1276
1277 Indicates whether the media is currently playing.
1278
1279 \sa playbackState
1280*/
1281
1282/*!
1283 \property QMediaPlayer::playing
1284 \brief Whether the media is playing.
1285 \since 6.5
1286
1287 \sa playbackState, PlayingState
1288*/
1289
1290/*!
1291 \qmlproperty real QtMultimedia::MediaPlayer::playbackRate
1292
1293 This property holds the rate at which media is played at as a multiple of
1294 the normal rate.
1295
1296 For more information, see \l{QMediaPlayer::playbackRate}.
1297
1298 Defaults to \c{1.0}.
1299*/
1300
1301/*!
1302 \property QMediaPlayer::playbackRate
1303 \brief the playback rate of the current media.
1304
1305 This value is a multiplier applied to the media's standard play rate. By
1306 default this value is 1.0, indicating that the media is playing at the
1307 standard pace. Values higher than 1.0 will increase the rate of play.
1308 Values less than zero can be set and indicate the media should rewind at the
1309 multiplier of the standard pace.
1310
1311 Not all playback services support change of the playback rate. It is
1312 framework defined as to the status and quality of audio and video
1313 while fast forwarding or rewinding.
1314*/
1315
1316/*!
1317 \fn void QMediaPlayer::durationChanged(qint64 duration)
1318
1319 Signals the duration of the content has changed to \a duration, expressed in milliseconds.
1320*/
1321
1322/*!
1323 \fn void QMediaPlayer::positionChanged(qint64 position)
1324
1325 Signals the position of the content has changed to \a position, expressed in
1326 milliseconds.
1327*/
1328
1329/*!
1330 \fn void QMediaPlayer::hasVideoChanged(bool videoAvailable)
1331
1332 Signals the availability of visual content has changed to \a videoAvailable.
1333*/
1334
1335/*!
1336 \fn void QMediaPlayer::hasAudioChanged(bool available)
1337
1338 Signals the availability of audio content has changed to \a available.
1339*/
1340
1341/*!
1342 \fn void QMediaPlayer::bufferProgressChanged(float filled)
1343
1344 Signals the amount of the local buffer \a filled as a number between 0 and 1.
1345*/
1346
1347QT_END_NAMESPACE
1348
1349#include "moc_qmediaplayer.cpp"
1350

source code of qtmultimedia/src/multimedia/playback/qmediaplayer.cpp