From 00bd9ac32579941442d209ae2740919f1c754735 Mon Sep 17 00:00:00 2001 From: Iiro Rastas <iiro.t.rastas@utu.fi> Date: Tue, 19 Nov 2019 13:38:05 +0200 Subject: [PATCH] Restore record button functionality The record button now works as previously. To support this change, a tagging system based on the one from feature/guienhance has been added. NetConfigurables are now created as peers connect and removed as they disconnect, which required changes to ConfigWindow. --- applications/ftl2mkv/src/main.cpp | 29 ++--- applications/gui/src/camera.cpp | 41 +++++- applications/gui/src/camera.hpp | 11 +- applications/gui/src/config_window.cpp | 117 +++++------------- applications/gui/src/config_window.hpp | 12 +- applications/gui/src/ctrl_window.cpp | 2 +- applications/gui/src/main.cpp | 33 ++++- applications/gui/src/media_panel.cpp | 70 +++++++---- applications/gui/src/screen.cpp | 27 ++-- applications/gui/src/src_window.cpp | 10 +- applications/gui/src/src_window.hpp | 2 +- applications/reconstruct/src/main.cpp | 1 + .../common/cpp/include/ftl/configuration.hpp | 7 ++ components/common/cpp/src/configuration.cpp | 12 ++ .../net/cpp/include/ftl/net_configurable.hpp | 2 +- .../rgbd-sources/include/ftl/rgbd/source.hpp | 6 +- 16 files changed, 219 insertions(+), 163 deletions(-) diff --git a/applications/ftl2mkv/src/main.cpp b/applications/ftl2mkv/src/main.cpp index b555dcbf7..a6a7a2448 100644 --- a/applications/ftl2mkv/src/main.cpp +++ b/applications/ftl2mkv/src/main.cpp @@ -99,7 +99,7 @@ int main(int argc, char **argv) { AVOutputFormat *fmt; AVFormatContext *oc; - AVStream *video_st[10] = {nullptr}; + AVStream *video_st[10][2] = {nullptr}; av_register_all(); @@ -130,28 +130,24 @@ int main(int argc, char **argv) { LOG(INFO) << "Converting..."; int current_stream = root->value("stream", 0); - int current_channel = 0; + int current_channel = root->value("channel", -1); //bool stream_added[10] = {false}; // TODO: In future, find a better way to discover number of streams... // Read entire file to find all streams before reading again to write data bool res = r.read(90000000000000, [¤t_stream,¤t_channel,&r,&video_st,oc](const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { - if (spkt.channel != static_cast<ftl::codecs::Channel>(current_channel)) return; + if (spkt.channel != static_cast<ftl::codecs::Channel>(current_channel) && current_channel != -1) return; if (spkt.streamID == current_stream || current_stream == 255) { - if (pkt.codec == codec_t::POSE) { - return; - } - - if (pkt.codec == codec_t::CALIBRATION) { + if (pkt.codec != codec_t::HEVC) { return; } if (spkt.streamID >= 10) return; // TODO: Allow for more than 10 - if (video_st[spkt.streamID] == nullptr) { - video_st[spkt.streamID] = add_video_stream(oc, pkt); + if (video_st[spkt.streamID][(spkt.channel == Channel::Left) ? 0 : 1] == nullptr) { + video_st[spkt.streamID][(spkt.channel == Channel::Left) ? 0 : 1] = add_video_stream(oc, pkt); } } }); @@ -172,14 +168,10 @@ int main(int argc, char **argv) { bool seen_key[10] = {false}; res = r.read(90000000000000, [¤t_stream,¤t_channel,&r,&video_st,oc,&seen_key](const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { - if (spkt.channel != static_cast<ftl::codecs::Channel>(current_channel)) return; + if (spkt.channel != static_cast<ftl::codecs::Channel>(current_channel) && current_channel != -1) return; if (spkt.streamID == current_stream || current_stream == 255) { - if (pkt.codec == codec_t::POSE) { - return; - } - - if (pkt.codec == codec_t::CALIBRATION) { + if (pkt.codec != codec_t::HEVC) { return; } @@ -201,7 +193,7 @@ int main(int argc, char **argv) { if (keyframe) avpkt.flags |= AV_PKT_FLAG_KEY; avpkt.pts = spkt.timestamp - r.getStartTime(); avpkt.dts = avpkt.pts; - avpkt.stream_index= video_st[spkt.streamID]->index; + avpkt.stream_index= video_st[spkt.streamID][(spkt.channel == Channel::Left) ? 0 : 1]->index; avpkt.data= const_cast<uint8_t*>(pkt.data.data()); avpkt.size= pkt.data.size(); avpkt.duration = 1; @@ -220,7 +212,8 @@ int main(int argc, char **argv) { //avcodec_close(video_st->codec); for (int i=0; i<10; ++i) { - if (video_st[i]) av_free(video_st[i]); + if (video_st[i][0]) av_free(video_st[i][0]); + if (video_st[i][1]) av_free(video_st[i][1]); } if (!(fmt->flags & AVFMT_NOFILE)) { diff --git a/applications/gui/src/camera.cpp b/applications/gui/src/camera.cpp index ae0d5627a..ff13ce928 100644 --- a/applications/gui/src/camera.cpp +++ b/applications/gui/src/camera.cpp @@ -137,6 +137,13 @@ ftl::gui::Camera::Camera(ftl::gui::Screen *screen, ftl::rgbd::Source *src) : scr sdepth_ = false; ftime_ = (float)glfwGetTime(); pause_ = false; + recording_ = false; + fileout_ = new std::ofstream(); + writer_ = new ftl::codecs::Writer(*fileout_); + recorder_ = std::function([this](ftl::rgbd::Source *src, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt) { + ftl::codecs::StreamPacket s = spkt; + writer_->write(s, pkt); + }); channel_ = Channel::Left; @@ -166,7 +173,8 @@ ftl::gui::Camera::Camera(ftl::gui::Screen *screen, ftl::rgbd::Source *src) : scr } ftl::gui::Camera::~Camera() { - + delete writer_; + delete fileout_; } ftl::rgbd::Source *ftl::gui::Camera::source() { @@ -494,6 +502,37 @@ const GLTexture &ftl::gui::Camera::captureFrame() { return texture1_; } +void ftl::gui::Camera::snapshot() { + UNIQUE_LOCK(mutex_, lk); + char timestamp[18]; + std::time_t t = std::time(NULL); + std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); + cv::Mat image; + cv::flip(im1_, image, 0); + cv::imwrite(std::string(timestamp) + ".png", image); +} + +void ftl::gui::Camera::toggleVideoRecording() { + if (recording_) { + src_->removeRawCallback(recorder_); + writer_->end(); + fileout_->close(); + recording_ = false; + } else { + char timestamp[18]; + std::time_t t=std::time(NULL); + std::strftime(timestamp, sizeof(timestamp), "%F-%H%M%S", std::localtime(&t)); + fileout_->open(std::string(timestamp) + ".ftl"); + + writer_->begin(); + src_->addRawCallback(recorder_); + + src_->inject(Channel::Calibration, src_->parameters(), Channel::Left, src_->getCapabilities()); + src_->inject(src_->getPose()); + recording_ = true; + } +} + nlohmann::json ftl::gui::Camera::getMetaData() { return nlohmann::json(); } diff --git a/applications/gui/src/camera.hpp b/applications/gui/src/camera.hpp index 24dcbacfd..43cf9c783 100644 --- a/applications/gui/src/camera.hpp +++ b/applications/gui/src/camera.hpp @@ -2,6 +2,7 @@ #define _FTL_GUI_CAMERA_HPP_ #include <ftl/rgbd/source.hpp> +#include <ftl/codecs/writer.hpp> #include "gltexture.hpp" #include <string> @@ -43,7 +44,7 @@ class Camera { void togglePause(); void isPaused(); - const ftl::codecs::Channels &availableChannels(); + const ftl::codecs::Channels &availableChannels() { return channels_; } const GLTexture &captureFrame(); const GLTexture &getLeft() const { return texture1_; } @@ -51,6 +52,10 @@ class Camera { bool thumbnail(cv::Mat &thumb); + void snapshot(); + + void toggleVideoRecording(); + nlohmann::json getMetaData(); StatisticsImage *stats_ = nullptr; @@ -85,6 +90,10 @@ class Camera { ftl::codecs::Channels channels_; cv::Mat im1_; // first channel (left) cv::Mat im2_; // second channel ("right") + bool recording_; + std::ofstream *fileout_; + ftl::codecs::Writer *writer_; + ftl::rgbd::RawCallback recorder_; MUTEX mutex_; diff --git a/applications/gui/src/config_window.cpp b/applications/gui/src/config_window.cpp index fcba8ff7a..4832454ad 100644 --- a/applications/gui/src/config_window.cpp +++ b/applications/gui/src/config_window.cpp @@ -2,10 +2,10 @@ #include <nanogui/layout.h> #include <nanogui/label.h> -#include <nanogui/combobox.h> #include <nanogui/button.h> #include <nanogui/entypo.h> #include <nanogui/formhelper.h> +#include <nanogui/vscrollpanel.h> #include <vector> #include <string> @@ -15,28 +15,25 @@ 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"); + auto vscroll = new VScrollPanel(this); + vscroll->setFixedHeight(300); + Widget *buttons = new Widget(vscroll); + buttons->setLayout(new BoxLayout(Orientation::Vertical, Alignment::Fill)); + for (auto c : configurables_) { - auto itembutton = new Button(this, c); + auto itembutton = new Button(buttons, c); itembutton->setCallback([this,c]() { LOG(INFO) << "Change configurable: " << c; _buildForm(c); @@ -52,67 +49,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 +111,6 @@ std::vector<ftl::gui::ConfigWindow::References *> ConfigWindow::_addElements(nan } } } - - return references; } void ConfigWindow::_buildForm(const std::string &suri) { @@ -145,50 +123,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 23279d93c..a0fe74155 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 67a3682bd..fc82c4583 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 50bc3638c..7875e52bb 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 800940199..abfff4a03 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, @@ -35,30 +34,57 @@ MediaPanel::MediaPanel(ftl::gui::Screen *screen) : nanogui::Window(screen, ""), if (cam) cam->showPoseWindow(); }); - 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 recordbutton = new PopupButton(this, "", ENTYPO_ICON_CONTROLLER_RECORD); + recordbutton->setTooltip("Record"); + recordbutton->setSide(Popup::Side::Right); + recordbutton->setChevronIcon(0); + auto recordpopup = recordbutton->popup(); + recordpopup->setLayout(new GroupLayout()); + recordpopup->setTheme(screen->toolbuttheme); + recordpopup->setAnchorHeight(150); + auto itembutton = new Button(recordpopup, "2D snapshot (.png)"); + itembutton->setCallback([this,recordbutton]() { + screen_->activeCamera()->snapshot(); + recordbutton->setPushed(false); + }); + itembutton = new Button(recordpopup, "Virtual camera recording (.ftl)"); + itembutton->setCallback([this,recordbutton]() { + std::cout << "Toggling video recording in itembutton callback." << '\n'; + screen_->activeCamera()->toggleVideoRecording(); + recordbutton->setCallback([this,recordbutton]() { + std::cout << "Toggling video recording in recordbutton callback." << '\n'; + screen_->activeCamera()->toggleVideoRecording(); + recordbutton->setCallback([]() {}); + recordbutton->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); + + // Prevents the popup from being opened, though it is shown while the button + // is being pressed. + recordbutton->setPushed(false); + }); + recordbutton->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + recordbutton->setPushed(false); + }); + itembutton = new Button(recordpopup, "3D scene recording (.ftl)"); + itembutton->setCallback([this,recordbutton]() { + 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]; + configurable->set("record", true); + recordbutton->setTextColor(nanogui::Color(1.0f,0.1f,0.1f,1.0f)); + recordbutton->setCallback([this,recordbutton,configurable]() { + configurable->set("record", false); + recordbutton->setCallback([]() {}); + recordbutton->setTextColor(nanogui::Color(1.0f,1.0f,1.0f,1.0f)); + recordbutton->setPushed(false); + }); } } - //if (state) ... start - //else ... stop + recordbutton->setPushed(false); }); + itembutton = new Button(recordpopup, "Detailed recording options"); button = new Button(this, "", ENTYPO_ICON_CONTROLLER_STOP); button->setCallback([this]() { diff --git a/applications/gui/src/screen.cpp b/applications/gui/src/screen.cpp index c359e227d..1ee7425ab 100644 --- a/applications/gui/src/screen.cpp +++ b/applications/gui/src/screen.cpp @@ -6,7 +6,6 @@ #include <nanogui/window.h> #include <nanogui/layout.h> #include <nanogui/imageview.h> -#include <nanogui/combobox.h> #include <nanogui/label.h> #include <nanogui/toolbutton.h> #include <nanogui/popupbutton.h> @@ -229,30 +228,29 @@ ftl::gui::Screen::Screen(ftl::Configurable *proot, ftl::net::Universe *pnet, ftl popup->setVisible(false); }); - popbutton = new PopupButton(innertool, "", ENTYPO_ICON_COG); - popbutton->setIconExtraScale(1.5f); - popbutton->setTheme(toolbuttheme); - popbutton->setTooltip("Settings"); - popbutton->setFixedSize(Vector2i(40,40)); - popbutton->setSide(Popup::Side::Right); - popbutton->setChevronIcon(0); - // popbutton->setPosition(Vector2i(5,height()-50)); - popup = popbutton->popup(); - popup->setLayout(new GroupLayout()); - popup->setTheme(toolbuttheme); + itembutton = new Button(innertool, "", ENTYPO_ICON_COG); + itembutton->setIconExtraScale(1.5f); + itembutton->setTheme(toolbuttheme); + itembutton->setTooltip("Settings"); + itembutton->setFixedSize(Vector2i(40,40)); + + itembutton->setCallback([this]() { + auto config_window = new ConfigWindow(this, ctrl_); + config_window->setTheme(windowtheme); + }); + /* //net_->onConnect([this,popup](ftl::net::Peer *p) { { 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); }); } @@ -264,6 +262,7 @@ ftl::gui::Screen::Screen(ftl::Configurable *proot, ftl::net::Universe *pnet, ftl auto config_window = new ConfigWindow(this, ctrl_); config_window->setTheme(windowtheme); }); + */ //configwindow_ = new ConfigWindow(parent, ctrl_); cwindow_ = new ftl::gui::ControlWindow(this, controller); diff --git a/applications/gui/src/src_window.cpp b/applications/gui/src/src_window.cpp index 8e087d1dd..0126810a5 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()); @@ -74,6 +74,14 @@ SourceWindow::SourceWindow(ftl::gui::Screen *screen) _updateCameras(screen_->control()->getNet()->findAll<string>("list_streams")); } +std::vector<ftl::gui::Camera*> SourceWindow::getCameras() { + auto cameras = std::vector<ftl::gui::Camera*>(cameras_.size()); + for (const auto &kv : cameras_) { + cameras.push_back(kv.second); + } + return cameras; +} + void SourceWindow::_updateCameras(const vector<string> &netcams) { for (auto s : netcams) { if (cameras_.find(s) == cameras_.end()) { diff --git a/applications/gui/src/src_window.hpp b/applications/gui/src/src_window.hpp index b2fe8a9e0..dab3f5d43 100644 --- a/applications/gui/src/src_window.hpp +++ b/applications/gui/src/src_window.hpp @@ -25,7 +25,7 @@ class SourceWindow : public nanogui::Window { explicit SourceWindow(ftl::gui::Screen *screen); ~SourceWindow(); - const std::vector<ftl::gui::Camera*> &getCameras(); + std::vector<ftl::gui::Camera*> getCameras(); virtual void draw(NVGcontext *ctx); diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp index 0603dad40..551a2dfe3 100644 --- a/applications/reconstruct/src/main.cpp +++ b/applications/reconstruct/src/main.cpp @@ -241,6 +241,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 94fcc7dfa..9e4ba8aed 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 89d539cbe..aa236c8a0 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 bdd21c470..d9fd6e528 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; }; diff --git a/components/rgbd-sources/include/ftl/rgbd/source.hpp b/components/rgbd-sources/include/ftl/rgbd/source.hpp index 748478879..895817359 100644 --- a/components/rgbd-sources/include/ftl/rgbd/source.hpp +++ b/components/rgbd-sources/include/ftl/rgbd/source.hpp @@ -31,6 +31,8 @@ class SnapshotReader; class VirtualSource; class Player; +typedef std::function<void(ftl::rgbd::Source*, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt)> RawCallback; + /** * RGBD Generic data source configurable entity. This class hides the * internal implementation of an RGBD source by providing accessor functions @@ -189,12 +191,12 @@ class Source : public ftl::Configurable { * Currently this only works for a net source since other sources don't * produce raw encoded data. */ - void addRawCallback(const std::function<void(ftl::rgbd::Source*, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt)> &); + void addRawCallback(const RawCallback &); /** * THIS DOES NOT WORK CURRENTLY. */ - void removeRawCallback(const std::function<void(ftl::rgbd::Source*, const ftl::codecs::StreamPacket &spkt, const ftl::codecs::Packet &pkt)> &); + void removeRawCallback(const RawCallback &); /** * INTERNAL. Used to send raw data to callbacks. -- GitLab