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 | |
24 | QT_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 | |
100 | void 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 | |
112 | void QMediaPlayerPrivate::setStatus(QMediaPlayer::MediaStatus s) |
113 | { |
114 | Q_Q(QMediaPlayer); |
115 | |
116 | emit q->mediaStatusChanged(status: s); |
117 | } |
118 | |
119 | void 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 | |
133 | void 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 | |
212 | QList<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 | |
228 | QMediaPlayer::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 | |
248 | QMediaPlayer::~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 | |
261 | QUrl 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 | |
276 | const 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 | */ |
290 | QMediaPlayer::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 | |
305 | QMediaPlayer::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 | */ |
318 | qint64 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 | */ |
331 | qint64 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 | */ |
346 | float 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 | */ |
361 | QMediaTimeRange 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 | */ |
377 | bool 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 | */ |
393 | bool 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 | */ |
405 | bool QMediaPlayer::isSeekable() const |
406 | { |
407 | Q_D(const QMediaPlayer); |
408 | return d->control && d->control->isSeekable(); |
409 | } |
410 | |
411 | bool 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 | */ |
420 | qreal 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 | */ |
452 | int QMediaPlayer::loops() const |
453 | { |
454 | Q_D(const QMediaPlayer); |
455 | return d->control ? d->control->loops() : 1; |
456 | } |
457 | |
458 | void 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 | */ |
470 | QMediaPlayer::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 | */ |
487 | QString 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 | */ |
506 | void 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 | */ |
533 | void 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 | */ |
555 | void QMediaPlayer::stop() |
556 | { |
557 | Q_D(QMediaPlayer); |
558 | |
559 | if (d->control) |
560 | d->control->stop(); |
561 | } |
562 | |
563 | void 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 | |
574 | void 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 | |
605 | void 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 | */ |
634 | void 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 | */ |
668 | void 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 | |
687 | QAudioOutput *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 | */ |
716 | QList<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 | */ |
741 | QList<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 | */ |
768 | QList<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 | */ |
791 | int 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 | */ |
815 | int 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 | */ |
839 | int QMediaPlayer::activeSubtitleTrack() const |
840 | { |
841 | Q_D(const QMediaPlayer); |
842 | return d->control ? d->control->activeTrack(QPlatformMediaPlayer::SubtitleStream) : -1; |
843 | } |
844 | |
845 | void 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 | |
856 | void 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 | |
867 | void 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 | */ |
897 | QObject *QMediaPlayer::videoOutput() const |
898 | { |
899 | Q_D(const QMediaPlayer); |
900 | return d->videoOutput; |
901 | } |
902 | |
903 | void 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 | */ |
922 | void 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 | */ |
932 | QVideoSink *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 | */ |
948 | void 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 | */ |
959 | bool 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 | */ |
986 | QMediaMetaData 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 | |
1347 | QT_END_NAMESPACE |
1348 | |
1349 | #include "moc_qmediaplayer.cpp" |
1350 | |