Message ID | 20220627122806.29586-2-dse@thaumatec.com |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Daniel On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > src/cam/capture_script.h | 7 +- > 2 files changed, 139 insertions(+), 13 deletions(-) > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > 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(); nit: remaining can potentilly be {} > + > + std::vector<std::string> values = { firstValue }; > + values.insert(std::end(values), > + std::begin(remaining), std::end(remaining)); > + valueArrays.push_back(values); > + > + return valueArrays; > + } This should address Laurent's comment and I assume it now works with both AfWindows: - [x, y, w, h] and AfWindows: - [[x, y, w, h], [x1, y1, w1, h1] .. ] > + > + /* 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) > { > 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; > } > > -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 {}; > + Thanks, this address my comment on v1. Nits apart it looks good to me Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Thanks j > ControlValue value{}; > > switch (id->type()) { > @@ -324,13 +440,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..fffe67e5 100644 > --- a/src/cam/capture_script.h > +++ b/src/cam/capture_script.h > @@ -54,9 +54,12 @@ private: > int parseControl(EventPtr event, libcamera::ControlList &controls); > > std::string parseScalar(); > + libcamera::ControlValue parseRectangles(); > + std::vector<std::vector<std::string>> parseArrays(); > + std::vector<std::string> parseSingleArray(); > > 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); > }; > -- > 2.34.1 >
Hi Jacopo, On Mon, Jun 27, 2022 at 6:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > Hi Daniel > > On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > > src/cam/capture_script.h | 7 +- > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > 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(); > > nit: remaining can potentilly be {} Yes, but the vector can be empty not only because of error, but also because there was a valid array but with only one element (already read in firstValue). We would need to add additional parameter returned from method to distinguish between these two situations. The higher level that calls parseArrays() should already know the expected number of elements in the single array, so the error will be caught anyway. I wouldn't spend too much time tweaking this solution as it is not critical. What do you think about leaving it as it is? > > > + > > + std::vector<std::string> values = { firstValue }; > > + values.insert(std::end(values), > > + std::begin(remaining), std::end(remaining)); > > + valueArrays.push_back(values); > > + > > + return valueArrays; > > + } > > This should address Laurent's comment and I assume it now works with > both > AfWindows: > - [x, y, w, h] > > and > AfWindows: > - [[x, y, w, h], [x1, y1, w1, h1] .. ] > Exactly, I tested it with both versions :) Best regards Daniel > > + > > + /* 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) > > { > > 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; > > } > > > > -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 {}; > > + > > Thanks, this address my comment on v1. > > Nits apart it looks good to me > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > > Thanks > j > > > ControlValue value{}; > > > > switch (id->type()) { > > @@ -324,13 +440,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..fffe67e5 100644 > > --- a/src/cam/capture_script.h > > +++ b/src/cam/capture_script.h > > @@ -54,9 +54,12 @@ private: > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > std::string parseScalar(); > > + libcamera::ControlValue parseRectangles(); > > + std::vector<std::vector<std::string>> parseArrays(); > > + std::vector<std::string> parseSingleArray(); > > > > 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); > > }; > > -- > > 2.34.1 > >
Hi Daniel, Thanks for the patches. On Tue, Jun 28, 2022 at 08:35:03AM +0200, Daniel Semkowicz via libcamera-devel wrote: > Hi Jacopo, > > On Mon, Jun 27, 2022 at 6:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > > > Hi Daniel > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > > > src/cam/capture_script.h | 7 +- > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > 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(); > > > > nit: remaining can potentilly be {} > > Yes, but the vector can be empty not only because of error, but also > because there was a valid array but with only one element (already read > in firstValue). > We would need to add additional parameter returned from method to > distinguish between these two situations. > The higher level that calls parseArrays() should already know the > expected number of elements in the single array, so the error will be > caught anyway. I wouldn't spend too much time tweaking this solution as > it is not critical. > What do you think about leaving it as it is? > > > > > > + > > > + std::vector<std::string> values = { firstValue }; > > > + values.insert(std::end(values), > > > + std::begin(remaining), std::end(remaining)); > > > + valueArrays.push_back(values); > > > + > > > + return valueArrays; > > > + } > > > > This should address Laurent's comment and I assume it now works with > > both > > AfWindows: > > - [x, y, w, h] Gotta be honest, I'm not a big fan of representing Rectangles this way; it's a bit... flat (if that's the right word). I'd prefer it to be like (x,y)/wxh Thanks, Paul > > > > and > > AfWindows: > > - [[x, y, w, h], [x1, y1, w1, h1] .. ] > > > > Exactly, I tested it with both versions :) > > Best regards > Daniel > > > > + > > > + /* 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) > > > { > > > 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; > > > } > > > > > > -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 {}; > > > + > > > > Thanks, this address my comment on v1. > > > > Nits apart it looks good to me > > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > > > > Thanks > > j > > > > > ControlValue value{}; > > > > > > switch (id->type()) { > > > @@ -324,13 +440,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..fffe67e5 100644 > > > --- a/src/cam/capture_script.h > > > +++ b/src/cam/capture_script.h > > > @@ -54,9 +54,12 @@ private: > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > std::string parseScalar(); > > > + libcamera::ControlValue parseRectangles(); > > > + std::vector<std::vector<std::string>> parseArrays(); > > > + std::vector<std::string> parseSingleArray(); > > > > > > 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); > > > }; > > > -- > > > 2.34.1 > > >
Hi Paul On Fri, Aug 05, 2022 at 04:47:46AM +0900, paul.elder@ideasonboard.com wrote: > Hi Daniel, > > Thanks for the patches. > > On Tue, Jun 28, 2022 at 08:35:03AM +0200, Daniel Semkowicz via libcamera-devel wrote: > > Hi Jacopo, > > > > On Mon, Jun 27, 2022 at 6:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > > > > > Hi Daniel > > > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > > > > src/cam/capture_script.h | 7 +- > > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > > 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(); > > > > > > nit: remaining can potentilly be {} > > > > Yes, but the vector can be empty not only because of error, but also > > because there was a valid array but with only one element (already read > > in firstValue). > > We would need to add additional parameter returned from method to > > distinguish between these two situations. > > The higher level that calls parseArrays() should already know the > > expected number of elements in the single array, so the error will be > > caught anyway. I wouldn't spend too much time tweaking this solution as > > it is not critical. > > What do you think about leaving it as it is? > > > > > > > > > + > > > > + std::vector<std::string> values = { firstValue }; > > > > + values.insert(std::end(values), > > > > + std::begin(remaining), std::end(remaining)); > > > > + valueArrays.push_back(values); > > > > + > > > > + return valueArrays; > > > > + } > > > > > > This should address Laurent's comment and I assume it now works with > > > both > > > AfWindows: > > > - [x, y, w, h] > > Gotta be honest, I'm not a big fan of representing Rectangles this way; > it's a bit... flat (if that's the right word). > I'd prefer it to be like (x,y)/wxh This would require specifying the rectangle as a string. How will it look like in the .yaml file ? Do you have examples you have tested your version to share ? > > > Thanks, > > Paul > > > > > > > and > > > AfWindows: > > > - [[x, y, w, h], [x1, y1, w1, h1] .. ] > > > > > > > Exactly, I tested it with both versions :) > > > > Best regards > > Daniel > > > > > > + > > > > + /* 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) > > > > { > > > > 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; > > > > } > > > > > > > > -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 {}; > > > > + > > > > > > Thanks, this address my comment on v1. > > > > > > Nits apart it looks good to me > > > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > > > > > > Thanks > > > j > > > > > > > ControlValue value{}; > > > > > > > > switch (id->type()) { > > > > @@ -324,13 +440,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..fffe67e5 100644 > > > > --- a/src/cam/capture_script.h > > > > +++ b/src/cam/capture_script.h > > > > @@ -54,9 +54,12 @@ private: > > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > > > std::string parseScalar(); > > > > + libcamera::ControlValue parseRectangles(); > > > > + std::vector<std::vector<std::string>> parseArrays(); > > > > + std::vector<std::string> parseSingleArray(); > > > > > > > > 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); > > > > }; > > > > -- > > > > 2.34.1 > > > >
Hi Jacopo, On Fri, Aug 05, 2022 at 09:20:26AM +0200, Jacopo Mondi wrote: > Hi Paul > > On Fri, Aug 05, 2022 at 04:47:46AM +0900, paul.elder@ideasonboard.com wrote: > > Hi Daniel, > > > > Thanks for the patches. > > > > On Tue, Jun 28, 2022 at 08:35:03AM +0200, Daniel Semkowicz via libcamera-devel wrote: > > > Hi Jacopo, > > > > > > On Mon, Jun 27, 2022 at 6:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > > > > > > > Hi Daniel > > > > > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > > > > > src/cam/capture_script.h | 7 +- > > > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > > > 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(); > > > > > > > > nit: remaining can potentilly be {} > > > > > > Yes, but the vector can be empty not only because of error, but also > > > because there was a valid array but with only one element (already read > > > in firstValue). > > > We would need to add additional parameter returned from method to > > > distinguish between these two situations. > > > The higher level that calls parseArrays() should already know the > > > expected number of elements in the single array, so the error will be > > > caught anyway. I wouldn't spend too much time tweaking this solution as > > > it is not critical. > > > What do you think about leaving it as it is? > > > > > > > > > > > > + > > > > > + std::vector<std::string> values = { firstValue }; > > > > > + values.insert(std::end(values), > > > > > + std::begin(remaining), std::end(remaining)); > > > > > + valueArrays.push_back(values); > > > > > + > > > > > + return valueArrays; > > > > > + } > > > > > > > > This should address Laurent's comment and I assume it now works with > > > > both > > > > AfWindows: > > > > - [x, y, w, h] > > > > Gotta be honest, I'm not a big fan of representing Rectangles this way; > > it's a bit... flat (if that's the right word). > > I'd prefer it to be like (x,y)/wxh > > This would require specifying the rectangle as a string. How will it > look like in the .yaml file ? Do you have examples you have tested > your version to share ? Oh right I forgot we've got a yaml spec to conform to :S I just have it in there as-is: frames: - 1: ScalerCrop: (0,0)/1920x1080 I suppose yaml doesn't have a "rectangle" type. So if it's turning that into a string vs into an array... yeah I guess an array of four ints is better. Alright, nvm my objection then :) Paul > > > > > > > > > > > > > and > > > > AfWindows: > > > > - [[x, y, w, h], [x1, y1, w1, h1] .. ] > > > > > > > > > > Exactly, I tested it with both versions :) > > > > > > Best regards > > > Daniel > > > > > > > > + > > > > > + /* 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) > > > > > { > > > > > 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; > > > > > } > > > > > > > > > > -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 {}; > > > > > + > > > > > > > > Thanks, this address my comment on v1. > > > > > > > > Nits apart it looks good to me > > > > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > > > > > > > > Thanks > > > > j > > > > > > > > > ControlValue value{}; > > > > > > > > > > switch (id->type()) { > > > > > @@ -324,13 +440,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..fffe67e5 100644 > > > > > --- a/src/cam/capture_script.h > > > > > +++ b/src/cam/capture_script.h > > > > > @@ -54,9 +54,12 @@ private: > > > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > > > > > std::string parseScalar(); > > > > > + libcamera::ControlValue parseRectangles(); > > > > > + std::vector<std::vector<std::string>> parseArrays(); > > > > > + std::vector<std::string> parseSingleArray(); > > > > > > > > > > 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); > > > > > }; > > > > > -- > > > > > 2.34.1 > > > > >
Hi Paul, On Mon, Aug 08, 2022 at 03:56:05PM +0900, paul.elder@ideasonboard.com wrote: > Hi Jacopo, > > On Fri, Aug 05, 2022 at 09:20:26AM +0200, Jacopo Mondi wrote: > > Hi Paul > > > > On Fri, Aug 05, 2022 at 04:47:46AM +0900, paul.elder@ideasonboard.com wrote: > > > Hi Daniel, > > > > > > Thanks for the patches. > > > > > > On Tue, Jun 28, 2022 at 08:35:03AM +0200, Daniel Semkowicz via libcamera-devel wrote: > > > > Hi Jacopo, > > > > > > > > On Mon, Jun 27, 2022 at 6:06 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > > > > > > > > > Hi Daniel > > > > > > > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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 | 145 ++++++++++++++++++++++++++++++++++--- > > > > > > src/cam/capture_script.h | 7 +- > > > > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > > > > 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(); > > > > > > > > > > nit: remaining can potentilly be {} > > > > > > > > Yes, but the vector can be empty not only because of error, but also > > > > because there was a valid array but with only one element (already read > > > > in firstValue). > > > > We would need to add additional parameter returned from method to > > > > distinguish between these two situations. > > > > The higher level that calls parseArrays() should already know the > > > > expected number of elements in the single array, so the error will be > > > > caught anyway. I wouldn't spend too much time tweaking this solution as > > > > it is not critical. > > > > What do you think about leaving it as it is? > > > > > > > > > > > > > > > + > > > > > > + std::vector<std::string> values = { firstValue }; > > > > > > + values.insert(std::end(values), > > > > > > + std::begin(remaining), std::end(remaining)); > > > > > > + valueArrays.push_back(values); > > > > > > + > > > > > > + return valueArrays; > > > > > > + } > > > > > > > > > > This should address Laurent's comment and I assume it now works with > > > > > both > > > > > AfWindows: > > > > > - [x, y, w, h] > > > > > > Gotta be honest, I'm not a big fan of representing Rectangles this way; > > > it's a bit... flat (if that's the right word). > > > I'd prefer it to be like (x,y)/wxh > > > > This would require specifying the rectangle as a string. How will it > > look like in the .yaml file ? Do you have examples you have tested > > your version to share ? > > Oh right I forgot we've got a yaml spec to conform to :S > > I just have it in there as-is: > > frames: > - 1: > ScalerCrop: (0,0)/1920x1080 > > I suppose yaml doesn't have a "rectangle" type. > > So if it's turning that into a string vs into an array... yeah I guess > an array of four ints is better. I would indeed prefer to avoid strings. From a correctness point of view we won't lose much as your code parses the string and if we ever would have a schema we can impose a format, but I feel it would be harder to express multiple rectangles. We could consider more complex mappings like: Rectangles: - x: 0 y: 0 w: 100 h: 100 - x: 120 y: 120 w: 80 h: 80 which are maybe easier to validate, but as far as I can tell won't give us anything more than a list of integers > > Alright, nvm my objection then :) Care to send a tag ? :) I guess we can collect that patch if it's fine with you! Thanks j > > > Paul > > > > > > > > > > > > > > > > > > > and > > > > > AfWindows: > > > > > - [[x, y, w, h], [x1, y1, w1, h1] .. ] > > > > > > > > > > > > > Exactly, I tested it with both versions :) > > > > > > > > Best regards > > > > Daniel > > > > > > > > > > + > > > > > > + /* 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) > > > > > > { > > > > > > 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; > > > > > > } > > > > > > > > > > > > -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 {}; > > > > > > + > > > > > > > > > > Thanks, this address my comment on v1. > > > > > > > > > > Nits apart it looks good to me > > > > > Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> > > > > > > > > > > Thanks > > > > > j > > > > > > > > > > > ControlValue value{}; > > > > > > > > > > > > switch (id->type()) { > > > > > > @@ -324,13 +440,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..fffe67e5 100644 > > > > > > --- a/src/cam/capture_script.h > > > > > > +++ b/src/cam/capture_script.h > > > > > > @@ -54,9 +54,12 @@ private: > > > > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > > > > > > > std::string parseScalar(); > > > > > > + libcamera::ControlValue parseRectangles(); > > > > > > + std::vector<std::vector<std::string>> parseArrays(); > > > > > > + std::vector<std::string> parseSingleArray(); > > > > > > > > > > > > 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); > > > > > > }; > > > > > > -- > > > > > > 2.34.1 > > > > > >
Hi Daniel, On Mon, Jun 27, 2022 at 02:28:05PM +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> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > --- > src/cam/capture_script.cpp | 145 ++++++++++++++++++++++++++++++++++--- > src/cam/capture_script.h | 7 +- > 2 files changed, 139 insertions(+), 13 deletions(-) > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > 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) > { > 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; > } > > -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 +440,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..fffe67e5 100644 > --- a/src/cam/capture_script.h > +++ b/src/cam/capture_script.h > @@ -54,9 +54,12 @@ private: > int parseControl(EventPtr event, libcamera::ControlList &controls); > > std::string parseScalar(); > + libcamera::ControlValue parseRectangles(); > + std::vector<std::vector<std::string>> parseArrays(); > + std::vector<std::string> parseSingleArray(); > > 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); > }; > -- > 2.34.1 >
Hi, Are there plans to merge it to master or additional changes are required? Best regards Daniel On Mon, Aug 8, 2022 at 12:27 PM <paul.elder@ideasonboard.com> wrote: > > Hi Daniel, > > On Mon, Jun 27, 2022 at 02:28:05PM +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> > > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > --- > > src/cam/capture_script.cpp | 145 ++++++++++++++++++++++++++++++++++--- > > src/cam/capture_script.h | 7 +- > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > 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) > > { > > 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; > > } > > > > -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 +440,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..fffe67e5 100644 > > --- a/src/cam/capture_script.h > > +++ b/src/cam/capture_script.h > > @@ -54,9 +54,12 @@ private: > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > std::string parseScalar(); > > + libcamera::ControlValue parseRectangles(); > > + std::vector<std::vector<std::string>> parseArrays(); > > + std::vector<std::string> parseSingleArray(); > > > > 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); > > }; > > -- > > 2.34.1 > >
You're right, the series is tagged and can be merged. I'll take care of that and sorry for the delay :) On Fri, Sep 02, 2022 at 10:02:40AM +0200, Daniel Semkowicz via libcamera-devel wrote: > Hi, > > Are there plans to merge it to master or additional changes are required? > > Best regards > Daniel > > On Mon, Aug 8, 2022 at 12:27 PM <paul.elder@ideasonboard.com> wrote: > > > > Hi Daniel, > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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> > > > > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > --- > > > src/cam/capture_script.cpp | 145 ++++++++++++++++++++++++++++++++++--- > > > src/cam/capture_script.h | 7 +- > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > 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) > > > { > > > 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; > > > } > > > > > > -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 +440,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..fffe67e5 100644 > > > --- a/src/cam/capture_script.h > > > +++ b/src/cam/capture_script.h > > > @@ -54,9 +54,12 @@ private: > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > std::string parseScalar(); > > > + libcamera::ControlValue parseRectangles(); > > > + std::vector<std::vector<std::string>> parseArrays(); > > > + std::vector<std::string> parseSingleArray(); > > > > > > 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); > > > }; > > > -- > > > 2.34.1 > > >
Thank you :) On Fri, Sep 2, 2022 at 12:32 PM Jacopo Mondi <jacopo@jmondi.org> wrote: > > You're right, the series is tagged and can be merged. > > I'll take care of that and sorry for the delay :) > > On Fri, Sep 02, 2022 at 10:02:40AM +0200, Daniel Semkowicz via libcamera-devel wrote: > > Hi, > > > > Are there plans to merge it to master or additional changes are required? > > > > Best regards > > Daniel > > > > On Mon, Aug 8, 2022 at 12:27 PM <paul.elder@ideasonboard.com> wrote: > > > > > > Hi Daniel, > > > > > > On Mon, Jun 27, 2022 at 02:28:05PM +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> > > > > > > Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> > > > > > > > --- > > > > src/cam/capture_script.cpp | 145 ++++++++++++++++++++++++++++++++++--- > > > > src/cam/capture_script.h | 7 +- > > > > 2 files changed, 139 insertions(+), 13 deletions(-) > > > > > > > > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp > > > > index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() > > > > 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) > > > > { > > > > 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; > > > > } > > > > > > > > -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 +440,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..fffe67e5 100644 > > > > --- a/src/cam/capture_script.h > > > > +++ b/src/cam/capture_script.h > > > > @@ -54,9 +54,12 @@ private: > > > > int parseControl(EventPtr event, libcamera::ControlList &controls); > > > > > > > > std::string parseScalar(); > > > > + libcamera::ControlValue parseRectangles(); > > > > + std::vector<std::vector<std::string>> parseArrays(); > > > > + std::vector<std::string> parseSingleArray(); > > > > > > > > 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); > > > > }; > > > > -- > > > > 2.34.1 > > > >
diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp index 9f22d5f7..6278a152 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,104 @@ std::string CaptureScript::parseScalar() 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) { 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; } -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 +440,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..fffe67e5 100644 --- a/src/cam/capture_script.h +++ b/src/cam/capture_script.h @@ -54,9 +54,12 @@ private: int parseControl(EventPtr event, libcamera::ControlList &controls); std::string parseScalar(); + libcamera::ControlValue parseRectangles(); + std::vector<std::vector<std::string>> parseArrays(); + std::vector<std::string> parseSingleArray(); 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); };
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 | 145 ++++++++++++++++++++++++++++++++++--- src/cam/capture_script.h | 7 +- 2 files changed, 139 insertions(+), 13 deletions(-)