cam: Add Rectangle type parsing in capture script

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>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Daniel Semkowicz 2022-06-27 14:28:05 +02:00 committed by Jacopo Mondi
parent 251f0534b7
commit f71c76ceff
2 changed files with 140 additions and 14 deletions

View file

@ -232,12 +232,15 @@ int CaptureScript::parseControl(EventPtr event, ControlList &controls)
return -EINVAL; return -EINVAL;
} }
std::string value = parseScalar();
if (value.empty())
return -EINVAL;
const ControlId *controlId = it->second; const ControlId *controlId = it->second;
ControlValue val = unpackControl(controlId, value);
ControlValue val = unpackControl(controlId);
if (val.isNone()) {
std::cerr << "Error unpacking control '" << name << "'"
<< std::endl;
return -EINVAL;
}
controls.set(controlId->id(), val); controls.set(controlId->id(), val);
return 0; return 0;
@ -252,6 +255,104 @@ std::string CaptureScript::parseScalar()
return eventScalarValue(event); return eventScalarValue(event);
} }
ControlValue CaptureScript::parseRectangles()
{
std::vector<libcamera::Rectangle> rectangles;
std::vector<std::vector<std::string>> arrays = parseArrays();
if (arrays.empty())
return {};
for (const std::vector<std::string> &values : arrays) {
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);
}
ControlValue controlValue;
controlValue.set(Span<const Rectangle>(rectangles));
return controlValue;
}
std::vector<std::vector<std::string>> CaptureScript::parseArrays()
{
EventPtr event = nextEvent(YAML_SEQUENCE_START_EVENT);
if (!event)
return {};
event = nextEvent();
if (!event)
return {};
std::vector<std::vector<std::string>> valueArrays;
/* Parse single array. */
if (event->type == YAML_SCALAR_EVENT) {
std::string firstValue = eventScalarValue(event);
if (firstValue.empty())
return {};
std::vector<std::string> remaining = parseSingleArray();
std::vector<std::string> values = { firstValue };
values.insert(std::end(values),
std::begin(remaining), std::end(remaining));
valueArrays.push_back(values);
return valueArrays;
}
/* Parse array of arrays. */
while (1) {
switch (event->type) {
case YAML_SEQUENCE_START_EVENT: {
std::vector<std::string> values = parseSingleArray();
valueArrays.push_back(values);
break;
}
case YAML_SEQUENCE_END_EVENT:
return valueArrays;
default:
return {};
}
event = nextEvent();
if (!event)
return {};
}
}
std::vector<std::string> CaptureScript::parseSingleArray()
{
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) void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
{ {
static const std::map<unsigned int, const char *> typeNames = { static const std::map<unsigned int, const char *> typeNames = {
@ -277,9 +378,24 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)
<< typeName << " control " << id->name() << std::endl; << typeName << " control " << id->name() << std::endl;
} }
ControlValue CaptureScript::unpackControl(const ControlId *id, ControlValue CaptureScript::unpackControl(const ControlId *id)
const std::string &repr)
{ {
/* 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{}; ControlValue value{};
switch (id->type()) { switch (id->type()) {
@ -324,13 +440,20 @@ ControlValue CaptureScript::unpackControl(const ControlId *id,
value.set<std::string>(repr); value.set<std::string>(repr);
break; break;
} }
case ControlTypeRectangle: default:
/* \todo Parse rectangles. */ std::cerr << "Unsupported control type" << std::endl;
break;
case ControlTypeSize:
/* \todo Parse Sizes. */
break; break;
} }
return value; 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);
}

View file

@ -54,9 +54,12 @@ private:
int parseControl(EventPtr event, libcamera::ControlList &controls); int parseControl(EventPtr event, libcamera::ControlList &controls);
std::string parseScalar(); std::string parseScalar();
libcamera::ControlValue parseRectangles();
std::vector<std::vector<std::string>> parseArrays();
std::vector<std::string> parseSingleArray();
void unpackFailure(const libcamera::ControlId *id, void unpackFailure(const libcamera::ControlId *id,
const std::string &repr); const std::string &repr);
libcamera::ControlValue unpackControl(const libcamera::ControlId *id, libcamera::ControlValue unpackControl(const libcamera::ControlId *id);
const std::string &repr); libcamera::Rectangle unpackRectangle(const std::vector<std::string> &strVec);
}; };