From f2f79c066dcf8ff3b14a78df4f6c52f0cc211850 Mon Sep 17 00:00:00 2001
From: Nicolas Pope <nwpope@utu.fi>
Date: Thu, 23 Jul 2020 20:12:28 +0300
Subject: [PATCH] Add data wrapper functions to frames

---
 applications/gui2/src/modules/camera.cpp      | 15 ++---
 applications/gui2/src/views/thumbnails.cpp    |  9 +--
 components/renderers/cpp/src/overlay.cpp      |  8 +--
 .../rgbd-sources/include/ftl/rgbd/frame.hpp   | 28 ++++++++--
 components/rgbd-sources/src/frame.cpp         | 55 +++++++++++++++++++
 .../structures/include/ftl/data/new_frame.hpp |  3 +
 components/structures/src/new_frame.cpp       |  4 ++
 7 files changed, 95 insertions(+), 27 deletions(-)

diff --git a/applications/gui2/src/modules/camera.cpp b/applications/gui2/src/modules/camera.cpp
index 8a95cd11a..5eeb063fb 100644
--- a/applications/gui2/src/modules/camera.cpp
+++ b/applications/gui2/src/modules/camera.cpp
@@ -39,7 +39,7 @@ void Camera::update(double delta) {
 		if (ptr) {
 			const auto &frame = ptr->frames[frame_idx];
 			if (frame.has(Channel::MetaData)) {
-				const auto &meta = frame.get<std::map<std::string,std::string>>(Channel::MetaData);
+				const auto &meta = frame.metadata();
 				if (meta.size() > 0) {
 					auto &jmeta = mod->getJSON(StatisticsPanel::MEDIA_META);
 
@@ -59,8 +59,9 @@ void Camera::update(double delta) {
 				}
 			}
 
+			const auto &rgbdf = frame.cast<ftl::rgbd::Frame>();
+
 			if (frame.has(Channel::Calibration)) {
-				const auto &rgbdf = frame.cast<ftl::rgbd::Frame>();
 				const auto &cam = rgbdf.getLeft();
 				auto &jcam = mod->getJSON(StatisticsPanel::CAMERA_DETAILS);
 				jcam["Resolution"] = std::to_string(cam.width) + std::string("x") + std::to_string(cam.height);
@@ -69,7 +70,7 @@ void Camera::update(double delta) {
 			}
 
 			if (frame.has(Channel::Capabilities)) {
-				const auto &caps = frame.get<std::unordered_set<ftl::rgbd::Capability>>(Channel::Capabilities);
+				const auto &caps = rgbdf.capabilities();
 				auto &jmeta = mod->getJSON(StatisticsPanel::MEDIA_META);
 
 				if (caps.count(Capability::TOUCH)) jmeta["Touch"] = nlohmann::json{{"icon", ENTYPO_ICON_MOUSE_POINTER},{"value", true}};
@@ -133,8 +134,8 @@ void Camera::_updateCapabilities(ftl::data::Frame &frame) {
 
 void Camera::initiate_(ftl::data::Frame &frame) {
 	if (frame.has(Channel::Capabilities)) {
-		const auto &cap = frame.get<std::unordered_set<Capability>>(Channel::Capabilities);
-		LOG(INFO) << "Camera Capabilities:";
+		const auto &rgbdf = frame.cast<ftl::rgbd::Frame>();
+		const auto &cap = rgbdf.capabilities();
 		for (auto c : cap) {
 			LOG(INFO) << " -- " << ftl::rgbd::capabilityName(c);
 
@@ -157,7 +158,7 @@ void Camera::initiate_(ftl::data::Frame &frame) {
 	}
 
 	if (frame.has(Channel::MetaData)) {
-		const auto &meta = frame.get<std::map<std::string,std::string>>(Channel::MetaData);
+		const auto &meta = frame.metadata();
 		LOG(INFO) << "Camera Frame Meta Data:";
 		for (auto m : meta) {
 			LOG(INFO) << " -- " << m.first << " = " << m.second;
@@ -307,7 +308,7 @@ std::string Camera::getActiveSourceURI() {
 	if (ptr) {
 		auto &frame = ptr->frames[frame_idx];
 		if (frame.has(ftl::codecs::Channel::MetaData)) {
-			const auto &meta = frame.get<std::map<std::string,std::string>>(ftl::codecs::Channel::MetaData);
+			const auto &meta = frame.metadata();
 			auto i = meta.find("id");
 			if (i != meta.end()) {
 				return i->second;
diff --git a/applications/gui2/src/views/thumbnails.cpp b/applications/gui2/src/views/thumbnails.cpp
index 79c4857d7..a12e7cfd7 100644
--- a/applications/gui2/src/views/thumbnails.cpp
+++ b/applications/gui2/src/views/thumbnails.cpp
@@ -181,14 +181,7 @@ void Thumbnails::updateThumbnails() {
 
 			perform_layout = true;
 
-			std::string name = "No Name";
-			if (frame.has(Channel::MetaData)) {
-				const auto &meta = frame.get<std::map<std::string,std::string>>(Channel::MetaData);
-				const auto i = meta.find("name");
-				if (i != meta.end()) {
-					name = i->second;
-				}
-			}
+			std::string name = frame.name();
 
 			auto* thumbnail = new ThumbView(thumbs.panel, ctrl_, FrameID(fsid, source), name);
 			thumbnail->setFixedSize(thumbsize_);
diff --git a/components/renderers/cpp/src/overlay.cpp b/components/renderers/cpp/src/overlay.cpp
index 609687ffa..64dfaa2fa 100644
--- a/components/renderers/cpp/src/overlay.cpp
+++ b/components/renderers/cpp/src/overlay.cpp
@@ -301,12 +301,8 @@ void Overlay::draw(NVGcontext *ctx, ftl::data::FrameSet &fs, ftl::rgbd::Frame &f
 
 			auto pose = f.getPose(); //.inverse() * state.getPose();
 
-			std::string name = "No Name";
-			if (fs.frames[i].has(Channel::MetaData)) {
-				const auto &meta = fs.frames[i].get<std::map<std::string,std::string>>(Channel::MetaData);
-				name = (meta.count("name")) ? meta.find("name")->second : "NoName";
-			}
-
+			std::string name = fs.frames[0].name();
+	
 			auto tpose = frame.getPose().inverse() * pose;
 			_drawOutlinedShape(Shape::CAMERA, tpose, Eigen::Vector3f(0.2f,0.2f,0.2f), make_uchar4(255,0,0,80), make_uchar4(255,0,0,255));
 			_drawAxis(tpose, Eigen::Vector3f(0.2f, 0.2f, 0.2f));
diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
index 32e2c2ede..74e06aaac 100644
--- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
@@ -17,6 +17,7 @@
 #include <ftl/codecs/packet.hpp>
 #include <ftl/utility/vectorbuffer.hpp>
 #include <ftl/cuda_common.hpp>
+#include <ftl/rgbd/capabilities.hpp>
 
 #include <type_traits>
 #include <array>
@@ -81,14 +82,29 @@ class VideoFrame {
 
 class Frame : public ftl::data::Frame {
 	public:
-	inline const ftl::rgbd::Camera &getLeftCamera() const { return std::get<0>(this->get<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration)); }
-	inline const ftl::rgbd::Camera &getRightCamera() const { return std::get<0>(this->get<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration2)); }
+	const ftl::rgbd::Camera &getLeftCamera() const;
+	const ftl::rgbd::Camera &getRightCamera() const;
 	inline const ftl::rgbd::Camera &getLeft() const { return getLeftCamera(); }
 	inline const ftl::rgbd::Camera &getRight() const { return getRightCamera(); }
-	inline const Eigen::Matrix4d &getPose() const { return this->get<Eigen::Matrix4d>(ftl::codecs::Channel::Pose); }
-	inline ftl::rgbd::Camera &setLeft() { return std::get<0>(this->create<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration)); }
-	inline ftl::rgbd::Camera &setRight() { return std::get<0>(this->create<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration2)); }
-	inline Eigen::Matrix4d &setPose() { return this->create<Eigen::Matrix4d>(ftl::codecs::Channel::Pose); }
+	const Eigen::Matrix4d &getPose() const;
+	ftl::rgbd::Camera &setLeft();
+	ftl::rgbd::Camera &setRight();
+	Eigen::Matrix4d &setPose();
+
+	std::string serial() const;
+	std::string device() const;
+
+	/** Note, this throws exception if channel is missing */
+	const std::unordered_set<ftl::rgbd::Capability> &capabilities() const;
+
+	/** Does not throw exception */
+	bool hasCapability(ftl::rgbd::Capability) const;
+
+	inline bool isLive() const { return hasCapability(ftl::rgbd::Capability::LIVE); }
+	inline bool isVirtual() const { return hasCapability(ftl::rgbd::Capability::VIRTUAL); }
+	inline bool isMovable() const { return hasCapability(ftl::rgbd::Capability::MOVABLE); }
+	inline bool isTouchable() const { return hasCapability(ftl::rgbd::Capability::TOUCH); }
+	inline bool isVR() const { return hasCapability(ftl::rgbd::Capability::VR); }
 
 	void upload(ftl::codecs::Channel c);
 
diff --git a/components/rgbd-sources/src/frame.cpp b/components/rgbd-sources/src/frame.cpp
index 0621902f0..10bacd8f0 100644
--- a/components/rgbd-sources/src/frame.cpp
+++ b/components/rgbd-sources/src/frame.cpp
@@ -114,6 +114,61 @@ unsigned int ftl::rgbd::Frame::getOpenGL(ftl::codecs::Channel c) const {
 }
 
 
+const ftl::rgbd::Camera &ftl::rgbd::Frame::getLeftCamera() const {
+	return std::get<0>(this->get<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration));
+}
+
+const ftl::rgbd::Camera &ftl::rgbd::Frame::getRightCamera() const {
+	return std::get<0>(this->get<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration2));
+}
+
+const Eigen::Matrix4d &ftl::rgbd::Frame::getPose() const {
+	return this->get<Eigen::Matrix4d>(ftl::codecs::Channel::Pose);
+}
+
+ftl::rgbd::Camera &ftl::rgbd::Frame::setLeft() {
+	return std::get<0>(this->create<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration));
+}
+
+ftl::rgbd::Camera &ftl::rgbd::Frame::setRight() {
+	return std::get<0>(this->create<std::tuple<ftl::rgbd::Camera, ftl::codecs::Channel, int>>(ftl::codecs::Channel::Calibration2));
+}
+
+Eigen::Matrix4d &ftl::rgbd::Frame::setPose() {
+	return this->create<Eigen::Matrix4d>(ftl::codecs::Channel::Pose);
+}
+
+std::string ftl::rgbd::Frame::serial() const {
+	if (hasChannel(Channel::MetaData)) {
+		const auto &meta = get<std::map<std::string,std::string>>(Channel::MetaData);
+		auto i = meta.find("serial");
+		if (i != meta.end()) return i->second;
+	}
+	return "";
+}
+
+std::string ftl::rgbd::Frame::device() const {
+	if (hasChannel(Channel::MetaData)) {
+		const auto &meta = get<std::map<std::string,std::string>>(Channel::MetaData);
+		auto i = meta.find("device");
+		if (i != meta.end()) return i->second;
+	}
+	return "";
+}
+
+const std::unordered_set<ftl::rgbd::Capability> &ftl::rgbd::Frame::capabilities() const {
+	return get<std::unordered_set<ftl::rgbd::Capability>>(Channel::Capabilities);
+}
+
+bool ftl::rgbd::Frame::hasCapability(ftl::rgbd::Capability c) const {
+	if (hasChannel(Channel::Capabilities)) {
+		const auto &cap = get<std::unordered_set<ftl::rgbd::Capability>>(Channel::Capabilities);
+		return cap.count(c) > 0;
+	}
+	return false;
+}
+
+
 template <>
 cv::Mat &ftl::data::Frame::create<cv::Mat, 0>(ftl::codecs::Channel c) {
 	return create<ftl::rgbd::VideoFrame>(c).createCPU();
diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp
index 557984e87..ec192495b 100644
--- a/components/structures/include/ftl/data/new_frame.hpp
+++ b/components/structures/include/ftl/data/new_frame.hpp
@@ -647,6 +647,9 @@ class Frame {
 	 */
 	std::string name() const;
 
+	/** Can throw an exception if missing, use `hasChannel(Channel::MetaData)` first. */
+	const std::map<std::string,std::string> &metadata() const;
+
 	// =========================================================================
 
 	protected:
diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp
index ba95ba267..487b6468c 100644
--- a/components/structures/src/new_frame.cpp
+++ b/components/structures/src/new_frame.cpp
@@ -481,6 +481,10 @@ std::string Frame::name() const {
 	return std::string("Frame-") + std::to_string(frameset()) + std::string("-") + std::to_string(source());
 }
 
+const std::map<std::string,std::string> &Frame::metadata() const {
+	return get<std::map<std::string,std::string>>(Channel::MetaData);
+}
+
 // ==== Session ================================================================
 
 ftl::Handle Session::onChange(uint32_t pid, ftl::codecs::Channel c, const std::function<bool(Frame&,ftl::codecs::Channel)> &cb) {
-- 
GitLab