PlayerComponent.h 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #ifndef PLAYERCOMPONENT_H
  2. #define PLAYERCOMPONENT_H
  3. #include <QObject>
  4. #include <QtCore/qglobal.h>
  5. #include <QVariant>
  6. #include <QSet>
  7. #include <QQuickWindow>
  8. #include <QTimer>
  9. #include <QTextStream>
  10. #include <functional>
  11. #include "ComponentManager.h"
  12. #include "CodecsComponent.h"
  13. #include <mpv/client.h>
  14. #include <mpv/qthelper.hpp>
  15. void initD3DDevice(void);
  16. ///////////////////////////////////////////////////////////////////////////////////////////////////
  17. class PlayerComponent : public ComponentBase
  18. {
  19. Q_OBJECT
  20. DEFINE_SINGLETON(PlayerComponent);
  21. public:
  22. const char* componentName() override { return "player"; }
  23. bool componentExport() override { return true; }
  24. bool componentInitialize() override;
  25. void componentPostInitialize() override;
  26. explicit PlayerComponent(QObject* parent = nullptr);
  27. ~PlayerComponent() override;
  28. // Deprecated. Corresponds to stop() + queueMedia().
  29. Q_INVOKABLE bool load(const QString& url, const QVariantMap& options, const QVariantMap& metadata, const QString& audioStream = QString(), const QString& subtitleStream = QString());
  30. // Append a media item to the internal playlist. If nothing is played yet, the
  31. // newly appended item will start playing immediately.
  32. // options:
  33. // - startMilliseconds: start playback at this time (in ms)
  34. // - autoplay: if false, start playback paused; if true, start normally
  35. Q_INVOKABLE void queueMedia(const QString& url, const QVariantMap& options, const QVariantMap &metadata, const QString& audioStream, const QString& subtitleStream);
  36. // This clears all items queued with queueMedia().
  37. // It explicitly excludes the currently playing item. The main use of this function
  38. // is updating the next item that should be played (for the purpose of gapless audio).
  39. // If you want to wipe everything, use stop().
  40. Q_INVOKABLE void clearQueue();
  41. Q_INVOKABLE virtual void seekTo(qint64 ms);
  42. // Stop playback and clear all queued items.
  43. Q_INVOKABLE virtual void stop();
  44. // A full reload of the stream is imminent (stop() + load())
  45. // Used ofr not resetting display mode with the next stop() call.
  46. Q_INVOKABLE virtual void streamSwitch();
  47. Q_INVOKABLE virtual void pause();
  48. Q_INVOKABLE virtual void play();
  49. // 0-100 volume 0=mute and 100=normal
  50. // Ignored if no audio output active (e.g. when no file is playing).
  51. Q_INVOKABLE virtual void setVolume(int volume);
  52. // Returns 0 if no audio output active.
  53. Q_INVOKABLE virtual int volume();
  54. // Ignored if no audio output active.
  55. Q_INVOKABLE virtual void setMuted(bool muted);
  56. // Returns 0 if no audio output active.
  57. Q_INVOKABLE virtual bool muted();
  58. // Returns a QVariant of the following format:
  59. // QVariantList (list of audio device entries)
  60. // QVariantMap (an audio device entry)
  61. // "name" -> QString (symbolic name/ID of the device)
  62. // "description" -> QString (human readable description intended for display)
  63. //
  64. Q_INVOKABLE virtual QVariant getAudioDeviceList();
  65. // Uses the "name" from the device list.
  66. Q_INVOKABLE virtual void setAudioDevice(const QString& name);
  67. Q_INVOKABLE virtual void setAudioStream(const QString& audioStream);
  68. Q_INVOKABLE virtual void setSubtitleStream(const QString& subtitleStream);
  69. Q_INVOKABLE virtual void setAudioDelay(qint64 milliseconds);
  70. Q_INVOKABLE virtual void setSubtitleDelay(qint64 milliseconds);
  71. // If enabled, hide the web view (whether it's OSD or not), and show video
  72. // only. If no video is running, render a black background only.
  73. Q_INVOKABLE virtual void setVideoOnlyMode(bool enable);
  74. // Currently is meant to check for "vc1" and "mpeg2video". Will return whether
  75. // it can be natively decoded. Will return true for all other codecs,
  76. // including unknown codec names.
  77. Q_INVOKABLE virtual bool checkCodecSupport(const QString& codec);
  78. // Return list of currently installed codecs. Includes builtin codecs.
  79. // Downloadable, but not yet installed codecs are excluded.
  80. // May include codecs that do not work, like vc1_mmal on RPIs with no license.
  81. // (checkCodecSupport() handles this specific case to a degree.)
  82. Q_INVOKABLE virtual QList<CodecDriver> installedCodecs();
  83. Q_INVOKABLE void userCommand(QString command);
  84. const mpv::qt::Handle getMpvHandle() const { return m_mpv; }
  85. virtual void setWindow(QQuickWindow* window);
  86. QString videoInformation() const;
  87. static QStringList AudioCodecsAll() { return { "ac3", "dts", "eac3", "dts-hd", "truehd" }; };
  88. static QStringList AudioCodecsSPDIF() { return { "ac3", "dts" }; };
  89. public Q_SLOTS:
  90. void setAudioConfiguration();
  91. void updateAudioDeviceList();
  92. void updateSubtitleSettings();
  93. void updateVideoSettings();
  94. private Q_SLOTS:
  95. void handleMpvEvents();
  96. void onRestoreDisplay();
  97. void onRefreshRateChange();
  98. void onReloadAudio();
  99. void onCodecsLoadingDone(CodecsFetcher* sender);
  100. Q_SIGNALS:
  101. void playing(const QString& url);
  102. void buffering(float);
  103. // playback has stopped due to a stop() or loadMedia() request
  104. void stopped(const QString& url);
  105. // playback has stopped because the current media was fully played
  106. void finished(const QString& url);
  107. // playback has stopped due to any reason - this always happens if the
  108. // playing() signal was emitted
  109. void playbackEnded(const QString& url);
  110. // emitted if playback has ended, and no more items are queued for playback
  111. void playbackAllDone();
  112. // emitted after playing(), and as soon as the the media is fully loaded, and
  113. // playback starts normally
  114. void playbackStarting();
  115. void paused(bool paused);
  116. // true if the video (or music) is actually
  117. // false if nothing is loaded, playback is paused, during seeking, or media is being loaded
  118. void playbackActive(bool active);
  119. void windowVisible(bool visible);
  120. // emitted as soon as the duration of the current file is known
  121. void updateDuration(qint64 milliseconds);
  122. // an error happened during playback - this implies abort of playback
  123. // the id is the (negative) error number, and the message parameter is a short
  124. // English description of the error (always the same for the same id, no
  125. // further information)
  126. void error(int id, const QString& message);
  127. // current position in ms should be triggered 2 times a second
  128. // when position updates
  129. void positionUpdate(quint64);
  130. void onMpvEvents();
  131. private:
  132. // this is the function actually implemented in the backends. the variantmap contains
  133. // a few known keys:
  134. // * subtitleStreamIndex
  135. // * subtitleStreamIdentifier
  136. // * audioStreamIndex
  137. // * audioStreamIdentifier
  138. // * viewOffset
  139. //
  140. void loadWithOptions(const QVariantMap& options);
  141. void setRpiWindow(QQuickWindow* window);
  142. void setQtQuickWindow(QQuickWindow* window);
  143. void handleMpvEvent(mpv_event *event);
  144. // Potentially switch the display refresh rate, and return true if the refresh rate
  145. // was actually changed.
  146. bool switchDisplayFrameRate();
  147. void checkCurrentAudioDevice(const QSet<QString>& old_devs, const QSet<QString>& new_devs);
  148. void appendAudioFormat(QTextStream& info, const QString& property) const;
  149. void initializeCodecSupport();
  150. PlaybackInfo getPlaybackInfo();
  151. // Make the player prefer certain codecs over others.
  152. void setPreferredCodecs(const QList<CodecDriver>& codecs);
  153. // Determine the required codecs and possibly download them.
  154. // Call resume() when done.
  155. void startCodecsLoading(std::function<void()> resume);
  156. void updateVideoAspectSettings();
  157. mpv::qt::Handle m_mpv;
  158. double m_lastPositionUpdate;
  159. qint64 m_playbackAudioDelay;
  160. QString m_currentUrl;
  161. bool m_playbackStartSent;
  162. QQuickWindow* m_window;
  163. float m_mediaFrameRate;
  164. QTimer m_restoreDisplayTimer;
  165. QTimer m_reloadAudioTimer;
  166. QSet<QString> m_audioDevices;
  167. bool m_streamSwitchImminent;
  168. QMap<QString, bool> m_codecSupport;
  169. bool m_doAc3Transcoding;
  170. QStringList m_passthroughCodecs;
  171. QVariantMap m_serverMediaInfo;
  172. };
  173. #endif // PLAYERCOMPONENT_H