[vlc-devel] [RFC 15/82] qt: provide wrapper around vlc_var with simple types

Pierre Lamot pierre at videolabs.io
Fri Feb 1 14:01:19 CET 2019


   values are accesible from Q_PROPERTIES for QML integration
---
 modules/gui/qt/Makefile.am               |   3 +
 modules/gui/qt/util/vlc_var_observer.cpp |  59 +++++
 modules/gui/qt/util/vlc_var_observer.hpp | 276 +++++++++++++++++++++++
 3 files changed, 338 insertions(+)
 create mode 100644 modules/gui/qt/util/vlc_var_observer.cpp
 create mode 100644 modules/gui/qt/util/vlc_var_observer.hpp

diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 0b20509bc0..1f51781643 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -146,6 +146,8 @@ libqt_plugin_la_SOURCES = \
 	gui/qt/util/singleton.hpp \
 	gui/qt/util/vlctick.cpp \
 	gui/qt/util/vlctick.hpp \
+	gui/qt/util/vlc_var_observer.cpp \
+	gui/qt/util/vlc_var_observer.hpp \
 	gui/qt/util/imagehelper.cpp gui/qt/util/imagehelper.hpp \
 	gui/qt/styles/seekstyle.cpp gui/qt/styles/seekstyle.hpp
 if HAVE_WIN32
@@ -232,6 +234,7 @@ nodist_libqt_plugin_la_SOURCES = \
 	gui/qt/util/qmenuview.moc.cpp \
 	gui/qt/util/qvlcapp.moc.cpp \
 	gui/qt/util/pictureflow.moc.cpp \
+	gui/qt/util/vlc_var_observer.moc.cpp \
 	gui/qt/util/vlctick.moc.cpp \
 	gui/qt/util/validators.moc.cpp \
 	gui/qt/util/buttons/RoundButton.moc.cpp \
diff --git a/modules/gui/qt/util/vlc_var_observer.cpp b/modules/gui/qt/util/vlc_var_observer.cpp
new file mode 100644
index 0000000000..72785cd791
--- /dev/null
+++ b/modules/gui/qt/util/vlc_var_observer.cpp
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * Copyright (C) 2019 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 "vlc_var_observer.hpp"
+
+VLCVarBooleanObserver::VLCVarBooleanObserver(vlc_object_t *object, QString property, QObject *parent)
+    : VLCVarObserver<VLCVarBooleanObserver, bool>(object, property, parent)
+{
+}
+
+void VLCVarBooleanObserver::setValue(bool value)
+{
+    setValueInternal(value);
+}
+
+VLCVarStringObserver::VLCVarStringObserver(vlc_object_t *object, QString property, QObject *parent)
+    : VLCVarObserver<VLCVarStringObserver, QString>(object, property, parent)
+{
+}
+
+void VLCVarStringObserver::setValue(QString value)
+{
+    setValueInternal(value);
+}
+
+VLCVarFloatObserver::VLCVarFloatObserver(vlc_object_t *object, QString property, QObject *parent)
+    : VLCVarObserver<VLCVarFloatObserver, float>(object, property, parent)
+{
+}
+
+void VLCVarFloatObserver::setValue(float value)
+{
+    setValueInternal(value);
+}
+
+VLCVarIntObserver::VLCVarIntObserver(vlc_object_t *object, QString property, QObject *parent)
+    : VLCVarObserver<VLCVarIntObserver, int64_t>(object, property, parent)
+{
+}
+
+void VLCVarIntObserver::setValue(int64_t value)
+{
+    setValueInternal(value);
+}
diff --git a/modules/gui/qt/util/vlc_var_observer.hpp b/modules/gui/qt/util/vlc_var_observer.hpp
new file mode 100644
index 0000000000..fd3a5ed20a
--- /dev/null
+++ b/modules/gui/qt/util/vlc_var_observer.hpp
@@ -0,0 +1,276 @@
+/*****************************************************************************
+ * Copyright (C) 2019 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 VLC_VAR_OBSERVER_HPP
+#define VLC_VAR_OBSERVER_HPP
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_variables.h>
+#include <vlc_cxx_helpers.hpp>
+
+#include <QObject>
+
+#include "qt.hpp"
+
+/*
+ * type traits to convert VLC_VAR to C++types
+ */
+template<typename T>
+struct VLCVarTypeTraits {
+};
+
+template<>
+struct VLCVarTypeTraits<QString>
+{
+    static const int var_type = VLC_VAR_STRING;
+    inline static QString fromValue(const vlc_value_t& value) {
+        return value.psz_string;
+    }
+    inline static vlc_value_t toValue(const QString& value) {
+        vlc_value_t ret;
+        ret.psz_string = strdup(qtu(value));
+        return ret;
+    }
+    inline static void releaseValue(vlc_value_t value) {
+        free(value.psz_string);
+    }
+};
+
+template<>
+struct VLCVarTypeTraits<bool>
+{
+    static const int var_type = VLC_VAR_BOOL;
+    inline static bool fromValue(const vlc_value_t& value) {
+        return value.b_bool;
+    }
+    inline static vlc_value_t toValue(bool value) {
+        vlc_value_t ret;
+        ret.b_bool = value;
+        return ret;
+    }
+    inline static void releaseValue(vlc_value_t) {}
+};
+
+template<>
+struct VLCVarTypeTraits<int64_t>
+{
+    static const int var_type = VLC_VAR_INTEGER;
+    inline static int64_t fromValue(const vlc_value_t& value) {
+        return value.i_int;
+    }
+    inline static vlc_value_t toValue(int64_t value) {
+        vlc_value_t ret;
+        ret.i_int = value;
+        return ret;
+    }
+    inline static void releaseValue(vlc_value_t) {}
+};
+
+template<>
+struct VLCVarTypeTraits<float>
+{
+    static const int var_type = VLC_VAR_FLOAT;
+    inline static float fromValue(const vlc_value_t& value) {
+        return value.f_float;
+    }
+    inline static vlc_value_t toValue(float value) {
+        vlc_value_t ret;
+        ret.f_float = value;
+        return ret;
+    }
+    inline static void releaseValue(vlc_value_t) {}
+};
+
+
+//Generic observer
+template<typename Derived, typename BaseType>
+class VLCVarObserver : public QObject
+{
+public:
+    VLCVarObserver(vlc_object_t* object, QString property, QObject* parent)
+        : QObject(parent)
+        , m_property(property)
+    {
+       resetObject(object);
+       Derived* derived = static_cast<Derived*>(this);
+       connect( derived, &Derived::valueChangedInternal, [this](vlc_object_t* object, BaseType val) {
+           this->onValueChangedInternal(object, val);
+       });
+    }
+
+    virtual ~VLCVarObserver()
+    {
+        if (m_object)
+        {
+            Derived* derived = static_cast<Derived*>(this);
+            var_DelCallback(m_object.get(), qtu(m_property), value_modified, derived);
+        }
+    }
+
+    ///change the object beeing observed
+    void resetObject( vlc_object_t* object )
+    {
+        Derived* derived = static_cast<Derived*>(this);
+        if (m_object)
+            var_DelCallback( m_object.get(), qtu(m_property), value_modified, derived );
+
+        m_object.reset( object, true );
+        if (m_object)
+        {
+            int type = var_Type(object, qtu(m_property));
+            if (type == 0) //variable not found
+            {
+                msg_Warn(m_object.get(), "variable %s not found in object", qtu(m_property));
+                m_object.reset(nullptr);
+                return;
+            }
+            assert((type & VLC_VAR_CLASS) == VLCVarTypeTraits<BaseType>::var_type);
+            vlc_value_t currentvalue;
+            if (var_Get(m_object.get(), qtu(m_property), &currentvalue) == VLC_SUCCESS)
+            {
+                BaseType value = VLCVarTypeTraits<BaseType>::fromValue(currentvalue);
+                if (m_value != value)
+                {
+                    m_value = value;
+                    emit derived->valueChanged( m_value );
+                }
+            }
+
+            var_AddCallback(m_object.get(), qtu(m_property), value_modified, derived);
+        }
+    }
+
+    BaseType getValue() const
+    {
+        if (!m_object)
+            return BaseType{};
+        return m_value;
+    }
+
+protected:
+    //called by setValue in child classes
+    void setValueInternal(BaseType value)
+    {
+        if (! m_object)
+            return;
+        vlc_value_t vlcvalue = VLCVarTypeTraits<BaseType>::toValue( value );
+        var_Set(m_object.get(), qtu(m_property), vlcvalue);
+        VLCVarTypeTraits<BaseType>::releaseValue(vlcvalue);
+    }
+
+private:
+    //executed on UI thread
+    virtual void onValueChangedInternal(vlc_object_t* object, BaseType value)
+    {
+        if (m_object.get() != object)
+            return;
+        if (m_value != value) {
+            m_value = value;
+            Derived* derived = static_cast<Derived*>(this);
+            emit derived->valueChanged( m_value );
+        }
+    }
+
+
+    //executed on variable thread, this forwards the callback to the UI thread
+    static int value_modified( vlc_object_t * object, char const *, vlc_value_t, vlc_value_t newValue, void * data)
+    {
+        Derived* that = static_cast<Derived*>(data);
+        emit that->onValueChangedInternal( object, VLCVarTypeTraits<BaseType>::fromValue( newValue ) );
+        return VLC_SUCCESS;
+    }
+
+    typedef vlc_shared_data_ptr_type(vlc_object_t, vlc_object_hold, vlc_object_release) ObjectPtr;
+    ObjectPtr m_object;
+    QString m_property;
+    BaseType m_value;
+};
+
+//specialisation
+
+class VLCVarBooleanObserver : public VLCVarObserver<VLCVarBooleanObserver, bool>
+{
+    Q_OBJECT
+public:
+    Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged)
+
+    VLCVarBooleanObserver(vlc_object_t* object, QString property, QObject* parent = nullptr);
+
+public slots:
+    void setValue(bool value);
+
+signals:
+    void valueChanged( bool );
+    void valueChangedInternal(vlc_object_t *, bool );
+};
+
+class VLCVarStringObserver : public VLCVarObserver<VLCVarStringObserver, QString>
+{
+    Q_OBJECT
+public:
+    Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)
+
+    VLCVarStringObserver(vlc_object_t* object, QString property, QObject* parent = nullptr);
+
+public slots:
+    void setValue(QString value);
+
+signals:
+    void valueChanged( QString );
+    void valueChangedInternal( vlc_object_t *, QString );
+};
+
+class VLCVarFloatObserver : public VLCVarObserver<VLCVarFloatObserver, float>
+{
+    Q_OBJECT
+public:
+    Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
+
+    VLCVarFloatObserver(vlc_object_t* object, QString property, QObject* parent = nullptr);
+
+public slots:
+    void setValue(float value);
+
+signals:
+    void valueChanged( float );
+    void valueChangedInternal( vlc_object_t *, float );
+};
+
+
+class VLCVarIntObserver : public VLCVarObserver<VLCVarIntObserver, int64_t>
+{
+    Q_OBJECT
+public:
+    Q_PROPERTY(int64_t value READ getValue WRITE setValue NOTIFY valueChanged)
+
+    VLCVarIntObserver(vlc_object_t* object, QString property, QObject* parent = nullptr);
+
+public slots:
+    void setValue(int64_t value);
+
+signals:
+    void valueChanged( int64_t );
+    void valueChangedInternal( vlc_object_t *,  int64_t );
+};
+
+#endif // VLC_VAR_OBSERVER_HPP
-- 
2.19.1



More information about the vlc-devel mailing list