Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qmediaplayer.cpp
Go to the documentation of this file.
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
25
101{
102 Q_Q(QMediaPlayer);
103
104 if (ps != state) {
106 emit q->playingChanged(ps == QMediaPlayer::PlayingState);
107 state = ps;
108 emit q->playbackStateChanged(ps);
109 }
110}
111
113{
114 Q_Q(QMediaPlayer);
115
116 emit q->mediaStatusChanged(s);
117}
118
120{
121 Q_Q(QMediaPlayer);
122
123 auto prevError = std::exchange(this->error, error);
124 auto prevErrorString = std::exchange(this->errorString, errorString);
125
126 if (prevError != error || prevErrorString != errorString)
127 emit q->errorChanged();
128
130 emit q->errorOccurred(error, errorString);
131}
132
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(new QFile(QLatin1Char(':') + media.path()));
147 if (!file->open(QFile::ReadOnly)) {
148 file.reset();
149 control->setMedia(QUrl(), nullptr);
151 control->error(QMediaPlayer::ResourceError, QMediaPlayer::tr("Attempting to play invalid Qt resource"));
152
153 } else if (control->streamPlaybackSupported()) {
154 control->setMedia(media, 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());
161 if (!tempFile->rename(tempFileName))
162 qWarning() << "Could not rename temporary file to:" << tempFileName;
163#else
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(QUrl(), nullptr);
177 delete tempFile;
178 qrcFile.reset();
179 return;
180 }
181 char buffer[4096];
182 while (true) {
183 qint64 len = file->read(buffer, sizeof(buffer));
184 if (len < 1)
185 break;
186 tempFile->write(buffer, len);
187 }
188 tempFile->close();
189#endif
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"))
201 if (url.scheme() == QLatin1String("content") && !stream) {
202 file.reset(new QFile(media.url()));
203 stream = file.get();
204 }
205
207 }
208
209 qrcFile.swap(file); // Cleans up any previous file
210}
211
213{
215 if (control) {
216 int count = control->trackCount(s);
217 for (int i = 0; i < count; ++i) {
218 tracks.append(control->trackMetaData(s, i));
219 }
220 }
221 return tracks;
222}
223
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(QMediaPlayer::ResourceError, maybeControl.error());
240 }
241}
242
243
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
262{
263 Q_D(const QMediaPlayer);
264
265 return d->source;
266}
267
277{
278 Q_D(const QMediaPlayer);
279
280 return d->stream;
281}
282
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
306{
307 Q_D(const QMediaPlayer);
308 return d->control ? d->control->mediaStatus() : NoMedia;
309}
310
319{
320 Q_D(const QMediaPlayer);
321 return d->control ? d->control->duration() : 0;
322}
323
332{
333 Q_D(const QMediaPlayer);
334 return d->control ? d->control->position() : 0;
335}
336
347{
348 Q_D(const QMediaPlayer);
349 return d->control ? d->control->bufferProgress() : 0;
350}
351
362{
363 Q_D(const QMediaPlayer);
364 return d->control ? d->control->availablePlaybackRanges() : QMediaTimeRange{};
365}
366
378{
379 Q_D(const QMediaPlayer);
380 return d->control && d->control->isAudioAvailable();
381}
382
394{
395 Q_D(const QMediaPlayer);
396 return d->control && d->control->isVideoAvailable();
397}
398
406{
407 Q_D(const QMediaPlayer);
408 return d->control && d->control->isSeekable();
409}
410
412{
413 Q_D(const QMediaPlayer);
414 return d->state == QMediaPlayer::PlayingState;
415}
416
421{
422 Q_D(const QMediaPlayer);
423 return d->control ? d->control->playbackRate() : 0.;
424}
425
453{
454 Q_D(const QMediaPlayer);
455 return d->control ? d->control->loops() : 1;
456}
457
459{
460 Q_D(QMediaPlayer);
461 if (loops == 0)
462 return;
463 if (d->control)
464 d->control->setLoops(loops);
465}
466
471{
472 return d_func()->error;
473}
474
488{
489 return d_func()->errorString;
490}
491
507{
508 Q_D(QMediaPlayer);
509
510 if (!d->control)
511 return;
512
513 // Reset error conditions
514 d->setError(NoError, QString());
515
516 d->control->play();
517}
518
534{
535 Q_D(QMediaPlayer);
536
537 if (d->control)
538 d->control->pause();
539}
540
556{
557 Q_D(QMediaPlayer);
558
559 if (d->control)
560 d->control->stop();
561}
562
564{
565 Q_D(QMediaPlayer);
566
567 if (!d->control)
568 return;
569 if (!d->control->isSeekable())
570 return;
571 d->control->setPosition(qMax(position, 0ll));
572}
573
575{
576 Q_D(QMediaPlayer);
577
578 if (d->control)
579 d->control->setPlaybackRate(rate);
580}
581
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(source, nullptr);
617 emit sourceChanged(d->source);
618}
619
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(d->source, device);
646 emit sourceChanged(d->source);
647}
648
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 }
685}
686
688{
689 Q_D(const QMediaPlayer);
690 return d->audioOutput;
691}
692
717{
718 Q_D(const QMediaPlayer);
719 return d->trackMetaData(QPlatformMediaPlayer::AudioStream);
720}
721
742{
743 Q_D(const QMediaPlayer);
744 return d->trackMetaData(QPlatformMediaPlayer::VideoStream);
745}
746
769{
770 Q_D(const QMediaPlayer);
771 return d->trackMetaData(QPlatformMediaPlayer::SubtitleStream);
772}
773
792{
793 Q_D(const QMediaPlayer);
794 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::AudioStream) : 0;
795}
796
816{
817 Q_D(const QMediaPlayer);
818 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::VideoStream) : -1;
819}
820
840{
841 Q_D(const QMediaPlayer);
842 return d->control ? d->control->activeTrack(QPlatformMediaPlayer::SubtitleStream) : -1;
843}
844
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
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
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
898{
899 Q_D(const QMediaPlayer);
900 return d->videoOutput;
901}
902
904{
905 Q_D(QMediaPlayer);
906 if (d->videoOutput == output)
907 return;
908
909 auto *sink = qobject_cast<QVideoSink *>(output);
910 if (!sink && output) {
911 auto *mo = output->metaObject();
912 mo->invokeMethod(output, "videoSink", Q_RETURN_ARG(QVideoSink *, sink));
913 }
914 d->videoOutput = output;
915 d->setVideoSink(sink);
916}
917
923{
924 Q_D(QMediaPlayer);
925 d->videoOutput = nullptr;
926 d->setVideoSink(sink);
927}
928
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*/
949{
950 // ### IMPLEMENT ME
951 Q_UNUSED(sinks);
952// setVideoOutput(!surfaces.empty() ? new QVideoSurfaces(surfaces, this) : nullptr);
953}
954#endif
955
960{
961 Q_D(const QMediaPlayer);
962 return bool(d->control);
963}
964
987{
988 Q_D(const QMediaPlayer);
989 return d->control ? d->control->metaData() : QMediaMetaData{};
990}
991
992// Enums
1152// Properties
1346
1347#include "moc_qmediaplayer.cpp"
IOBluetoothDevice * device
\qmltype AudioOutput \instantiates QAudioOutput
\inmodule QtCore
Definition qdir.h:19
bool mkpath(const QString &dirPath) const
Creates the directory path dirPath.
Definition qdir.cpp:1579
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
Definition qdir.cpp:2130
static QString currentPath()
Returns the absolute path of the application's current directory.
Definition qdir.cpp:2051
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString suffix() const
Returns the suffix (extension) of the file.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
QString fileName() const override
Returns the name set by setFileName() or to the QFile constructors.
Definition qfile.cpp:277
\inmodule QtCore \reentrant
Definition qiodevice.h:34
virtual bool reset()
Seeks to the start of input for random-access devices.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
\inmodule QtMultimedia
QPlatformMediaPlayer * control
void setState(QMediaPlayer::PlaybackState state)
\qmltype MediaPlayer \instantiates QMediaPlayer
QMediaPlayer::PlaybackState state
QList< QMediaMetaData > trackMetaData(QPlatformMediaPlayer::TrackType s) const
void setMedia(const QUrl &media, QIODevice *stream=nullptr)
std::unique_ptr< QFile > qrcFile
void setStatus(QMediaPlayer::MediaStatus status)
QMediaPlayer::Error error
void setError(QMediaPlayer::Error error, const QString &errorString)
The QMediaPlayer class allows the playing of a media files.
void setActiveAudioTrack(int index)
void setVideoSink(QVideoSink *sink)
Sets sink to be the QVideoSink instance to retrieve video data.
void setSource(const QUrl &source)
\qmlproperty url QtMultimedia::MediaPlayer::source
void setAudioOutput(QAudioOutput *output)
void setActiveVideoTrack(int index)
bool isAvailable() const
Returns true if the media player is supported on this platform.
QVideoSink * videoSink() const
Returns the QVideoSink instance.
int activeVideoTrack
Returns the currently active video track.
qint64 position
\qmlproperty int QtMultimedia::MediaPlayer::position
void sourceChanged(const QUrl &media)
Signals that the media source has been changed to media.
const QIODevice * sourceDevice() const
Returns the stream source of media data.
qint64 duration
\qmlproperty int QtMultimedia::MediaPlayer::duration
void setActiveSubtitleTrack(int index)
MediaStatus mediaStatus
the status of the current media stream.
MediaStatus
\qmlproperty enumeration QtMultimedia::MediaPlayer::playbackState
void setVideoOutput(QObject *)
qreal playbackRate
\qmlproperty real QtMultimedia::MediaPlayer::playbackRate
PlaybackState playbackState
Returns the \l{QMediaPlayer::}{PlaybackState}.
void audioOutputChanged()
QMediaTimeRange bufferedTimeRange() const
Returns a QMediaTimeRange describing the currently buffered data.
QMediaPlayer(QObject *parent=nullptr)
Constructs a QMediaPlayer instance as a child of {parent}.
void stop()
\qmlmethod QtMultimedia::MediaPlayer::stop()
float bufferProgress
\qmlproperty real QtMultimedia::MediaPlayer::bufferProgress
QUrl source
the active media source being used by the player object.
PlaybackState
Defines the current state of a media player.
QObject * videoOutput
\qmlproperty VideoOutput QtMultimedia::MediaPlayer::videoOutput
bool hasVideo
\qmlproperty bool QtMultimedia::MediaPlayer::hasVideo
void setPlaybackRate(qreal rate)
void setLoops(int loops)
~QMediaPlayer()
Destroys the player object.
void setPosition(qint64 position)
void play()
\qmlmethod QtMultimedia::MediaPlayer::play()
int activeAudioTrack
\qmlproperty int QtMultimedia::MediaPlayer::activeAudioTrack
void setSourceDevice(QIODevice *device, const QUrl &sourceUrl=QUrl())
Sets the current source device.
void pause()
\qmlmethod QtMultimedia::MediaPlayer::pause()
Error error
a string describing the last error condition.
bool hasAudio
\qmlproperty bool QtMultimedia::MediaPlayer::hasAudio
int activeSubtitleTrack
Returns the currently active subtitle track.
bool isPlaying() const
int loops
Determines how often the media is played before the player stops.
bool isSeekable() const
Returns true if the media is seekable.
QAudioOutput * audioOutput
\qmlproperty AudioOutput QtMultimedia::MediaPlayer::audioOutput
Error
\qmlproperty enumeration QtMultimedia::MediaPlayer::mediaStatus
QMediaMetaData metaData
\qmlproperty mediaMetaData QtMultimedia::MediaPlayer::metaData
QList< QMediaMetaData > subtitleTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::subtitleTracks
QList< QMediaMetaData > audioTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::audioTracks
QString errorString
\qmlproperty string QtMultimedia::MediaPlayer::errorString
QList< QMediaMetaData > videoTracks
\qmlproperty list<mediaMetaData> QtMultimedia::MediaPlayer::videoTracks
The QMediaTimeRange class represents a set of zero or more disjoint time intervals.
\inmodule QtCore
Definition qobject.h:90
static QPlatformMediaIntegration * instance()
virtual QMaybe< QPlatformMediaPlayer * > createPlayer(QMediaPlayer *)
virtual int trackCount(TrackType)
void error(int error, const QString &errorString)
virtual void setMedia(const QUrl &media, QIODevice *stream)=0
virtual QMediaMetaData trackMetaData(TrackType, int)
void mediaStatusChanged(QMediaPlayer::MediaStatus status)
virtual bool streamPlaybackSupported() const
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
\inmodule QtCore \reentrant
static QTemporaryFile * createNativeFile(const QString &fileName)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3354
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2814
static QUrl fromUserInput(const QString &userInput, const QString &workingDirectory=QString(), UserInputResolutionOptions options=DefaultResolution)
Returns a valid URL from a user supplied userInput string if one can be deduced.
Definition qurl.cpp:3743
@ AssumeLocalFile
Definition qurl.h:175
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1888
QString scheme() const
Returns the scheme of the URL.
Definition qurl.cpp:1983
QString path(ComponentFormattingOptions options=FullyDecoded) const
Returns the path of the URL.
Definition qurl.cpp:2465
The QVideoSink class represents a generic sink for video data.
Definition qvideosink.h:22
auto mo
[7]
Combined button and popup list for selecting options.
static QT_BEGIN_NAMESPACE const char tempFile[]
DBusConnection const char DBusError * error
EGLStreamKHR stream
#define qWarning
Definition qlogging.h:162
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
#define Q_RETURN_ARG(Type, data)
Definition qobjectdefs.h:63
GLuint index
[2]
GLenum GLenum GLsizei count
GLenum GLuint buffer
GLsizei GLsizei GLchar * source
GLuint GLenum * rate
GLenum GLsizei len
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
GLsizei GLenum GLboolean sink
GLdouble s
[6]
Definition qopenglext.h:235
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
#define emit
#define Q_UNUSED(x)
long long qint64
Definition qtypes.h:55
double qreal
Definition qtypes.h:92
QT_BEGIN_NAMESPACE typedef uchar * output
QFile file
[0]
QUrl url("example.com")
[constructor-url-reference]
myObject disconnect()
[26]
\inmodule QtCore \reentrant
Definition qchar.h:17
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent