[vlc-devel] [PATCH 5/7] qt: add a model to select where video should be rendered
Pierre Lamot
pierre at videolabs.io
Fri Aug 14 18:49:03 CEST 2020
This allows to select where the video should be rendered according to the
capabilities of the compositor.
---
modules/gui/qt/Makefile.am | 3 +
modules/gui/qt/maininterface/mainui.cpp | 2 +
.../qt/util/video_surface_target_model.cpp | 229 ++++++++++++++++++
.../qt/util/video_surface_target_model.hpp | 63 +++++
4 files changed, 297 insertions(+)
create mode 100644 modules/gui/qt/util/video_surface_target_model.cpp
create mode 100644 modules/gui/qt/util/video_surface_target_model.hpp
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index dbb43476b8..04958cadd6 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -213,6 +213,8 @@ libqt_plugin_la_SOURCES = \
gui/qt/util/varcommon_p.hpp \
gui/qt/util/varchoicemodel.cpp gui/qt/util/varchoicemodel.hpp \
gui/qt/util/variables.cpp gui/qt/util/variables.hpp \
+ gui/qt/util/video_surface_target_model.cpp \
+ gui/qt/util/video_surface_target_model.hpp \
gui/qt/util/vlctick.cpp \
gui/qt/util/vlctick.hpp \
gui/qt/widgets/native/animators.cpp \
@@ -342,6 +344,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/util/validators.moc.cpp \
gui/qt/util/varchoicemodel.moc.cpp \
gui/qt/util/variables.moc.cpp \
+ gui/qt/util/video_surface_target_model.moc.cpp \
gui/qt/util/vlctick.moc.cpp \
gui/qt/widgets/native/animators.moc.cpp \
gui/qt/widgets/native/customwidgets.moc.cpp \
diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp
index f371e4321e..88ed793505 100644
--- a/modules/gui/qt/maininterface/mainui.cpp
+++ b/modules/gui/qt/maininterface/mainui.cpp
@@ -25,6 +25,7 @@
#include "util/recent_media_model.hpp"
#include "util/settings.hpp"
#include "util/navigation_history.hpp"
+#include "util/video_surface_target_model.hpp"
#include "dialogs/help/aboutmodel.hpp"
#include "dialogs/dialogs_provider.hpp"
@@ -196,6 +197,7 @@ void MainUI::registerQMLTypes()
qmlRegisterUncreatableType<ProgramListModel>("org.videolan.vlc", 0, 1, "ProgramListModel", "available programs of a media" );
qmlRegisterUncreatableType<VLCVarChoiceModel>("org.videolan.vlc", 0, 1, "VLCVarChoiceModel", "generic variable with choice model" );
qmlRegisterUncreatableType<PlayerController>("org.videolan.vlc", 0, 1, "PlayerController", "player controller" );
+ qmlRegisterType<VideoSurfaceTargetModel>( "org.videolan.vlc", 0, 1, "VideoSurfaceTargetModel" );
qRegisterMetaType<PlaylistPtr>();
qRegisterMetaType<PlaylistItem>();
diff --git a/modules/gui/qt/util/video_surface_target_model.cpp b/modules/gui/qt/util/video_surface_target_model.cpp
new file mode 100644
index 0000000000..37ffa97892
--- /dev/null
+++ b/modules/gui/qt/util/video_surface_target_model.cpp
@@ -0,0 +1,229 @@
+/*****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "video_surface_target_model.hpp"
+
+#include <QGuiApplication>
+
+using namespace vlc;
+
+VideoSurfaceTargetModel::VideoSurfaceTargetModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+QHash<int, QByteArray> VideoSurfaceTargetModel::roleNames() const
+{
+ QHash<int, QByteArray> roleNames = this->QAbstractListModel::roleNames();
+ roleNames[Qt::CheckStateRole] = "checked";
+ return roleNames;
+}
+
+void VideoSurfaceTargetModel::setCtx(QmlMainContext* ctx)
+{
+ if (m_ctx)
+ {
+ disconnect(qApp, &QGuiApplication::screenAdded,
+ this, &VideoSurfaceTargetModel::onScreenCountChanged);
+ disconnect(qApp, &QGuiApplication::screenRemoved,
+ this, &VideoSurfaceTargetModel::onScreenCountChanged);
+ disconnect(m_compositor, &Compositor::videoSurfaceChanged,
+ this, &VideoSurfaceTargetModel::onVideoSurfaceChanged);
+ }
+ m_ctx = ctx;
+ if (m_ctx)
+ {
+ m_compositor = ctx->getIntf()->p_sys->p_compositor;
+ m_supportedModes = m_compositor->getSupportedVideoSurfaceModes();
+ connect(m_compositor, &Compositor::videoSurfaceChanged,
+ this, &VideoSurfaceTargetModel::onVideoSurfaceChanged);
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::FULLSCREEN)
+ {
+ m_screenList = QGuiApplication::screens();
+ connect(qApp, &QGuiApplication::screenAdded,
+ this, &VideoSurfaceTargetModel::onScreenCountChanged);
+ connect(qApp, &QGuiApplication::screenRemoved,
+ this, &VideoSurfaceTargetModel::onScreenCountChanged);
+ }
+ onScreenCountChanged();
+ }
+ emit ctxChanged();
+}
+
+int VideoSurfaceTargetModel::rowCount(const QModelIndex&) const
+{
+ int count = 0;
+ if (!m_ctx)
+ return 0;
+
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::FULLSCREEN)
+ count += m_screenList.size();
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::EMBED)
+ count += 1;
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::WINDOWED)
+ count += 1;
+ return count;
+}
+
+QVariant VideoSurfaceTargetModel::data( const QModelIndex& index, int role ) const
+{
+ auto idx = index.row();
+
+ if (!m_ctx)
+ return {};
+
+ //first index are static entries
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::EMBED)
+ {
+ if (idx == 0)
+ {
+ switch ( role )
+ {
+ case Qt::DisplayRole: return qtr("embed");
+ case Qt::CheckStateRole: return m_target == index.row();
+ default: return {};
+ }
+ }
+ idx -= 1;
+ }
+
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::WINDOWED)
+ {
+ if (idx == 0)
+ {
+ switch ( role )
+ {
+ case Qt::DisplayRole: return qtr("windowed");
+ case Qt::CheckStateRole: return m_target == index.row();
+ default: return {};
+ }
+ }
+ idx -= 1;
+ }
+
+ if ( idx < 0 || idx >= m_screenList.size() )
+ return {};
+
+ const QScreen* screen = m_screenList[idx];
+ switch ( role )
+ {
+ case Qt::DisplayRole: return screen->name();
+ case Qt::CheckStateRole: return m_target == index.row();
+ default: return {};
+ }
+}
+
+
+bool VideoSurfaceTargetModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (!m_ctx)
+ return false;
+
+ int row = index.row();
+ if (role != Qt::CheckStateRole)
+ return false;
+
+ //only update the variable when we select an entry
+ if (!value.toBool())
+ return false;
+
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::EMBED)
+ {
+ if (row == 0)
+ {
+ m_compositor->setVideoSurface(Compositor::VideoSurfaceTarget::EMBED);
+ return true;
+ }
+ row -= 1;
+ }
+
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::WINDOWED)
+ {
+ if (row == 0)
+ {
+ m_compositor->setVideoSurface(Compositor::VideoSurfaceTarget::WINDOWED);
+ return true;
+ }
+ row -= 1;
+ }
+
+ if (row >= 0 && row < m_screenList.size())
+ {
+ QScreen* screen = m_screenList[row];
+ m_compositor->setVideoSurface(Compositor::VideoSurfaceTarget::FULLSCREEN, QVariant(screen->name()));
+ return true;
+ }
+ return false;
+}
+
+void VideoSurfaceTargetModel::onScreenCountChanged()
+{
+ beginResetModel();
+ m_screenList = QGuiApplication::screens();
+ endResetModel();
+}
+
+void VideoSurfaceTargetModel::onVideoSurfaceChanged(Compositor::VideoSurfaceTarget target, QVariant param)
+{
+ int idx = 0;
+ bool found = false;
+ if (m_supportedModes & Compositor::VideoSurfaceTarget::EMBED)
+ {
+ if (target == Compositor::VideoSurfaceTarget::EMBED)
+ found = true;
+ else
+ idx += 1;
+ }
+
+ if (!found && (m_supportedModes & Compositor::VideoSurfaceTarget::WINDOWED))
+ {
+ if (target == Compositor::VideoSurfaceTarget::WINDOWED)
+ found = true;
+ else
+ idx += 1;
+ }
+
+ if (!found && (m_supportedModes & Compositor::VideoSurfaceTarget::FULLSCREEN))
+ {
+ if (target == Compositor::VideoSurfaceTarget::FULLSCREEN)
+ {
+ QString screenName = param.toString();
+ for (auto screen : m_screenList)
+ {
+ if (screen->name() == screenName)
+ {
+ found = true;
+ break;
+ }
+ idx++;
+ }
+ }
+ }
+ int oldTarget = m_target;
+ if (found)
+ m_target = idx;
+ else
+ m_target = -1;
+
+ if (oldTarget != -1)
+ emit dataChanged(index(oldTarget),index(oldTarget), {Qt::CheckStateRole});
+ if (m_target != -1)
+ emit dataChanged(index(m_target),index(m_target), {Qt::CheckStateRole});
+}
+
+
diff --git a/modules/gui/qt/util/video_surface_target_model.hpp b/modules/gui/qt/util/video_surface_target_model.hpp
new file mode 100644
index 0000000000..d7f8e6b73f
--- /dev/null
+++ b/modules/gui/qt/util/video_surface_target_model.hpp
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef VIDEOSURFACETARGETMODEL_HPP
+#define VIDEOSURFACETARGETMODEL_HPP
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qt.hpp"
+#include <QAbstractListModel>
+#include <QScreen>
+#include "maininterface/compositor.hpp"
+#include "qml_main_context.hpp"
+
+class VideoSurfaceTargetModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QmlMainContext* ctx READ getCtx WRITE setCtx NOTIFY ctxChanged)
+public:
+ explicit VideoSurfaceTargetModel(QObject *parent = nullptr);
+
+ int rowCount(QModelIndex const &parent = {}) const override;
+ QVariant data(QModelIndex const &index, const int role = Qt::DisplayRole) const override;
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override;
+ QHash<int, QByteArray> roleNames() const override;
+
+ void setCtx(QmlMainContext* ctx);
+ inline QmlMainContext* getCtx() const { return m_ctx; }
+
+signals:
+ void ctxChanged();
+
+private slots:
+ void onScreenCountChanged();
+ void onVideoSurfaceChanged(vlc::Compositor::VideoSurfaceTarget target, QVariant param);
+
+private:
+ QmlMainContext* m_ctx = nullptr;
+ vlc::Compositor* m_compositor = nullptr;
+ vlc::Compositor::VideoSurfaceTarget m_supportedModes = vlc::Compositor::UNDEF;
+ QList<QScreen *> m_screenList;
+ int m_target = -1; //the current target
+};
+
+#endif // VIDEOSURFACETARGETMODEL_HPP
--
2.25.1
More information about the vlc-devel
mailing list