[libcamera-devel] [PATCH 1/3] libcamera: controls: Add std::string and double ControlValue type.

Naushir Patuck naush at raspberrypi.com
Mon Feb 17 15:26:07 CET 2020


Strings are a convenient control type for controls such as
AWB mode ("indoor", "outdoor", "halogen", etc.) or AGC mode ("sports",
"long exposure", "spot", etc.).

Double control values are useful for control values such as EV and even
gains.

This commit adds support for std::string and double control types.
Functionality such as ControlRange on std::string types do not really
make sense, so do nothing with that for now. Also add appropriate test
for the new ControlValue types.

Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
---
 include/libcamera/controls.h    |  6 +++
 src/libcamera/controls.cpp      | 72 ++++++++++++++++++++++++++++++++-
 test/controls/control_value.cpp | 26 ++++++++++++
 3 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h
index 458b84e..ac74122 100644
--- a/include/libcamera/controls.h
+++ b/include/libcamera/controls.h
@@ -20,6 +20,8 @@ enum ControlType {
 	ControlTypeBool,
 	ControlTypeInteger32,
 	ControlTypeInteger64,
+	ControlTypeString,
+	ControlTypeDouble,
 };
 
 class ControlValue
@@ -29,6 +31,8 @@ public:
 	ControlValue(bool value);
 	ControlValue(int32_t value);
 	ControlValue(int64_t value);
+	ControlValue(std::string value);
+	ControlValue(double value);
 
 	ControlType type() const { return type_; }
 	bool isNone() const { return type_ == ControlTypeNone; }
@@ -53,7 +57,9 @@ private:
 		bool bool_;
 		int32_t integer32_;
 		int64_t integer64_;
+		double double_;
 	};
+	std::string string_;
 };
 
 class ControlId
diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp
index 0031cd0..6eb79c9 100644
--- a/src/libcamera/controls.cpp
+++ b/src/libcamera/controls.cpp
@@ -58,6 +58,10 @@ LOG_DEFINE_CATEGORY(Controls)
  * The control stores a 32-bit integer value
  * \var ControlTypeInteger64
  * The control stores a 64-bit integer value
+ * \var ControlTypeString
+ * The control stores a std::string value
+ * \var ControlTypeDouble
+ * The control stores a double value
  */
 
 /**
@@ -100,6 +104,24 @@ ControlValue::ControlValue(int64_t value)
 {
 }
 
+/**
+ * \brief Construct a std::string ControlValue
+ * \param[in] value String value to store
+ */
+ControlValue::ControlValue(std::string value)
+	: type_(ControlTypeString), string_(value)
+{
+}
+
+/**
+ * \brief Construct a double ControlValue
+ * \param[in] value Double value to store
+ */
+ControlValue::ControlValue(double value)
+	: type_(ControlTypeDouble), double_(value)
+{
+}
+
 /**
  * \fn ControlValue::type()
  * \brief Retrieve the data type of the value
@@ -153,6 +175,18 @@ const int64_t &ControlValue::get<int64_t>() const
 	return integer64_;
 }
 
+template<>
+const std::string &ControlValue::get<std::string>() const
+{
+	return string_;
+}
+
+template<>
+const double &ControlValue::get<double>() const
+{
+	return double_;
+}
+
 template<>
 void ControlValue::set<bool>(const bool &value)
 {
@@ -173,6 +207,21 @@ void ControlValue::set<int64_t>(const int64_t &value)
 	type_ = ControlTypeInteger64;
 	integer64_ = value;
 }
+
+template<>
+void ControlValue::set<std::string>(const std::string &value)
+{
+	type_ = ControlTypeString;
+	string_ = value;
+}
+
+template<>
+void ControlValue::set<double>(const double &value)
+{
+	type_ = ControlTypeDouble;
+	double_ = value;
+}
+
 #endif /* __DOXYGEN__ */
 
 /**
@@ -190,6 +239,10 @@ std::string ControlValue::toString() const
 		return std::to_string(integer32_);
 	case ControlTypeInteger64:
 		return std::to_string(integer64_);
+	case ControlTypeString:
+		return string_;
+	case ControlTypeDouble:
+		return std::to_string(double_);
 	}
 
 	return "<ValueType Error>";
@@ -211,6 +264,10 @@ bool ControlValue::operator==(const ControlValue &other) const
 		return integer32_ == other.integer32_;
 	case ControlTypeInteger64:
 		return integer64_ == other.integer64_;
+	case ControlTypeString:
+		return string_ == other.string_;
+	case ControlTypeDouble:
+		return double_ == other.double_;
 	default:
 		return false;
 	}
@@ -341,6 +398,18 @@ Control<int64_t>::Control(unsigned int id, const char *name)
 	: ControlId(id, name, ControlTypeInteger64)
 {
 }
+
+template<>
+Control<std::string>::Control(unsigned int id, const char *name)
+	: ControlId(id, name, ControlTypeString)
+{
+}
+
+template<>
+Control<double>::Control(unsigned int id, const char *name)
+	: ControlId(id, name, ControlTypeDouble)
+{
+}
 #endif /* __DOXYGEN__ */
 
 /**
@@ -583,7 +652,8 @@ void ControlInfoMap::generateIdmap()
 	idmap_.clear();
 
 	for (const auto &ctrl : *this) {
-		if (ctrl.first->type() != ctrl.second.min().type()) {
+		if (ctrl.first->type() != ControlTypeString &&
+			(ctrl.first->type() != ctrl.second.min().type())) {
 			LOG(Controls, Error)
 				<< "Control " << utils::hex(ctrl.first->id())
 				<< " type and range type mismatch";
diff --git a/test/controls/control_value.cpp b/test/controls/control_value.cpp
index a1ffa84..55174da 100644
--- a/test/controls/control_value.cpp
+++ b/test/controls/control_value.cpp
@@ -21,10 +21,14 @@ protected:
 	{
 		ControlValue integer(1234);
 		ControlValue boolean(true);
+		ControlValue fractional(3.142);
+		ControlValue string(std::string("MyString"));
 
 		/* Just a string conversion output test... no validation */
 		cout << "Int: " << integer.toString()
 		     << " Bool: " << boolean.toString()
+		     << " Frac: " << fractional.toString()
+		     << " String: " << string.toString()
 		     << endl;
 
 		if (integer.get<int32_t>() != 1234) {
@@ -37,6 +41,16 @@ protected:
 			return TestFail;
 		}
 
+		if (fractional.get<double>() != 3.142) {
+			cerr << "Failed to get Fractional" << endl;
+			return TestFail;
+		}
+
+		if (string.get<std::string>() != std::string("MyString")) {
+			cerr << "Failed to get String" << endl;
+			return TestFail;
+		}
+
 		/* Test an uninitialised value, and updating it. */
 
 		ControlValue value;
@@ -62,6 +76,18 @@ protected:
 			return TestFail;
 		}
 
+		value.set<double>(2.718);
+		if (value.get<double>() != 2.718) {
+			cerr << "Failed to get Fractional" << endl;
+			return TestFail;
+		}
+
+		value.set<std::string>(std::string("Test"));
+		if (value.get<std::string>() != std::string("Test")) {
+			cerr << "Failed to get String" << endl;
+			return TestFail;
+		}
+
 		return TestPass;
 	}
 };
-- 
2.17.1



More information about the libcamera-devel mailing list