From: Soeren Apel Date: Mon, 27 Apr 2020 09:00:36 +0000 (+0200) Subject: Add metadata object handling X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=commitdiff_plain;h=f2739baea42501f5ad5f503f6ead9374b9253566 Add metadata object handling --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c77435d4..bd5de9ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 index 00000000..72b4be66 --- /dev/null +++ b/pv/metadata_obj.cpp @@ -0,0 +1,142 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2020 Soeren Apel + * + * 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 . + */ + +#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 index 00000000..593fe968 --- /dev/null +++ b/pv/metadata_obj.hpp @@ -0,0 +1,114 @@ +/* + * This file is part of the PulseView project. + * + * Copyright (C) 2020 Soeren Apel + * + * 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 . + */ + +#ifndef PULSEVIEW_PV_METADATA_OBJ_HPP +#define PULSEVIEW_PV_METADATA_OBJ_HPP + +#include +#include + +#include +#include +#include + +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 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 callbacks_; + deque objects_; +}; + + +} // namespace pv + +#endif // PULSEVIEW_PV_METADATA_OBJ_HPP diff --git a/pv/session.cpp b/pv/session.cpp index 6b879cf9..d50a9dd6 100644 --- a/pv/session.cpp +++ b/pv/session.cpp @@ -905,6 +905,11 @@ void Session::remove_decode_signal(shared_ptr signal) } #endif +MetadataObjManager* Session::metadata_obj_manager() +{ + return &metadata_obj_manager_; +} + void Session::set_capture_state(capture_state state) { bool changed; diff --git a/pv/session.hpp b/pv/session.hpp index 095c4dd0..ac3a076d 100644 --- a/pv/session.hpp +++ b/pv/session.hpp @@ -45,10 +45,10 @@ #include #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 device() const; QString name() const; - void set_name(QString name); const vector< shared_ptr > views() const; shared_ptr main_view() const; - shared_ptr main_bar() const; - void set_main_bar(shared_ptr 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 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()); capture_state get_capture_state() const; - void start_capture(function error_handler); - void stop_capture(); double get_samplerate() const; @@ -194,9 +185,7 @@ public: vector get_triggers(uint32_t segment_id) const; void register_view(shared_ptr view); - void deregister_view(shared_ptr view); - bool has_view(shared_ptr view); const vector< shared_ptr > signalbases() const; @@ -209,6 +198,8 @@ public: void remove_decode_signal(shared_ptr 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 meta); - void feed_in_trigger(); - void feed_in_frame_begin(); void feed_in_frame_end(); - void feed_in_logic(shared_ptr logic); - void feed_in_analog(shared_ptr analog); void data_feed_in(shared_ptr device, @@ -309,6 +295,8 @@ private: QElapsedTimer acq_time_; + MetadataObjManager metadata_obj_manager_; + #ifdef ENABLE_FLOW RefPtr pipeline_; RefPtr source_; diff --git a/pv/views/tabular_decoder/view.hpp b/pv/views/tabular_decoder/view.hpp index 93761bda..290e42a1 100644 --- a/pv/views/tabular_decoder/view.hpp +++ b/pv/views/tabular_decoder/view.hpp @@ -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]; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5ab5afa4..2b6cb87e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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