PlayerComponent.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 "QtHelper.h"
  14. #include <mpv/client.h>
  15. ///////////////////////////////////////////////////////////////////////////////////////////////////
  16. class PlayerComponent : public ComponentBase
  17. {
  18. Q_OBJECT
  19. DEFINE_SINGLETON(PlayerComponent);
  20. public:
  21. const char* componentName() override { return "player"; }
  22. bool componentExport() override { return true; }
  23. bool componentInitialize() override;
  24. void componentPostInitialize() override;
  25. explicit PlayerComponent(QObject* parent = nullptr);
  26. ~PlayerComponent() override;
  27. // Deprecated. Corresponds to stop() + queueMedia().
  28. Q_INVOKABLE bool load(const QString& url, const QVariantMap& options, const QVariantMap& metadata, const QString& audioStream = QString(), const QString& subtitleStream = QString());
  29. // Append a media item to the internal playlist. If nothing is played yet, the
  30. // newly appended item will start playing immediately.
  31. // options:
  32. // - startMilliseconds: start playback at this time (in ms)
  33. // - autoplay: if false, start playback paused; if true, start normally
  34. Q_INVOKABLE void queueMedia(const QString& url, const QVariantMap& options, const QVariantMap &metadata, const QString& audioStream, const QString& subtitleStream);
  35. // This clears all items queued with queueMedia().
  36. // It explicitly excludes the currently playing item. The main use of this function
  37. // is updating the next item that should be played (for the purpose of gapless audio).
  38. // If you want to wipe everything, use stop().
  39. Q_INVOKABLE void clearQueue();
  40. Q_INVOKABLE virtual void seekTo(qint64 ms);
  41. // Stop playback and clear all queued items.
  42. Q_INVOKABLE virtual void stop();
  43. // A full reload of the stream is imminent (stop() + load())
  44. // Used for not resetting display mode with the next stop() call.
  45. Q_INVOKABLE virtual void streamSwitch();
  46. Q_INVOKABLE virtual void pause();
  47. Q_INVOKABLE virtual void play();
  48. // 0-100 volume 0=mute and 100=normal
  49. // Ignored if no audio output active (e.g. when no file is playing).
  50. Q_INVOKABLE virtual void setVolume(int volume);
  51. // Returns 0 if no audio output active.
  52. Q_INVOKABLE virtual int volume();
  53. // Ignored if no audio output active.
  54. Q_INVOKABLE virtual void setMuted(bool muted);
  55. // Returns 0 if no audio output active.
  56. Q_INVOKABLE virtual bool muted();
  57. // Returns a QVariant of the following format:
  58. // QVariantList (list of audio device entries)
  59. // QVariantMap (an audio device entry)
  60. // "name" -> QString (symbolic name/ID of the device)
  61. // "description" -> QString (human readable description intended for display)
  62. //
  63. Q_INVOKABLE virtual QVariant getAudioDeviceList();
  64. // Uses the "name" from the device list.
  65. Q_INVOKABLE virtual void setAudioDevice(const QString& name);
  66. Q_INVOKABLE virtual void setAudioStream(const QString& audioStream);
  67. Q_INVOKABLE virtual void setSubtitleStream(const QString& subtitleStream);
  68. Q_INVOKABLE virtual void setAudioDelay(qint64 milliseconds);
  69. Q_INVOKABLE virtual void setSubtitleDelay(qint64 milliseconds);
  70. // If enabled, hide the web view (whether it's OSD or not), and show video
  71. // only. If no video is running, render a black background only.
  72. Q_INVOKABLE virtual void setVideoOnlyMode(bool enable);
  73. // Currently is meant to check for "vc1" and "mpeg2video". Will return whether
  74. // it can be natively decoded. Will return true for all other codecs,
  75. // including unknown codec names.
  76. Q_INVOKABLE virtual bool checkCodecSupport(const QString& codec);
  77. // Return list of currently installed codecs. Includes builtin codecs.
  78. // Downloadable, but not yet installed codecs are excluded.
  79. // May include codecs that do not work, like vc1_mmal on RPIs with no license.
  80. // (checkCodecSupport() handles this specific case to a degree.)
  81. Q_INVOKABLE virtual QList<CodecDriver> installedCodecDrivers();
  82. // Return list of codecs supported for decoding. This specifically returns
  83. // the format and not decoder implementation (e.g. "h264" not "h264_mmal").
  84. Q_INVOKABLE virtual QStringList installedDecoderCodecs();
  85. Q_INVOKABLE void userCommand(QString command);
  86. // Set the region in which video should be rendered. This uses Qt pixel
  87. // coordinates (x=0,y=0 is the top/left corner).
  88. // If the aspect ratio mismatches, the video will be letterboxed or pillarboxed.
  89. // The lower/right pixel border is always excluded.
  90. // setVideoRectangle(-1, -1, -1 , -1) will revert to the default and
  91. // automatically use the whole window. (Same if the rectangle is 0-sized.)
  92. Q_INVOKABLE void setVideoRectangle(int x, int y, int w, int h);
  93. Q_INVOKABLE void setPlaybackRate(int rate);
  94. Q_INVOKABLE qint64 getPosition();
  95. Q_INVOKABLE qint64 getDuration();
  96. QRect videoRectangle() { return m_videoRectangle; }
  97. const mpv::qt::Handle getMpvHandle() const { return m_mpv; }
  98. virtual void setWindow(QQuickWindow* window);
  99. QString videoInformation() const;
  100. static QStringList AudioCodecsAll() { return { "ac3", "dts", "eac3", "dts-hd", "truehd" }; };
  101. static QStringList AudioCodecsSPDIF() { return { "ac3", "dts" }; };
  102. enum class State {
  103. finished,
  104. canceled,
  105. error,
  106. paused,
  107. playing,
  108. buffering,
  109. };
  110. enum class MediaType {
  111. Subtitle,
  112. Audio,
  113. };
  114. public Q_SLOTS:
  115. void setAudioConfiguration();
  116. void updateAudioDeviceList();
  117. void updateSubtitleSettings();
  118. void updateVideoSettings();
  119. private Q_SLOTS:
  120. void handleMpvEvents();
  121. void onRestoreDisplay();
  122. void onRefreshRateChange();
  123. void onCodecsLoadingDone(CodecsFetcher* sender);
  124. void updateAudioDevice();
  125. Q_SIGNALS:
  126. // The following signals correspond to the State enum above.
  127. void playing(); // playback is progressing (audio playing, pictures are moving)
  128. void buffering(float percent); // temporary state during "playing", or during media loading
  129. void paused(); // paused (covers all sub-states)
  130. void finished(); // playback finished successfully
  131. void canceled(); // playback was stopped (by user/via API)
  132. void error(const QString& msg); // playback stopped due to external error
  133. // To be phased out. Raised on finished() and canceled().
  134. void stopped(); // playback finished successfully, or was stopped with stop()
  135. void stateChanged(State newState, State oldState); // all state changes
  136. // true if the video (or music) is actually playing
  137. // false if nothing is loaded, playback is paused, during seeking, or media is being loaded
  138. void videoPlaybackActive(bool active);
  139. void windowVisible(bool visible);
  140. // emitted as soon as the duration of the current file is known
  141. void updateDuration(qint64 milliseconds);
  142. // current position in ms should be triggered 2 times a second
  143. // when position updates
  144. void positionUpdate(quint64);
  145. void onVideoRecangleChanged();
  146. void onMpvEvents();
  147. void onMetaData(const QVariantMap &meta, QUrl baseUrl);
  148. private:
  149. // this is the function actually implemented in the backends. the variantmap contains
  150. // a few known keys:
  151. // * subtitleStreamIndex
  152. // * subtitleStreamIdentifier
  153. // * audioStreamIndex
  154. // * audioStreamIdentifier
  155. // * viewOffset
  156. //
  157. void loadWithOptions(const QVariantMap& options);
  158. void setQtQuickWindow(QQuickWindow* window);
  159. void updatePlaybackState();
  160. void handleMpvEvent(mpv_event *event);
  161. // Potentially switch the display refresh rate, and return true if the refresh rate
  162. // was actually changed.
  163. bool switchDisplayFrameRate();
  164. void checkCurrentAudioDevice(const QSet<QString>& old_devs, const QSet<QString>& new_devs);
  165. void appendAudioFormat(QTextStream& info, const QString& property) const;
  166. void initializeCodecSupport();
  167. PlaybackInfo getPlaybackInfo();
  168. // Make the player prefer certain codecs over others.
  169. void setPreferredCodecs(const QList<CodecDriver>& codecs);
  170. // Determine the required codecs and possibly download them.
  171. // Call resume() when done.
  172. void startCodecsLoading(std::function<void()> resume);
  173. void updateVideoAspectSettings();
  174. QVariantList findStreamsForURL(const QString &url);
  175. void reselectStream(const QString &streamSelection, MediaType target);
  176. mpv::qt::Handle m_mpv;
  177. State m_state;
  178. bool m_paused;
  179. bool m_playbackActive;
  180. bool m_windowVisible;
  181. bool m_videoPlaybackActive;
  182. bool m_inPlayback;
  183. bool m_playbackCanceled;
  184. QString m_playbackError;
  185. int m_bufferingPercentage;
  186. int m_lastBufferingPercentage;
  187. double m_lastPositionUpdate;
  188. qint64 m_playbackAudioDelay;
  189. QQuickWindow* m_window;
  190. float m_mediaFrameRate;
  191. QTimer m_restoreDisplayTimer;
  192. QTimer m_reloadAudioTimer;
  193. QSet<QString> m_audioDevices;
  194. bool m_streamSwitchImminent;
  195. QMap<QString, bool> m_codecSupport;
  196. bool m_doAc3Transcoding;
  197. QStringList m_passthroughCodecs;
  198. QVariantMap m_serverMediaInfo;
  199. QString m_currentSubtitleStream;
  200. QString m_currentAudioStream;
  201. QRect m_videoRectangle;
  202. };
  203. #endif // PLAYERCOMPONENT_H