From 0a1d20d480685eb5f65ca5746a609f766d24d6b5 Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nwpope@utu.fi>
Date: Thu, 16 Jul 2020 10:55:59 +0300
Subject: [PATCH] WIP Record options window

---
 applications/gui2/src/modules/camera.cpp      | 11 +++
 applications/gui2/src/modules/camera.hpp      |  4 +
 applications/gui2/src/views/camera.cpp        | 81 ++++++++++++++++++-
 components/codecs/src/channels.cpp            | 19 ++++-
 .../structures/include/ftl/data/new_frame.hpp |  5 ++
 components/structures/src/new_frame.cpp       | 15 ++++
 6 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp
index c79e70c2f..1d8766c59 100644
--- a/applications/gui2/src/modules/camera.cpp
+++ b/applications/gui2/src/modules/camera.cpp
@@ -81,6 +81,17 @@ std::unordered_set<Channel> Camera::availableChannels() {
 	return {};
 }
 
+std::unordered_set<Channel> Camera::allAvailableChannels() {
+	if (std::atomic_load(&latest_)) {
+		auto set = latest_->frames[frame_idx].available();
+		for (auto i : latest_->frames[frame_idx].allChannels()) {
+			set.emplace(i);
+		}
+		return set;
+	}
+	return {};
+}
+
 void Camera::activate(ftl::data::FrameID id) {
 	frame_idx = id.source();
 	frame_id_ = id;
diff --git a/applications/gui2/src/modules/camera.hpp b/applications/gui2/src/modules/camera.hpp
index 1c58a6758..008555560 100644
--- a/applications/gui2/src/modules/camera.hpp
+++ b/applications/gui2/src/modules/camera.hpp
@@ -32,6 +32,10 @@ public:
 	bool getFrame(ftl::cuda::TextureObject<uchar4>&);
 
 	std::unordered_set<ftl::codecs::Channel> availableChannels();
+
+	/** This includes data channels etc */
+	std::unordered_set<ftl::codecs::Channel> allAvailableChannels();
+	
 	void touch(int id, ftl::codecs::TouchType t, int x, int y, float d, int strength);
 
 	/** Check if new frame is available */
diff --git a/applications/gui2/src/views/camera.cpp b/applications/gui2/src/views/camera.cpp
index 6d7ed3255..f943672ee 100644
--- a/applications/gui2/src/views/camera.cpp
+++ b/applications/gui2/src/views/camera.cpp
@@ -22,6 +22,74 @@ using ftl::gui2::VolumeButton;
 
 using ftl::codecs::Channel;
 
+// ==== Record Options =========================================================
+
+class RecordOptions : public nanogui::Window {
+public:
+	RecordOptions(nanogui::Widget *parent, Camera* ctrl);
+	virtual ~RecordOptions();
+
+private:
+	Camera* ctrl_;
+
+public:
+	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+};
+
+RecordOptions::RecordOptions(nanogui::Widget *parent, Camera* ctrl)
+ : nanogui::Window(parent, "Recording"), ctrl_(ctrl) {
+
+	using namespace nanogui;
+
+	//setFixedWidth(300);
+	setLayout(new GroupLayout(15, 6, 14, 10));
+	setPosition(Vector2i(parent->width()/2.0f - 100.0f, parent->height()/2.0f - 100.0f));
+	setVisible(true);
+
+	auto close = new nanogui::Button(buttonPanel(), "", ENTYPO_ICON_CROSS);
+	close->setTheme(dynamic_cast<ftl::gui2::Screen*>(screen())->getTheme("window_dark"));
+	close->setBackgroundColor(theme()->mWindowHeaderGradientBot);
+	close->setCallback([this](){ dispose();});
+
+	// Add all available channels as checkboxes
+	auto channels = ctrl_->allAvailableChannels();
+	for (auto c : channels) {
+		// Skip channels that can't be encoded
+		if (int(c) < 32) {
+			switch (c) {
+			case Channel::Colour	:
+			case Channel::Colour2	:
+			case Channel::Depth		:
+			case Channel::Depth2	:
+			case Channel::ColourHighRes :
+			case Channel::Colour2HighRes : break;
+			default: continue;
+			}
+		}
+
+		auto check = new CheckBox(this, ftl::codecs::name(c));
+		switch (c) {
+		case Channel::Colour		:
+		case Channel::Pose			:
+		case Channel::Capabilities	:
+		case Channel::Calibration	:
+		case Channel::MetaData		: check->setChecked(true); break;
+		default: break;
+		}
+	}
+
+	auto start = new Button(this, "Start");
+	start->setCallback([this]() {
+
+	});
+
+	screen()->performLayout();
+}
+
+RecordOptions::~RecordOptions() {
+
+}
+
 // === MediaPanel ==============================================================
 
 class MediaPanel : public FixedWindow {
@@ -43,6 +111,7 @@ public:
 private:
 	std::vector<nanogui::Widget*> buttons(); // channel buttons
 	Camera* ctrl_;
+	RecordOptions *record_opts_=nullptr;
 
 public:
 	EIGEN_MAKE_ALIGNED_OPERATOR_NEW
@@ -82,7 +151,7 @@ MediaPanel::MediaPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl) :
 	});
 
 	// Record
-	auto button_record = new ftl::gui2::PopupButton(this, "", ENTYPO_ICON_CONTROLLER_RECORD);
+	/*auto button_record = new ftl::gui2::PopupButton(this, "", ENTYPO_ICON_CONTROLLER_RECORD);
 	button_record->setSide(Popup::Side::Right);
 	button_record->setChevronIcon(0);
 
@@ -108,6 +177,14 @@ MediaPanel::MediaPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl) :
 			button_record->setPushed(false);
 			ctrl_->stopRecording();
 		}
+	});*/
+
+	// Record
+	auto button_record = new Button(this, "", ENTYPO_ICON_CONTROLLER_RECORD);
+	button_record->setCallback([this]() {
+		if (record_opts_) return;
+
+		record_opts_ = new RecordOptions(screen(), ctrl_);
 	});
 
 	// Channel select. Creates buttons for 32 channels and sets available ones
@@ -144,6 +221,8 @@ MediaPanel::MediaPanel(nanogui::Widget *parent, ftl::gui2::Camera* ctrl) :
 }
 
 MediaPanel::~MediaPanel() {
+	// FIXME: nanogui deletes twice
+	//if (record_opts_) record_opts_->dispose();
 }
 
 void MediaPanel::draw(NVGcontext *ctx) {
diff --git a/components/codecs/src/channels.cpp b/components/codecs/src/channels.cpp
index 1e9d8d526..54d1181c0 100644
--- a/components/codecs/src/channels.cpp
+++ b/components/codecs/src/channels.cpp
@@ -79,11 +79,28 @@ static ChannelInfo info[] = {
 	"Configuration", 0,
 	"Calibration", 0,
 	"Pose", 0,
-	"Data", 0
+	"Calibration2", 0,
+	"Index", 0,
+	"Control", 0,
+	"Settings3", 0,
+	"MetaData", 0,
+	"Capabilities", 0,
+	"CalibrationData", 0
+};
+
+static ChannelInfo info_data[] = {
+	"Data", 0,
+	"Faces", 0,
+	"Transforms", 0,
+	"Shapes3D", 0,
+	"Messages", 0,
+	"Touch", 0
 };
 
 std::string ftl::codecs::name(Channel c) {
+	// FIXME: This function is dangerous
 	if (c == Channel::None) return "None";
+	else if (int(c) >= 2048) return info_data[(int)c - 2048].name;
 	else return info[(int)c].name;
 }
 
diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp
index 1533e034a..b110f186e 100644
--- a/components/structures/include/ftl/data/new_frame.hpp
+++ b/components/structures/include/ftl/data/new_frame.hpp
@@ -310,6 +310,11 @@ class Frame {
 	 */
 	std::unordered_set<ftl::codecs::Channel> channels() const;
 
+	/**
+	 * All channels including those in the persistent store.
+	 */
+	std::unordered_set<ftl::codecs::Channel> allChannels() const;
+
 	/**
 	 * Test if the type of the channel matches the template type. Other
 	 * functions throw exceptions if wrong type is used, but this will not. It
diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp
index 64f64846b..28f16369a 100644
--- a/components/structures/src/new_frame.cpp
+++ b/components/structures/src/new_frame.cpp
@@ -414,6 +414,21 @@ std::unordered_set<ftl::codecs::Channel> Frame::channels() const {
 	return res;
 }
 
+std::unordered_set<ftl::codecs::Channel> Frame::allChannels() const {
+	std::unordered_set<ftl::codecs::Channel> res{};
+	for (const auto& [k, v] : data_) {
+		std::ignore = v;
+		res.emplace(k);
+	}
+	if (parent_) {
+		for (const auto& [k, v] : parent_->data_) {
+			std::ignore = v;
+			res.emplace(k);
+		}
+	}
+	return res;
+}
+
 // ==== Session ================================================================
 
 ftl::Handle Session::onChange(uint32_t pid, ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) {
-- 
GitLab