[libcamera-devel,v2,1/2] cam: Add Rectangle type parsing in capture script
diff mbox series

Message ID 20220624130523.41535-2-dse@thaumatec.com
State Accepted
Headers show
Series
  • cam: Add Rectangle type parsing in capture script
Related show

Commit Message

Daniel Semkowicz June 24, 2022, 1:05 p.m. UTC
This change is required for AfWindows control from capture script.
Parser expects array of arrays of parameters, so it is possible to
specify multiple rectangles.

Signed-off-by: Daniel Semkowicz <dse@thaumatec.com>
---
 src/cam/capture_script.cpp | 109 +++++++++++++++++++++++++++++++++----
 src/cam/capture_script.h   |   6 +-
 2 files changed, 102 insertions(+), 13 deletions(-)

Comments

Laurent Pinchart June 24, 2022, 5:47 p.m. UTC | #1
Hi Daniel,

Thank you for the patch.

On Fri, Jun 24, 2022 at 03:05:22PM +0200, Daniel Semkowicz via libcamera-devel wrote:
> This change is required for AfWindows control from capture script.
> Parser expects array of arrays of parameters, so it is possible to
> specify multiple rectangles.
> 
> Signed-off-by: Daniel Semkowicz <dse@thaumatec.com>
> ---
>  src/cam/capture_script.cpp | 109 +++++++++++++++++++++++++++++++++----
>  src/cam/capture_script.h   |   6 +-
>  2 files changed, 102 insertions(+), 13 deletions(-)
> 
> diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp
> index 9f22d5f7..5812b122 100644
> --- a/src/cam/capture_script.cpp
> +++ b/src/cam/capture_script.cpp
> @@ -232,12 +232,15 @@ int CaptureScript::parseControl(EventPtr event, ControlList &controls)
>  		return -EINVAL;
>  	}
>  
> -	std::string value = parseScalar();
> -	if (value.empty())
> +	const ControlId *controlId = it->second;
> +
> +	ControlValue val = unpackControl(controlId);
> +	if (val.isNone()) {
> +		std::cerr << "Error unpacking control '" << name << "'"
> +			  << std::endl;
>  		return -EINVAL;
> +	}
>  
> -	const ControlId *controlId = it->second;
> -	ControlValue val = unpackControl(controlId, value);
>  	controls.set(controlId->id(), val);
>  
>  	return 0;
> @@ -252,6 +255,68 @@ std::string CaptureScript::parseScalar()
>  	return eventScalarValue(event);
>  }
>  
> +ControlValue CaptureScript::parseRectangles()
> +{
> +	EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT);
> +	if (!event)
> +		return {};
> +
> +	std::vector<libcamera::Rectangle> rectangles;

Hmmm... we have an issue here. The code will work fine for AfWindows, as
it's an array of rectangles, but it will fail for controls are expressed
as a single rectangle, unless the YAML file stores them as an array
containing one rectangle.

Do you have an idea on how we could fix that ?

> +
> +	while (1) {
> +		event = nextEvent();
> +		if (!event)
> +			return {};
> +
> +		switch (event->type) {
> +		case YAML_SEQUENCE_START_EVENT: {
> +			std::vector<std::string> values = parseArray();
> +			if (values.size() != 4) {
> +				std::cerr << "Error parsing Rectangle: expected "
> +					     "array with 4 parameters" << std::endl;
> +				return {};
> +			}
> +
> +			Rectangle rect = unpackRectangle(values);
> +			rectangles.push_back(rect);
> +			break;
> +		}
> +		case YAML_SEQUENCE_END_EVENT: {
> +			ControlValue controlValue;
> +			controlValue.set(Span<const Rectangle>(rectangles));
> +			return controlValue;
> +		}
> +		default:
> +			return {};
> +		}
> +	}
> +}
> +
> +std::vector<std::string> CaptureScript::parseArray()
> +{
> +	std::vector<std::string> values;
> +
> +	while (1) {
> +		EventPtr event = nextEvent();
> +		if (!event)
> +			return {};
> +
> +		switch (event->type) {
> +		case YAML_SCALAR_EVENT: {
> +			std::string value = eventScalarValue(event);
> +			if (value.empty())
> +				return {};
> +			values.push_back(value);
> +			break;
> +		}
> +		case YAML_SEQUENCE_END_EVENT:
> +			return values;
> +		default:
> +			return {};
> +		}
> +	}
> +}
> +
>  void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
>  {
>  	static const std::map<unsigned int, const char *> typeNames = {
> @@ -277,9 +342,24 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
>  		  << typeName << " control " << id->name() << std::endl;
>  }
>  
> -ControlValue CaptureScript::unpackControl(const ControlId *id,
> -					  const std::string &repr)
> +ControlValue CaptureScript::unpackControl(const ControlId *id)
>  {
> +	/* Parse complex types */

Nitpicking, s/types/types./

> +	switch (id->type()) {
> +	case ControlTypeRectangle:
> +		return parseRectangles();
> +	case ControlTypeSize:
> +		/* \todo Parse Sizes. */
> +		return {};

Feel free to send another patch to address this too ;-)

> +	default:
> +		break;
> +	}
> +
> +	/* Parse basic types represented by a single scalar */

Same here, s/scalar/scalar./

> +	const std::string repr = parseScalar();
> +	if (repr.empty())
> +		return {};
> +
>  	ControlValue value{};
>  
>  	switch (id->type()) {
> @@ -324,13 +404,20 @@ ControlValue CaptureScript::unpackControl(const ControlId *id,
>  		value.set<std::string>(repr);
>  		break;
>  	}
> -	case ControlTypeRectangle:
> -		/* \todo Parse rectangles. */
> -		break;
> -	case ControlTypeSize:
> -		/* \todo Parse Sizes. */
> +	default:
> +		std::cerr << "Unsupported control type" << std::endl;
>  		break;
>  	}
>  
>  	return value;
>  }
> +
> +libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)
> +{
> +	int x = strtol(strVec[0].c_str(), NULL, 10);
> +	int y = strtol(strVec[1].c_str(), NULL, 10);
> +	unsigned int width = strtoul(strVec[2].c_str(), NULL, 10);
> +	unsigned int height = strtoul(strVec[3].c_str(), NULL, 10);
> +
> +	return Rectangle(x, y, width, height);
> +}
> diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h
> index 8b4f8f62..130872b4 100644
> --- a/src/cam/capture_script.h
> +++ b/src/cam/capture_script.h
> @@ -54,9 +54,11 @@ private:
>  	int parseControl(EventPtr event, libcamera::ControlList &controls);
>  
>  	std::string parseScalar();
> +	libcamera::ControlValue parseRectangles();
> +	std::vector<std::string> parseArray();
>  
>  	void unpackFailure(const libcamera::ControlId *id,
>  			   const std::string &repr);
> -	libcamera::ControlValue unpackControl(const libcamera::ControlId *id,
> -					      const std::string &repr);
> +	libcamera::ControlValue unpackControl(const libcamera::ControlId *id);
> +	libcamera::Rectangle unpackRectangle(const std::vector<std::string> &strVec);
>  };

Patch
diff mbox series

diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp
index 9f22d5f7..5812b122 100644
--- a/src/cam/capture_script.cpp
+++ b/src/cam/capture_script.cpp
@@ -232,12 +232,15 @@  int CaptureScript::parseControl(EventPtr event, ControlList &controls)
 		return -EINVAL;
 	}
 
-	std::string value = parseScalar();
-	if (value.empty())
+	const ControlId *controlId = it->second;
+
+	ControlValue val = unpackControl(controlId);
+	if (val.isNone()) {
+		std::cerr << "Error unpacking control '" << name << "'"
+			  << std::endl;
 		return -EINVAL;
+	}
 
-	const ControlId *controlId = it->second;
-	ControlValue val = unpackControl(controlId, value);
 	controls.set(controlId->id(), val);
 
 	return 0;
@@ -252,6 +255,68 @@  std::string CaptureScript::parseScalar()
 	return eventScalarValue(event);
 }
 
+ControlValue CaptureScript::parseRectangles()
+{
+	EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT);
+	if (!event)
+		return {};
+
+	std::vector<libcamera::Rectangle> rectangles;
+
+	while (1) {
+		event = nextEvent();
+		if (!event)
+			return {};
+
+		switch (event->type) {
+		case YAML_SEQUENCE_START_EVENT: {
+			std::vector<std::string> values = parseArray();
+			if (values.size() != 4) {
+				std::cerr << "Error parsing Rectangle: expected "
+					     "array with 4 parameters" << std::endl;
+				return {};
+			}
+
+			Rectangle rect = unpackRectangle(values);
+			rectangles.push_back(rect);
+			break;
+		}
+		case YAML_SEQUENCE_END_EVENT: {
+			ControlValue controlValue;
+			controlValue.set(Span<const Rectangle>(rectangles));
+			return controlValue;
+		}
+		default:
+			return {};
+		}
+	}
+}
+
+std::vector<std::string> CaptureScript::parseArray()
+{
+	std::vector<std::string> values;
+
+	while (1) {
+		EventPtr event = nextEvent();
+		if (!event)
+			return {};
+
+		switch (event->type) {
+		case YAML_SCALAR_EVENT: {
+			std::string value = eventScalarValue(event);
+			if (value.empty())
+				return {};
+			values.push_back(value);
+			break;
+		}
+		case YAML_SEQUENCE_END_EVENT:
+			return values;
+		default:
+			return {};
+		}
+	}
+}
+
 void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
 {
 	static const std::map<unsigned int, const char *> typeNames = {
@@ -277,9 +342,24 @@  void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
 		  << typeName << " control " << id->name() << std::endl;
 }
 
-ControlValue CaptureScript::unpackControl(const ControlId *id,
-					  const std::string &repr)
+ControlValue CaptureScript::unpackControl(const ControlId *id)
 {
+	/* Parse complex types */
+	switch (id->type()) {
+	case ControlTypeRectangle:
+		return parseRectangles();
+	case ControlTypeSize:
+		/* \todo Parse Sizes. */
+		return {};
+	default:
+		break;
+	}
+
+	/* Parse basic types represented by a single scalar */
+	const std::string repr = parseScalar();
+	if (repr.empty())
+		return {};
+
 	ControlValue value{};
 
 	switch (id->type()) {
@@ -324,13 +404,20 @@  ControlValue CaptureScript::unpackControl(const ControlId *id,
 		value.set<std::string>(repr);
 		break;
 	}
-	case ControlTypeRectangle:
-		/* \todo Parse rectangles. */
-		break;
-	case ControlTypeSize:
-		/* \todo Parse Sizes. */
+	default:
+		std::cerr << "Unsupported control type" << std::endl;
 		break;
 	}
 
 	return value;
 }
+
+libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)
+{
+	int x = strtol(strVec[0].c_str(), NULL, 10);
+	int y = strtol(strVec[1].c_str(), NULL, 10);
+	unsigned int width = strtoul(strVec[2].c_str(), NULL, 10);
+	unsigned int height = strtoul(strVec[3].c_str(), NULL, 10);
+
+	return Rectangle(x, y, width, height);
+}
diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h
index 8b4f8f62..130872b4 100644
--- a/src/cam/capture_script.h
+++ b/src/cam/capture_script.h
@@ -54,9 +54,11 @@  private:
 	int parseControl(EventPtr event, libcamera::ControlList &controls);
 
 	std::string parseScalar();
+	libcamera::ControlValue parseRectangles();
+	std::vector<std::string> parseArray();
 
 	void unpackFailure(const libcamera::ControlId *id,
 			   const std::string &repr);
-	libcamera::ControlValue unpackControl(const libcamera::ControlId *id,
-					      const std::string &repr);
+	libcamera::ControlValue unpackControl(const libcamera::ControlId *id);
+	libcamera::Rectangle unpackRectangle(const std::vector<std::string> &strVec);
 };