diff --git a/applications/gui/src/config_window.cpp b/applications/gui/src/config_window.cpp index fcba8ff7ad2e033ab790790b03aed4a3af25af15..d75772f09e84e391e8d6eedd342fe819c1349c68 100644 --- a/applications/gui/src/config_window.cpp +++ b/applications/gui/src/config_window.cpp @@ -15,23 +15,15 @@ using std::string; using std::vector; using ftl::config::json_t; -ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl, const ftl::UUID &peer) : ConfigWindow(parent, ctrl, std::optional<ftl::UUID>(peer)) { - -} - -ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl, const std::optional<ftl::UUID> &peer) - : nanogui::Window(parent, "Settings"), ctrl_(ctrl), peer_(peer) { +ConfigWindow::ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl) + : nanogui::Window(parent, "Settings"), ctrl_(ctrl) { using namespace nanogui; setLayout(new GroupLayout()); setPosition(Vector2i(parent->width()/2.0f - 100.0f, parent->height()/2.0f - 100.0f)); //setModal(true); - if (peer) { - configurables_ = ctrl->getConfigurables(peer.value()); - } else { - configurables_ = ftl::config::list(); - } + configurables_ = ftl::config::list(); new Label(this, "Select Configurable","sans-bold"); @@ -52,67 +44,50 @@ ConfigWindow::~ConfigWindow() { } -class ConfigWindow::References { - public: - References(ftl::NetConfigurable* nc, ftl::config::json_t* config, const std::string* suri) : nc(nc), config(config), suri(suri) { - } - - ~References() { - delete nc; - delete config; - delete suri; - } - - private: - ftl::NetConfigurable* nc; - ftl::config::json_t* config; - const std::string* suri; -}; - -std::vector<ftl::gui::ConfigWindow::References *> ConfigWindow::_addElements(nanogui::FormHelper *form, ftl::Configurable &nc, const std::string &suri, std::function<ftl::Configurable*(const std::string*, std::vector<References *>&)> construct) { +void ConfigWindow::_addElements(nanogui::FormHelper *form, const std::string &suri) { using namespace nanogui; - std::vector<References *> references; - - auto data = nc.getConfig(); + Configurable *configurable = ftl::config::find(suri); + ftl::config::json_t data; + if (configurable) { + data = configurable->getConfig(); + } for (auto i=data.begin(); i!=data.end(); ++i) { if (i.key() == "$id") continue; if (i.key() == "$ref" && i.value().is_string()) { LOG(INFO) << "Follow $ref: " << i.value(); - const std::string* suri = new std::string(i.value().get<string>()); - ftl::Configurable* rc = construct(suri, references); - auto new_references = _addElements(form, *rc, *suri, construct); - references.insert(references.end(), new_references.begin(), new_references.end()); + const std::string suri = std::string(i.value().get<string>()); + _addElements(form, suri); continue; } if (i.value().is_boolean()) { string key = i.key(); - form->addVariable<bool>(i.key(), [this,data,key,&nc](const bool &b){ - nc.set(key, b); + form->addVariable<bool>(i.key(), [this,data,key,suri](const bool &b){ + ftl::config::update(suri+"/"+key, b); }, [data,key]() -> bool { return data[key].get<bool>(); }); } else if (i.value().is_number_integer()) { string key = i.key(); - form->addVariable<int>(i.key(), [this,data,key,&nc](const int &f){ - nc.set(key, f); + form->addVariable<int>(i.key(), [this,data,key,suri](const int &f){ + ftl::config::update(suri+"/"+key, f); }, [data,key]() -> int { return data[key].get<int>(); }); } else if (i.value().is_number_float()) { string key = i.key(); - form->addVariable<float>(i.key(), [this,data,key,&nc](const float &f){ - nc.set(key, f); + form->addVariable<float>(i.key(), [this,data,key,suri](const float &f){ + ftl::config::update(suri+"/"+key, f); }, [data,key]() -> float { return data[key].get<float>(); }); } else if (i.value().is_string()) { string key = i.key(); - form->addVariable<string>(i.key(), [this,data,key,&nc](const string &f){ - nc.set(key, f); + form->addVariable<string>(i.key(), [this,data,key,suri](const string &f){ + ftl::config::update(suri+"/"+key, f); }, [data,key]() -> string { return data[key].get<string>(); }); @@ -131,8 +106,6 @@ std::vector<ftl::gui::ConfigWindow::References *> ConfigWindow::_addElements(nan } } } - - return references; } void ConfigWindow::_buildForm(const std::string &suri) { @@ -145,50 +118,15 @@ void ConfigWindow::_buildForm(const std::string &suri) { form->addWindow(Vector2i(100,50), uri.getFragment()); form->window()->setTheme(theme()); - ftl::config::json_t* config; - config = new ftl::config::json_t; - const std::string* allocated_suri = new std::string(suri); - std::vector<ftl::gui::ConfigWindow::References *> references; - - ftl::Configurable* nc; - - if (peer_) { - *config = ctrl_->get(peer_.value(), suri); - nc = new ftl::NetConfigurable(peer_.value(), *allocated_suri, *ctrl_, *config); + _addElements(form, suri); - references = _addElements(form, *nc, *allocated_suri, [this](auto suri, auto &references) { - ftl::config::json_t* config = new ftl::config::json_t; - *config = ctrl_->get(peer_.value(), *suri); - auto nc = new ftl::NetConfigurable(peer_.value(), *suri, *ctrl_, *config); - auto r = new References(nc, config, suri); - references.push_back(r); - return nc; - }); - } else { - nc = ftl::config::find(suri); - if (nc) { - references = _addElements(form, *nc, *allocated_suri, [this](auto suri, auto &references) { - return ftl::config::find(*suri); - }); - } - } - - auto closebutton = form->addButton("Close", [this,form,config,allocated_suri,nc,references]() { + auto closebutton = form->addButton("Close", [this,form]() { form->window()->setVisible(false); - for(auto r : references) { - delete r; - } - if (peer_) { - delete nc; - } - delete config; - delete allocated_suri; delete form; }); closebutton->setIcon(ENTYPO_ICON_CROSS); } bool ConfigWindow::exists(const std::string &uri) { - // If the Configurable is a NetConfigurable, the URI is not checked. - return peer_ || ftl::config::find(uri); -} \ No newline at end of file + return ftl::config::find(uri) != nullptr; +} diff --git a/applications/gui/src/config_window.hpp b/applications/gui/src/config_window.hpp index 23279d93cee1d601e53e0147b4edee8d5309a483..a0fe74155fe5320f983871d8c9237c7571625670 100644 --- a/applications/gui/src/config_window.hpp +++ b/applications/gui/src/config_window.hpp @@ -16,23 +16,15 @@ namespace gui { */ class ConfigWindow : public nanogui::Window { public: - ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl, const ftl::UUID &peer); - ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl, const std::optional<ftl::UUID> &peer = std::nullopt); + ConfigWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl); ~ConfigWindow(); private: - /* - References holds the pointers to a NetConfigurable and all its members so that - they can all be returned from _addElements() and then simultaneously deleted - as the form is closed. - */ - class References; ftl::ctrl::Master *ctrl_; - std::optional<ftl::UUID> peer_; std::vector<std::string> configurables_; void _buildForm(const std::string &uri); - std::vector<References *> _addElements(nanogui::FormHelper *form, ftl::Configurable &nc, const std::string &suri, std::function<ftl::Configurable*(const std::string*, std::vector<References *>&)> construct); + void _addElements(nanogui::FormHelper *form, const std::string &suri); bool exists(const std::string &uri); }; diff --git a/applications/gui/src/ctrl_window.cpp b/applications/gui/src/ctrl_window.cpp index 67a3682bd2fcfcb55a68fb9c71b6dd55aad36491..fc82c45838a568efc8b4e8d456cdb3fbbef2c8b4 100644 --- a/applications/gui/src/ctrl_window.cpp +++ b/applications/gui/src/ctrl_window.cpp @@ -69,7 +69,7 @@ ControlWindow::ControlWindow(nanogui::Widget *parent, ftl::ctrl::Master *ctrl) button = new Button(tools, "", ENTYPO_ICON_COG); button->setCallback([this,parent] { - auto cfgwin = new ConfigWindow(parent, ctrl_, _getActiveID()); + auto cfgwin = new ConfigWindow(parent, ctrl_); cfgwin->setTheme(theme()); }); button->setTooltip("Edit node configuration"); diff --git a/applications/gui/src/main.cpp b/applications/gui/src/main.cpp index 50bc3638c2e26197fbcf5b74dadacd4b6a49d0ad..7875e52bb04afc59953ac1a728dafe64008b6d6c 100644 --- a/applications/gui/src/main.cpp +++ b/applications/gui/src/main.cpp @@ -2,6 +2,7 @@ #include <ftl/net/universe.hpp> #include <ftl/rgbd.hpp> #include <ftl/master.hpp> +#include <ftl/net_configurable.hpp> #include <loguru.hpp> @@ -12,9 +13,6 @@ int main(int argc, char **argv) { auto root = ftl::configure(argc, argv, "gui_default"); ftl::net::Universe *net = ftl::create<ftl::net::Universe>(root, "net"); - net->start(); - net->waitConnections(); - ftl::ctrl::Master *controller = new ftl::ctrl::Master(root, net); controller->onLog([](const ftl::ctrl::LogEvent &e){ const int v = e.verbosity; @@ -25,6 +23,33 @@ int main(int argc, char **argv) { } }); + std::map<ftl::UUID, std::vector<ftl::NetConfigurable*>> peerConfigurables; + + net->onConnect([&controller, &peerConfigurables](ftl::net::Peer *p) { + ftl::UUID peer = p->id(); + auto cs = controller->getConfigurables(peer); + for (auto c : cs) { + ftl::config::json_t *configuration = new ftl::config::json_t; + *configuration = controller->get(peer, c); + if (!configuration->empty()) { + ftl::NetConfigurable *nc = new ftl::NetConfigurable(peer, c, *controller, *configuration); + peerConfigurables[peer].push_back(nc); + } + } + }); + + net->onDisconnect([&peerConfigurables](ftl::net::Peer *p) { + ftl::UUID peer = p->id(); + for (ftl::NetConfigurable *nc : peerConfigurables[peer]) { + ftl::config::json_t *configuration = &(nc->getConfig()); + delete nc; + delete configuration; + } + }); + + net->start(); + net->waitConnections(); + /*auto available = net.findAll<string>("list_streams"); for (auto &a : available) { std::cout << " -- " << a << std::endl; @@ -57,4 +82,4 @@ int main(int argc, char **argv) { delete root; return 0; -} \ No newline at end of file +} diff --git a/applications/gui/src/media_panel.cpp b/applications/gui/src/media_panel.cpp index b3ea1a6afbbc8f2a31bf294e85a85564fdffe1cb..407fb917222c078c76d34a58d00ac93f2deb7228 100644 --- a/applications/gui/src/media_panel.cpp +++ b/applications/gui/src/media_panel.cpp @@ -18,7 +18,6 @@ MediaPanel::MediaPanel(ftl::gui::Screen *screen) : nanogui::Window(screen, ""), using namespace nanogui; paused_ = false; - writer_ = nullptr; disable_switch_channels_ = false; setLayout(new BoxLayout(Orientation::Horizontal, @@ -38,26 +37,21 @@ MediaPanel::MediaPanel(ftl::gui::Screen *screen) : nanogui::Window(screen, ""), button = new Button(this, "", ENTYPO_ICON_CONTROLLER_RECORD); button->setFlags(Button::ToggleButton); button->setChangeCallback([this,button](bool state) { - if (state){ - auto *cam = screen_->activeCamera(); - - button->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); - char timestamp[18]; - std::time_t t=std::time(NULL); - std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); - writer_ = new ftl::rgbd::SnapshotStreamWriter(std::string(timestamp) + ".tar.gz", 1000 / 25); - writer_->addSource(cam->source()); - writer_->start(); - } else { - button->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); - if (writer_) { - writer_->stop(); - delete writer_; - writer_ = nullptr; + auto tag = screen_->activeCamera()->source()->get<std::string>("uri"); + if (tag) { + auto tagvalue = tag.value(); + auto configurables = ftl::config::findByTag(tagvalue); + if (configurables.size() > 0) { + ftl::Configurable *configurable = configurables[0]; + if (state){ + configurable->set("record", true); + button->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + } else { + button->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); + configurable->set("record", false); + } } } - //if (state) ... start - //else ... stop }); button = new Button(this, "", ENTYPO_ICON_CONTROLLER_STOP); diff --git a/applications/gui/src/screen.cpp b/applications/gui/src/screen.cpp index a9f4cc023265ba427a0be451ee3337fe834528bc..474952f0c8e5df041962a3333d5a1c0ea0a677be 100644 --- a/applications/gui/src/screen.cpp +++ b/applications/gui/src/screen.cpp @@ -229,14 +229,13 @@ ftl::gui::Screen::Screen(ftl::Configurable *proot, ftl::net::Universe *pnet, ftl { LOG(INFO) << "NET CONNECT"; auto node_details = ctrl_->getSlaves(); - std::vector<std::string> node_titles; for (auto &d : node_details) { LOG(INFO) << "ADDING TITLE: " << d.dump(); auto peer = ftl::UUID(d["id"].get<std::string>()); auto itembutton = new Button(popup, d["title"].get<std::string>()); itembutton->setCallback([this,popup,peer]() { - auto config_window = new ConfigWindow(this, ctrl_, peer); + auto config_window = new ConfigWindow(this, ctrl_); config_window->setTheme(windowtheme); }); } diff --git a/applications/gui/src/src_window.cpp b/applications/gui/src/src_window.cpp index 8e087d1dd42e25b00afd0efaf7b5dd22d5139a0d..b5eb141f72278ed986aac47b6bb3bd2feb7a7345 100644 --- a/applications/gui/src/src_window.cpp +++ b/applications/gui/src/src_window.cpp @@ -63,7 +63,7 @@ SourceWindow::SourceWindow(ftl::gui::Screen *screen) UNIQUE_LOCK(mutex_, lk); _updateCameras(screen_->net()->findAll<string>("list_streams")); }); - + UNIQUE_LOCK(mutex_, lk); std::vector<ftl::rgbd::Source*> srcs = ftl::createArray<ftl::rgbd::Source>(screen_->root(), "sources", screen_->net()); diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index 83dd19f84dabd37d345c0ac1294970fa8fd8c4cf..02ee515a1a02bf6128a051a7c67d860ed538b075 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -176,6 +176,7 @@ static void run(ftl::Configurable *root) { //ftl::voxhash::SceneRep *scene = ftl::create<ftl::voxhash::SceneRep>(root, "voxelhash"); ftl::rgbd::Streamer *stream = ftl::create<ftl::rgbd::Streamer>(root, "stream", net); ftl::rgbd::VirtualSource *virt = ftl::create<ftl::rgbd::VirtualSource>(root, "virtual"); + root->set("tags", nlohmann::json::array({ root->getID()+"/virtual" })); ftl::render::Triangular *splat = ftl::create<ftl::render::Triangular>(root, "renderer", &scene_B); ftl::rgbd::Group *group = new ftl::rgbd::Group; ftl::ILW *align = ftl::create<ftl::ILW>(root, "merge"); diff --git a/components/common/cpp/include/ftl/configuration.hpp b/components/common/cpp/include/ftl/configuration.hpp index 94fcc7dfa6b57e9bfd59fbcf36c5be80e0b82638..9e4ba8aed4bcf8b5f2c8cec2c1079edb945359c3 100644 --- a/components/common/cpp/include/ftl/configuration.hpp +++ b/components/common/cpp/include/ftl/configuration.hpp @@ -72,6 +72,13 @@ json_t &resolveWait(const std::string &); */ Configurable *find(const std::string &uri); +/** + * Get all configurables that contain a specified tag. Tags are given under the + * "tags" property as an array of strings, but only during configurable + * construction. + */ +const std::vector<Configurable *> &findByTag(const std::string &tag); + std::vector<std::string> list(); /** diff --git a/components/common/cpp/src/configuration.cpp b/components/common/cpp/src/configuration.cpp index bd9d9feec20538cebc210cafba72a98f651b243c..082285f4826b88fb0a7589d76e9ec27cc7c9c1ee 100644 --- a/components/common/cpp/src/configuration.cpp +++ b/components/common/cpp/src/configuration.cpp @@ -165,6 +165,7 @@ static bool mergeConfig(const string path) { static std::map<std::string, json_t*> config_index; static std::map<std::string, ftl::Configurable*> config_instance; +static std::map<std::string, std::vector<ftl::Configurable*>> tag_index; /* * Recursively URI index the JSON structure. @@ -198,6 +199,10 @@ ftl::Configurable *ftl::config::find(const std::string &uri) { else return (*ix).second; } +const std::vector<Configurable*> &ftl::config::findByTag(const std::string &tag) { + return tag_index[tag]; +} + std::vector<std::string> ftl::config::list() { vector<string> r; for (auto i : config_instance) { @@ -219,6 +224,13 @@ void ftl::config::registerConfigurable(ftl::Configurable *cfg) { } else { config_instance[*uri] = cfg; LOG(INFO) << "Registering instance: " << *uri; + + auto tags = cfg->get<vector<string>>("tags"); + if (tags) { + for (auto &t : *tags) { + tag_index[t].push_back(cfg); + } + } } } diff --git a/components/net/cpp/include/ftl/net_configurable.hpp b/components/net/cpp/include/ftl/net_configurable.hpp index 3a31ecc27675f2e37b72bc42ee83da0dee5b7e4c..a9deaf94b0a75c121d6fcd367715da1b465a8ef2 100644 --- a/components/net/cpp/include/ftl/net_configurable.hpp +++ b/components/net/cpp/include/ftl/net_configurable.hpp @@ -17,7 +17,7 @@ namespace ftl { private: ftl::UUID peer; - const std::string &suri; + const std::string suri; ftl::ctrl::Master &ctrl; };