#pragma once #include #include #include #include // QML video surface backed by libmpv (through MpvQt). // mpv properties we care about are mirrored as Qt properties so QML can bind to them. class MpvItem : public MpvAbstractItem { Q_OBJECT QML_ELEMENT Q_PROPERTY(QUrl currentUrl READ currentUrl NOTIFY currentUrlChanged) Q_PROPERTY(QString mediaTitle READ mediaTitle NOTIFY mediaTitleChanged) Q_PROPERTY(double position READ position NOTIFY positionChanged) Q_PROPERTY(double duration READ duration NOTIFY durationChanged) Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged) Q_PROPERTY(bool fileLoaded READ isFileLoaded NOTIFY fileLoadedChanged) // Subtitle tracks of the current file, each a map with id, title, lang, codec, // external, externalFilename and ffIndex (FFmpeg stream index, -1 for external // files). Track id 0 means "no subtitle". Q_PROPERTY(QVariantList subtitleTracks READ subtitleTracks NOTIFY subtitleTracksChanged) Q_PROPERTY(int subtitleId READ subtitleId WRITE setSubtitleId NOTIFY subtitleTracksChanged) Q_PROPERTY(int secondarySubtitleId READ secondarySubtitleId WRITE setSecondarySubtitleId NOTIFY subtitleTracksChanged) // In seconds; applied to both subtitles so a translation stays in sync with its source. Q_PROPERTY(double subtitleDelay READ subtitleDelay WRITE setSubtitleDelay NOTIFY subtitleDelayChanged) // Audio tracks of the current file, each a map with id, title, lang and codec. Q_PROPERTY(QVariantList audioTracks READ audioTracks NOTIFY audioTracksChanged) Q_PROPERTY(int audioId READ audioId WRITE setAudioId NOTIFY audioTracksChanged) // 0 to volumeMax (mpv's "volume-max", 130 unless mpv.conf changes it). Q_PROPERTY(int volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(int volumeMax READ volumeMax NOTIFY volumeMaxChanged) Q_PROPERTY(bool mute READ mute WRITE setMute NOTIFY muteChanged) Q_PROPERTY(double speed READ speed WRITE setSpeed NOTIFY speedChanged) // Chapters of the current file, each a map with title and time (in seconds). Q_PROPERTY(QVariantList chapters READ chapters NOTIFY chaptersChanged) // Index into chapters, -1 before the first chapter or without chapters. Q_PROPERTY(int chapter READ chapter WRITE setChapter NOTIFY chapterChanged) // Load the user's mpv.conf when mpv starts. Must be set before the item is shown. Q_PROPERTY(bool loadUserConfig READ loadUserConfig WRITE setLoadUserConfig NOTIFY loadUserConfigChanged) Q_PROPERTY(QString userConfigDir READ userConfigDir CONSTANT) // The mpv.conf files that were loaded, and the options in them that were ignored. Q_PROPERTY(QStringList loadedUserConfigFiles READ loadedUserConfigFiles NOTIFY userConfigApplied) Q_PROPERTY(QStringList skippedUserOptions READ skippedUserOptions NOTIFY userConfigApplied) public: explicit MpvItem(QQuickItem *parent = nullptr); ~MpvItem() override = default; QUrl currentUrl() const; QString mediaTitle() const; double position() const; double duration() const; bool paused() const; void setPaused(bool paused); bool isFileLoaded() const; QVariantList subtitleTracks() const; int subtitleId() const; void setSubtitleId(int id); int secondarySubtitleId() const; void setSecondarySubtitleId(int id); double subtitleDelay() const; void setSubtitleDelay(double seconds); QVariantList audioTracks() const; int audioId() const; void setAudioId(int id); int volume() const; void setVolume(int volume); int volumeMax() const; bool mute() const; void setMute(bool mute); double speed() const; void setSpeed(double speed); QVariantList chapters() const; int chapter() const; void setChapter(int chapter); bool loadUserConfig() const; void setLoadUserConfig(bool load); QString userConfigDir() const; QStringList loadedUserConfigFiles() const; QStringList skippedUserOptions() const; Q_INVOKABLE void loadFile(const QUrl &url); // Unloads the current file. Q_INVOKABLE void stop(); Q_INVOKABLE void togglePause(); Q_INVOKABLE void seek(double seconds); // Seeks \a seconds forward, or backward when negative. Q_INVOKABLE void seekBy(double seconds); Q_INVOKABLE void frameStep(bool forward); // Saves a screenshot the way mpv does (screenshot-directory, screenshot-format). Q_INVOKABLE void screenshot(); // Adds an external subtitle file and makes it the primary subtitle. Q_INVOKABLE void addSubtitleFile(const QUrl &url); // Makes \a url the only subtitle shown, adding it first (named \a title) unless it is // already loaded. Q_INVOKABLE void showTranslatedSubtitleFile(const QUrl &url, const QString &title); // Shows a short message on mpv's on-screen display. Q_INVOKABLE void showText(const QString &text); Q_SIGNALS: void currentUrlChanged(); void mediaTitleChanged(); void positionChanged(); void durationChanged(); void pausedChanged(); void fileLoadedChanged(); void subtitleTracksChanged(); void subtitleDelayChanged(); void audioTracksChanged(); void volumeChanged(); void volumeMaxChanged(); void muteChanged(); void speedChanged(); void chaptersChanged(); void chapterChanged(); // Playback reached the end of the file. The last frame stays on screen. void endOfFile(); void loadUserConfigChanged(); // mpv.conf was queued for loading; options set after this take precedence over it. void userConfigApplied(); private: void onPropertyChanged(const QString &property, const QVariant &value); void setFileLoaded(bool loaded); void updateTracks(const QVariantList &trackList); void applyUserConfig(); void showOnlySubtitle(int id); bool m_ready = false; QUrl m_pendingUrl; QUrl m_currentUrl; QString m_mediaTitle; double m_position = 0.0; double m_duration = 0.0; bool m_paused = false; bool m_fileLoaded = false; QVariantList m_subtitleTracks; int m_subtitleId = 0; int m_secondarySubtitleId = 0; double m_subtitleDelay = 0.0; QVariantList m_audioTracks; int m_audioId = 0; int m_volume = 100; int m_volumeMax = 130; bool m_mute = false; double m_speed = 1.0; QVariantList m_chapters; int m_chapter = -1; // File added by showTranslatedSubtitleFile() that should be shown once mpv lists it. QString m_pendingTranslatedPath; bool m_loadUserConfig = false; QStringList m_loadedUserConfigFiles; QStringList m_skippedUserOptions; };