diff --git a/applications/gui2/src/main.cpp b/applications/gui2/src/main.cpp index 0a7eeccb2e5bca68a9e33e4a5a8bae43ecca348d..500baaca32287a84f9080ea5984a5c446154750a 100644 --- a/applications/gui2/src/main.cpp +++ b/applications/gui2/src/main.cpp @@ -174,5 +174,7 @@ int main(int argc, char **argv) { ftl::pool.stop(true); LOG(INFO) << "All threads stopped."; + ftl::config::cleanup(); + return 0; } diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp index 9f9b8d84855883454f029af5b6b9027d37c23e09..709c08d48e14cce46f116c2c83bd15dfd098e249 100644 --- a/applications/vision/src/main.cpp +++ b/applications/vision/src/main.cpp @@ -297,6 +297,9 @@ int main(int argc, char **argv) { run(root); delete root; + + ftl::config::cleanup(); + LOG(INFO) << "Terminating with code " << ftl::exit_code; LOG(INFO) << "Branch: " << ftl::branch_name; return ftl::exit_code; diff --git a/components/common/cpp/include/ftl/configurable.hpp b/components/common/cpp/include/ftl/configurable.hpp index 1c157ba601c01a1bb8cb01df5eddfd07b60b6269..c32b3dce434a3b93ddb60b1a71841d60825ed3c8 100644 --- a/components/common/cpp/include/ftl/configurable.hpp +++ b/components/common/cpp/include/ftl/configurable.hpp @@ -12,6 +12,7 @@ #include <list> #include <functional> #include <optional> +#include <unordered_set> #define REQUIRED(...) required(__func__, __VA_ARGS__) @@ -102,12 +103,37 @@ class Configurable { */ virtual void refresh(); + /** + * Restore configurable properties from session storage using this key. + * The key could be the same as configurable ID or perhaps uses another + * property such as URI. If restore is used it will also result in a save + * when the configurable is destroyed. The key should ideally be unique. + * + * The allowed parameter specifies the set of properties that can be saved. + */ + void restore(const std::string &key, const std::unordered_set<std::string> &allowed); + + /** + * Load defaults from config file. The key represents type information and + * many configurables can load from the same key. If load defaults has been + * used by the configurable, then it is also called again when the + * configurable is reset. + */ + void loadDefaults(const std::string &key); + + virtual void reset() {}; + + void save(); + protected: nlohmann::json *config_; virtual void inject(const std::string &name, nlohmann::json &value) {} private: + std::string restore_; + std::string defaults_; + std::unordered_set<std::string> save_allowed_; std::map<std::string, std::list<std::function<void(const config::Event&)>>> observers_; void _trigger(const std::string &name); diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp index 5b0106fe0dbc15e8cb3cefbbb7b08630d52d5098..79a5b540322a376799c721eb2f987dd3d10a1325 100644 --- a/components/common/cpp/include/ftl/configuration.hpp +++ b/components/common/cpp/include/ftl/configuration.hpp @@ -42,6 +42,9 @@ Configurable *configure(int argc, char **argv, const std::string &root); Configurable *configure(json_t &); +nlohmann::json &getRestore(const std::string &key); +nlohmann::json &getDefault(const std::string &key); + void cleanup(); void removeConfigurable(Configurable *cfg); diff --git a/components/common/cpp/src/configurable.cpp b/components/common/cpp/src/configurable.cpp index 5791980d43c384a6b3f751b4dc8028e902cf5357..6ded7367f6e28492c501351069c0bd570d96a069 100644 --- a/components/common/cpp/src/configurable.cpp +++ b/components/common/cpp/src/configurable.cpp @@ -26,9 +26,29 @@ Configurable::Configurable(nlohmann::json &config) : config_(&config) { } Configurable::~Configurable() { + save(); ftl::config::removeConfigurable(this); } +void Configurable::save() { + if (restore_.size() > 0) { + auto &r = ftl::config::getRestore(restore_); + for (auto &i : save_allowed_) { + r[i] = (*config_)[i]; + } + } +} + +void Configurable::restore(const std::string &key, const std::unordered_set<std::string> &allowed) { + auto &r = ftl::config::getRestore(key); + if (r.is_object()) { + config_->merge_patch(r); + + } + restore_ = key; + save_allowed_ = allowed; +} + template <typename T> T ftl::Configurable::value(const std::string &name, const T &def) { auto r = get<T>(name); diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp index 9c1154d6e63e88c80197b12b6d681b0a29c7ac30..aba5beede2a9fd37c56c977f49acf794f6442b0b 100644 --- a/components/common/cpp/src/configuration.cpp +++ b/components/common/cpp/src/configuration.cpp @@ -236,11 +236,25 @@ static bool mergeConfig(const string path) { } } +static MUTEX mutex; static std::map<std::string, json_t*> config_index; static std::map<std::string, ftl::Configurable*> config_instance; static std::map<std::string, ftl::Configurable*> config_alias; static std::map<std::string, std::vector<ftl::Configurable*>> tag_index; +static nlohmann::json config_restore; +static nlohmann::json config_defaults; + +nlohmann::json &ftl::config::getRestore(const std::string &key) { + UNIQUE_LOCK(mutex, lk); + return config_restore[key]; +} + +nlohmann::json &ftl::config::getDefault(const std::string &key) { + UNIQUE_LOCK(mutex, lk); + return config_defaults[key]; +} + /* * Recursively URI index the JSON structure. */ @@ -640,19 +654,27 @@ Configurable *ftl::config::configure(ftl::config::json_t &cfg) { return rootcfg; } -static bool doing_cleanup = false; +static std::atomic_bool doing_cleanup = false; void ftl::config::cleanup() { if (doing_cleanup) return; doing_cleanup = true; + + //UNIQUE_LOCK(mutex, lk); + for (auto f : config_instance) { - delete f.second; + //delete f.second; + f.second->save(); } config_instance.clear(); + + ftl::saveJSON(FTL_LOCAL_CONFIG_ROOT "/session.json", config_restore); + doing_cleanup = false; } void ftl::config::removeConfigurable(Configurable *cfg) { if (doing_cleanup) return; + UNIQUE_LOCK(mutex, lk); auto i = config_instance.find(cfg->getID()); if (i != config_instance.end()) { @@ -821,6 +843,8 @@ Configurable *ftl::config::configure(int argc, char **argv, const std::string &r if (options.find("id") != options.end()) config["$id"] = nlohmann::json::parse(options["id"]).get<string>(); _indexConfig(config); + config_restore = std::move(ftl::loadJSON(FTL_LOCAL_CONFIG_ROOT "/session.json")); + Configurable *rootcfg = create<Configurable>(config); if (root_str.size() > 0) { LOG(INFO) << "Setting root to " << root_str; diff --git a/components/streams/src/feed.cpp b/components/streams/src/feed.cpp index a1d3babd61a23627fd6f1582f7cdf7acd52eb3e0..baa9b1e3dfefbf302783417738b91aac98c81a60 100644 --- a/components/streams/src/feed.cpp +++ b/components/streams/src/feed.cpp @@ -22,7 +22,7 @@ using ftl::stream::Feed; using ftl::codecs::Channel; -static nlohmann::json feed_config; +//static nlohmann::json feed_config; //////////////////////////////////////////////////////////////////////////////// @@ -61,7 +61,10 @@ Feed::Filter &Feed::Filter::select(const std::unordered_set<ftl::codecs::Channel Feed::Feed(nlohmann::json &config, ftl::net::Universe*net) : ftl::Configurable(config), net_(net) { - feed_config = ftl::loadJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json"); + //feed_config = ftl::loadJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json"); + restore(ftl::Configurable::getID(), { + "recent_files" + }); pool_ = std::make_unique<ftl::data::Pool>(3,5); @@ -159,7 +162,7 @@ Feed::Feed(nlohmann::json &config, ftl::net::Universe*net) : Feed::~Feed() { std::unique_lock<std::mutex> lk(mtx_); - ftl::saveJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json", feed_config); + //ftl::saveJSON(FTL_LOCAL_CONFIG_ROOT "/feed.json", feed_config); receiver_.reset(); // Note: Force destruction first to remove filters this way @@ -331,7 +334,7 @@ std::vector<std::string> Feed::availableNetworkSources() { std::vector<std::string> Feed::availableFileSources() { std::vector<std::string> files; - auto &recent_files = feed_config["recent_files"]; + auto &recent_files = getConfig()["recent_files"]; for (auto &f : recent_files.items()) { files.push_back(f.key()); @@ -371,7 +374,7 @@ std::string Feed::getName(const std::string &puri) { } else if (uri.getScheme() == ftl::URI::SCHEME_DEVICE) { return "Device"; } else if (uri.getScheme() == ftl::URI::SCHEME_FILE) { - return feed_config["recent_files"][uri.getBaseURI()].value("name", "FTLFile"); + return getConfig()["recent_files"][uri.getBaseURI()].value("name", "FTLFile"); } return "No Name"; @@ -422,7 +425,7 @@ uint32_t Feed::add(const std::string &path) { fstream->set("uri", path); - auto &recent_files = feed_config["recent_files"]; + auto &recent_files = getConfig()["recent_files"]; auto &file_details = recent_files[uri.getBaseURI()]; std::string fname = uri.getPathSegment(-1); file_details["name"] = fname.substr(0, fname.find_last_of('.')); diff --git a/components/streams/src/renderer.cpp b/components/streams/src/renderer.cpp index 3e88b942302fe7b4f21af77de44209052d5e6f46..a9f80db5e27f7210be196a4aa6a230c610de284e 100644 --- a/components/streams/src/renderer.cpp +++ b/components/streams/src/renderer.cpp @@ -11,6 +11,11 @@ using ftl::rgbd::Capability; Source::Source(nlohmann::json &config, ftl::stream::Feed *feed) : ftl::Configurable(config), feed_(feed) { + restore("device:render", { + "renderer", + "source", + "intrinsics" + }); renderer_ = std::unique_ptr<ftl::render::CUDARender>( ftl::create<ftl::render::CUDARender>(this, "renderer")