Add metadata object handling
authorSoeren Apel <soeren@apelpie.net>
Mon, 27 Apr 2020 09:00:36 +0000 (11:00 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Sun, 3 May 2020 15:20:55 +0000 (17:20 +0200)
CMakeLists.txt
pv/metadata_obj.cpp [new file with mode: 0644]
pv/metadata_obj.hpp [new file with mode: 0644]
pv/session.cpp
pv/session.hpp
pv/views/tabular_decoder/view.hpp
test/CMakeLists.txt

index c77435d462c37ba352e9482aa3e799d4668b4b34..bd5de9ec8730296474c0b5365fbeaddd495a7264 100644 (file)
@@ -247,6 +247,7 @@ set(pulseview_SOURCES
        pv/globalsettings.cpp
        pv/logging.cpp
        pv/mainwindow.cpp
+       pv/metadata_obj.cpp
        pv/session.cpp
        pv/storesession.cpp
        pv/util.cpp
@@ -322,6 +323,7 @@ set(pulseview_HEADERS
        pv/logging.hpp
        pv/globalsettings.hpp
        pv/mainwindow.hpp
+       pv/metadata_obj.hpp
        pv/session.hpp
        pv/storesession.hpp
        pv/binding/device.hpp
diff --git a/pv/metadata_obj.cpp b/pv/metadata_obj.cpp
new file mode 100644 (file)
index 0000000..72b4be6
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2020 Soeren Apel <soeren@apelpie.net>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "metadata_obj.hpp"
+
+
+namespace pv {
+
+const char* MetadataObjectNames[MetadataObjTypeCount] = {
+       "main_view_range",
+       "selection",
+       "time_marker"
+};
+
+const char* MetadataValueNames[MetadataObjValueCount] = {
+       "start_sample",
+       "end_sample"
+       "text"
+};
+
+
+MetadataObject::MetadataObject(MetadataObjManager* obj_manager, uint32_t obj_id,
+       MetadataObjectType obj_type) :
+       obj_manager_(obj_manager),
+       id_(obj_id),
+       type_(obj_type)
+{
+       // Make sure we accept all value type indices
+       values_.resize(MetadataObjValueCount);
+}
+
+uint32_t MetadataObject::id() const
+{
+       return id_;
+}
+
+MetadataObjectType MetadataObject::type() const
+{
+       return type_;
+}
+
+void MetadataObject::set_value(MetadataValueType value_type, QVariant& value)
+{
+       values_.at((uint8_t)value_type) = value;
+       obj_manager_->notify_observers(this, value_type);
+}
+
+QVariant MetadataObject::value(MetadataValueType value_type) const
+{
+       return values_.at((uint8_t)value_type);
+}
+
+
+MetadataObject* MetadataObjManager::create_object(MetadataObjectType obj_type)
+{
+       // Note: This function is not reentrant as race conditions between
+       // emplace_back() and back() may occur
+
+       objects_.emplace_back(this, objects_.size(), obj_type);
+       MetadataObject* obj = &(objects_.back());
+
+       for (MetadataObjObserverInterface *cb : callbacks_)
+               cb->on_metadata_object_created(obj->id(), obj->type());
+
+       return obj;
+}
+
+void MetadataObjManager::delete_object(uint32_t obj_id)
+{
+       MetadataObjectType type = objects_.at(obj_id).type();
+
+       objects_.erase(std::remove_if(objects_.begin(), objects_.end(),
+               [&](MetadataObject obj) { return obj.id() == obj_id; }),
+               objects_.end());
+
+       for (MetadataObjObserverInterface *cb : callbacks_)
+               cb->on_metadata_object_deleted(obj_id, type);
+}
+
+MetadataObject* MetadataObjManager::find_object_by_type(MetadataObjectType obj_type)
+{
+       for (MetadataObject& obj : objects_)
+               if (obj.type() == obj_type)
+                       return &obj;
+
+       return nullptr;
+}
+
+MetadataObject* MetadataObjManager::object(uint32_t obj_id)
+{
+       return &(objects_.at(obj_id));
+}
+
+void MetadataObjManager::add_observer(MetadataObjObserverInterface *cb)
+{
+       callbacks_.emplace_back(cb);
+}
+
+void MetadataObjManager::remove_observer(MetadataObjObserverInterface *cb)
+{
+       for (auto cb_it = callbacks_.begin(); cb_it != callbacks_.end(); cb_it++)
+               if (*cb_it == cb) {
+                       callbacks_.erase(cb_it);
+                       break;
+               }
+}
+
+void MetadataObjManager::save_objects(QSettings &settings) const
+{
+       (void)settings;
+}
+
+void MetadataObjManager::restore_objects(QSettings &settings)
+{
+       (void)settings;
+}
+
+void MetadataObjManager::notify_observers(MetadataObject* obj,
+       MetadataValueType changed_value)
+{
+       for (MetadataObjObserverInterface *cb : callbacks_)
+               cb->on_metadata_object_changed(obj->id(), obj->type(), changed_value,
+                       obj->value(changed_value));
+}
+
+} // namespace pv
diff --git a/pv/metadata_obj.hpp b/pv/metadata_obj.hpp
new file mode 100644 (file)
index 0000000..593fe96
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2020 Soeren Apel <soeren@apelpie.net>
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PULSEVIEW_PV_METADATA_OBJ_HPP
+#define PULSEVIEW_PV_METADATA_OBJ_HPP
+
+#include <deque>
+#include <vector>
+
+#include <QObject>
+#include <QSettings>
+#include <QString>
+
+using std::deque;
+using std::vector;
+
+namespace pv {
+
+
+// When adding an entry here, don't forget to update MetadataObjectNames as well
+enum MetadataObjectType {
+       MetadataObjMainViewRange,
+       MetadataObjSelection,
+       MetadataObjTimeMarker,
+       MetadataObjTypeCount  // Indicates how many metadata object types there are, must always be last
+};
+
+// When adding an entry here, don't forget to update MetadataValueNames as well
+enum MetadataValueType {
+       MetadataObjStartSample,
+       MetadataObjEndSample,
+       MetadataObjText,
+       MetadataObjValueCount  // Indicates how many metadata value types there are, must always be last
+};
+
+extern const char* MetadataObjectNames[MetadataObjTypeCount];
+extern const char* MetadataValueNames[MetadataObjValueCount];
+
+
+class MetadataObjManager;
+
+
+class MetadataObjObserverInterface
+{
+public:
+       virtual void on_metadata_object_created(uint32_t obj_id, MetadataObjectType obj_type) = 0;
+       virtual void on_metadata_object_deleted(uint32_t obj_id, MetadataObjectType obj_type) = 0;
+       virtual void on_metadata_object_changed(uint32_t obj_id, MetadataObjectType obj_type,
+               MetadataValueType value_type, const QVariant& value) = 0;
+};
+
+
+class MetadataObject
+{
+public:
+       MetadataObject(MetadataObjManager* obj_manager, uint32_t obj_id, MetadataObjectType obj_type);
+       virtual ~MetadataObject() = default;
+
+       virtual uint32_t id() const;
+       virtual MetadataObjectType type() const;
+
+       virtual void set_value(MetadataValueType value_type, QVariant& value);
+       virtual QVariant value(MetadataValueType value_type) const;
+private:
+       MetadataObjManager* obj_manager_;
+       uint32_t id_;
+       MetadataObjectType type_;
+       vector<QVariant> values_;
+};
+
+
+class MetadataObjManager : public QObject
+{
+       Q_OBJECT
+
+public:
+       MetadataObject* create_object(MetadataObjectType obj_type);
+       void delete_object(uint32_t obj_id);
+       MetadataObject* find_object_by_type(MetadataObjectType obj_type);
+       MetadataObject* object(uint32_t obj_id);
+
+       void add_observer(MetadataObjObserverInterface *cb);
+       void remove_observer(MetadataObjObserverInterface *cb);
+
+       void save_objects(QSettings &settings) const;
+       void restore_objects(QSettings &settings);
+
+       void notify_observers(MetadataObject* obj, MetadataValueType changed_value);
+
+private:
+       vector<MetadataObjObserverInterface*> callbacks_;
+       deque<MetadataObject> objects_;
+};
+
+
+} // namespace pv
+
+#endif // PULSEVIEW_PV_METADATA_OBJ_HPP
index 6b879cf91dcdd4e4b6127cb99a780366042d09a1..d50a9dd6a41420c16a92d70c3898104657004064 100644 (file)
@@ -905,6 +905,11 @@ void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
 }
 #endif
 
+MetadataObjManager* Session::metadata_obj_manager()
+{
+       return &metadata_obj_manager_;
+}
+
 void Session::set_capture_state(capture_state state)
 {
        bool changed;
index 095c4dd0217dd51f490c3d4d99bbc3d952b773b9..ac3a076d2fb8d5e0edda93c86a849b5e16310847 100644 (file)
 #include <libsigrokflow/libsigrokflow.hpp>
 #endif
 
+#include "metadata_obj.hpp"
 #include "util.hpp"
 #include "views/viewbase.hpp"
 
-
 using std::function;
 using std::map;
 using std::mutex;
@@ -108,6 +108,7 @@ namespace views {
 class ViewBase;
 }
 
+
 class Session : public QObject
 {
        Q_OBJECT
@@ -135,15 +136,12 @@ public:
        shared_ptr<devices::Device> device() const;
 
        QString name() const;
-
        void set_name(QString name);
 
        const vector< shared_ptr<views::ViewBase> > views() const;
 
        shared_ptr<views::ViewBase> main_view() const;
-
        shared_ptr<pv::toolbars::MainBar> main_bar() const;
-
        void set_main_bar(shared_ptr<pv::toolbars::MainBar> main_bar);
 
        /**
@@ -152,11 +150,8 @@ public:
        bool data_saved() const;
 
        void save_setup(QSettings &settings) const;
-
        void save_settings(QSettings &settings) const;
-
        void restore_setup(QSettings &settings);
-
        void restore_settings(QSettings &settings);
 
        /**
@@ -168,9 +163,7 @@ public:
         * Sets device instance that will be used in the next capture session.
         */
        void set_device(shared_ptr<devices::Device> device);
-
        void set_default_device();
-
        bool using_file_device() const;
 
        void load_init_file(const string &file_name, const string &format,
@@ -182,9 +175,7 @@ public:
                        map<string, Glib::VariantBase>());
 
        capture_state get_capture_state() const;
-
        void start_capture(function<void (const QString)> error_handler);
-
        void stop_capture();
 
        double get_samplerate() const;
@@ -194,9 +185,7 @@ public:
        vector<util::Timestamp> get_triggers(uint32_t segment_id) const;
 
        void register_view(shared_ptr<views::ViewBase> view);
-
        void deregister_view(shared_ptr<views::ViewBase> view);
-
        bool has_view(shared_ptr<views::ViewBase> view);
 
        const vector< shared_ptr<data::SignalBase> > signalbases() const;
@@ -209,6 +198,8 @@ public:
        void remove_decode_signal(shared_ptr<data::DecodeSignal> signal);
 #endif
 
+       MetadataObjManager* metadata_obj_manager();
+
 private:
        void set_capture_state(capture_state state);
 
@@ -235,16 +226,11 @@ private:
 #endif
 
        void feed_in_header();
-
        void feed_in_meta(shared_ptr<sigrok::Meta> meta);
-
        void feed_in_trigger();
-
        void feed_in_frame_begin();
        void feed_in_frame_end();
-
        void feed_in_logic(shared_ptr<sigrok::Logic> logic);
-
        void feed_in_analog(shared_ptr<sigrok::Analog> analog);
 
        void data_feed_in(shared_ptr<sigrok::Device> device,
@@ -309,6 +295,8 @@ private:
 
        QElapsedTimer acq_time_;
 
+       MetadataObjManager metadata_obj_manager_;
+
 #ifdef ENABLE_FLOW
        RefPtr<Pipeline> pipeline_;
        RefPtr<Element> source_;
index 93761bda49bc15e56fadad2162bec7791aa55b13..290e42a14b8f06d57bf079dd9e4aec351a3e832a 100644 (file)
@@ -49,7 +49,7 @@ enum ViewModeType {
        ViewModeAll,
        ViewModeLatest,
 //     ViewModeVisible,
-       ViewModeCount // Indicates how many save types there are, must always be last
+       ViewModeCount // Indicates how many view mode types there are, must always be last
 };
 
 extern const char* SaveTypeNames[SaveTypeCount];
index 5ab5afa4a22c1ff839796d83064036462038f763..2b6cb87eacb05c12d4a7ec90a626b24a84cef280 100644 (file)
@@ -24,6 +24,7 @@ set(pulseview_TEST_SOURCES
        ${PROJECT_SOURCE_DIR}/pv/globalsettings.cpp
        ${PROJECT_SOURCE_DIR}/pv/logging.cpp
        ${PROJECT_SOURCE_DIR}/pv/mainwindow.cpp
+       ${PROJECT_SOURCE_DIR}/pv/metadata_obj.cpp
        ${PROJECT_SOURCE_DIR}/pv/session.cpp
        ${PROJECT_SOURCE_DIR}/pv/storesession.cpp
        ${PROJECT_SOURCE_DIR}/pv/util.cpp
@@ -107,6 +108,7 @@ set(pulseview_TEST_HEADERS
        ${PROJECT_SOURCE_DIR}/pv/globalsettings.hpp
        ${PROJECT_SOURCE_DIR}/pv/logging.hpp
        ${PROJECT_SOURCE_DIR}/pv/mainwindow.hpp
+       ${PROJECT_SOURCE_DIR}/pv/metadata_obj.hpp
        ${PROJECT_SOURCE_DIR}/pv/session.hpp
        ${PROJECT_SOURCE_DIR}/pv/storesession.hpp
        ${PROJECT_SOURCE_DIR}/pv/binding/device.hpp