[{"id":25487,"web_url":"https://patchwork.libcamera.org/comment/25487/","msgid":"<20221020062339.GC3874866@pyrite.rasen.tech>","date":"2022-10-20T06:23:39","subject":"Re: [libcamera-devel] [PATCH] cam: capture_script: Support parsing\n\tarray controls","submitter":{"id":97,"url":"https://patchwork.libcamera.org/api/people/97/","name":"Nicolas Dufresne via libcamera-devel","email":"libcamera-devel@lists.libcamera.org"},"content":"Hi Jacopo,\n\nOn Tue, Sep 20, 2022 at 07:38:17PM +0200, Jacopo Mondi via libcamera-devel wrote:\n> Add support for parsing array controls to the cam capture script.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  src/cam/capture_script.cpp | 156 +++++++++++++++++++++++++++++++++----\n>  src/cam/capture_script.h   |   5 ++\n>  2 files changed, 144 insertions(+), 17 deletions(-)\n> \n> diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp\n> index 5a27361ce4d9..2feb0a535835 100644\n> --- a/src/cam/capture_script.cpp\n> +++ b/src/cam/capture_script.cpp\n> @@ -454,24 +454,9 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)\n>  \t\t  << typeName << \" control \" << id->name() << std::endl;\n>  }\n>  \n> -ControlValue CaptureScript::unpackControl(const ControlId *id)\n> +ControlValue CaptureScript::parseScalarControl(const ControlId *id,\n> +\t\t\t\t\t       const std::string repr)\n>  {\n> -\t/* Parse complex types. */\n> -\tswitch (id->type()) {\n> -\tcase ControlTypeRectangle:\n> -\t\treturn parseRectangles();\n> -\tcase ControlTypeSize:\n> -\t\t/* \\todo Parse Sizes. */\n> -\t\treturn {};\n> -\tdefault:\n> -\t\tbreak;\n> -\t}\n> -\n> -\t/* Parse basic types represented by a single scalar. */\n> -\tconst std::string repr = parseScalar();\n> -\tif (repr.empty())\n> -\t\treturn {};\n> -\n>  \tControlValue value{};\n>  \n>  \tswitch (id->type()) {\n> @@ -524,6 +509,143 @@ ControlValue CaptureScript::unpackControl(const ControlId *id)\n>  \treturn value;\n>  }\n>  \n> +ControlValue CaptureScript::parseArrayControl(const ControlId *id,\n> +\t\t\t\t\t      const std::vector<std::string> &repr)\n> +{\n> +\tControlValue value{};\n> +\n> +\tswitch (id->type()) {\n> +\tcase ControlTypeNone:\n> +\t\tbreak;\n> +\tcase ControlTypeBool: {\n> +\t\t/*\n> +\t\t * This is unpleasant, but we cannot use an std::vector<> as its\n> +\t\t * boolean type overload does not allow to access the raw data.\n> +\t\t * As we need a contiguous memory region to wrap in a span,\n> +\t\t * use an array instead but be strict about not overflowing it\n> +\t\t * by limiting the number of controls we can store.\n> +\t\t *\n> +\t\t * Be loud but do not fail, as the issue would present at\n> +\t\t * runtime only.\n> +\t\t */\n> +\t\tstatic constexpr unsigned int kMaxNumBooleanControls = 1024;\n> +\t\tstd::array<bool, kMaxNumBooleanControls> values;\n> +\t\tunsigned int idx = 0;\n> +\n> +\t\tfor (const std::string &s : repr) {\n> +\t\t\tbool val;\n> +\n> +\t\t\tif (s == \"true\") {\n> +\t\t\t\tval = true;\n> +\t\t\t} else if (s == \"false\") {\n> +\t\t\t\tval = false;\n> +\t\t\t} else {\n> +\t\t\t\tunpackFailure(id, s);\n> +\t\t\t\treturn value;\n> +\t\t\t}\n> +\n> +\t\t\tif (idx == kMaxNumBooleanControls) {\n> +\t\t\t\tstd::cerr << \"Cannot parse more than \"\n> +\t\t\t\t\t  << kMaxNumBooleanControls\n> +\t\t\t\t\t  << \" boolean controls\" << std::endl;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\n> +\t\t\tvalues[idx++] = val;\n> +\t\t}\n> +\n> +\t\tvalue = Span<bool>(values.data(), values.size());\n\nWouldn't this make a Span with size kMaxNumBooleanControls?\n\n\nPaul\n\n> +\t\tbreak;\n> +\t}\n> +\tcase ControlTypeByte: {\n> +\t\tstd::vector<uint8_t> values;\n> +\t\tfor (const std::string &s : repr) {\n> +\t\t\tuint8_t val = strtoll(s.c_str(), NULL, 10);\n> +\t\t\tvalues.push_back(val);\n> +\t\t}\n> +\n> +\t\tvalue = Span<const uint8_t>(values.data(), values.size());\n> +\t\tbreak;\n> +\t}\n> +\tcase ControlTypeInteger32: {\n> +\t\tstd::vector<int32_t> values;\n> +\t\tfor (const std::string &s : repr) {\n> +\t\t\tint32_t val = strtoll(s.c_str(), NULL, 10);\n> +\t\t\tvalues.push_back(val);\n> +\t\t}\n> +\n> +\t\tvalue = Span<const int32_t>(values.data(), values.size());\n> +\t\tbreak;\n> +\t}\n> +\tcase ControlTypeInteger64: {\n> +\t\tstd::vector<int64_t> values;\n> +\t\tfor (const std::string &s : repr) {\n> +\t\t\tint64_t val = strtoll(s.c_str(), NULL, 10);\n> +\t\t\tvalues.push_back(val);\n> +\t\t}\n> +\n> +\t\tvalue = Span<const int64_t>(values.data(), values.size());\n> +\t\tbreak;\n> +\t}\n> +\tcase ControlTypeFloat: {\n> +\t\tstd::vector<float> values;\n> +\t\tfor (const std::string &s : repr)\n> +\t\t\tvalues.push_back(strtof(s.c_str(), NULL));\n> +\n> +\t\tvalue = Span<const float>(values.data(), values.size());\n> +\t\tbreak;\n> +\t}\n> +\tcase ControlTypeString: {\n> +\t\tvalue = Span<const std::string>(repr.data(), repr.size());\n> +\t\tbreak;\n> +\t}\n> +\tdefault:\n> +\t\tstd::cerr << \"Unsupported control type\" << std::endl;\n> +\t\tbreak;\n> +\t}\n> +\n> +\treturn value;\n> +}\n> +\n> +ControlValue CaptureScript::unpackControl(const ControlId *id)\n> +{\n> +\t/* Parse complex types. */\n> +\tswitch (id->type()) {\n> +\tcase ControlTypeRectangle:\n> +\t\treturn parseRectangles();\n> +\tcase ControlTypeSize:\n> +\t\t/* \\todo Parse Sizes. */\n> +\t\treturn {};\n> +\tdefault:\n> +\t\tbreak;\n> +\t}\n> +\n> +\t/* Check if the control has a single scalar value or is an array. */\n> +\tEventPtr event = nextEvent();\n> +\tif (!event)\n> +\t\treturn {};\n> +\n> +\tswitch (event->type) {\n> +\tcase YAML_SCALAR_EVENT: {\n> +\t\tconst std::string repr = eventScalarValue(event);\n> +\t\tif (repr.empty())\n> +\t\t\treturn {};\n> +\n> +\t\treturn parseScalarControl(id, repr);\n> +\t}\n> +\tcase YAML_SEQUENCE_START_EVENT: {\n> +\t\tstd::vector<std::string> array = parseSingleArray();\n> +\t\tif (array.empty())\n> +\t\t\treturn {};\n> +\n> +\t\treturn parseArrayControl(id, array);\n> +\t}\n> +\tdefault:\n> +\t\tstd::cerr << \"Unexpected event type: \" << event->type << std::endl;\n> +\t\treturn {};\n> +\t}\n> +}\n> +\n>  libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)\n>  {\n>  \tint x = strtol(strVec[0].c_str(), NULL, 10);\n> diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h\n> index 7a0ddebb00b5..40042c0330f0 100644\n> --- a/src/cam/capture_script.h\n> +++ b/src/cam/capture_script.h\n> @@ -56,6 +56,11 @@ private:\n>  \tint parseFrame(EventPtr event);\n>  \tint parseControl(EventPtr event, libcamera::ControlList &controls);\n>  \n> +\tlibcamera::ControlValue parseScalarControl(const libcamera::ControlId *id,\n> +\t\t\t\t\t\t   const std::string repr);\n> +\tlibcamera::ControlValue parseArrayControl(const libcamera::ControlId *id,\n> +\t\t\t\t\t\t  const std::vector<std::string> &repr);\n> +\n>  \tstd::string parseScalar();\n>  \tlibcamera::ControlValue parseRectangles();\n>  \tstd::vector<std::vector<std::string>> parseArrays();\n> -- \n> 2.30.2\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id DC1E4BD16B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 20 Oct 2022 06:23:48 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 3641C62E8F;\n\tThu, 20 Oct 2022 08:23:48 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E41D262E75\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 20 Oct 2022 08:23:46 +0200 (CEST)","from pyrite.rasen.tech (h175-177-042-159.catv02.itscom.jp\n\t[175.177.42.159])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 77594570;\n\tThu, 20 Oct 2022 08:23:45 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666247028;\n\tbh=HqwrwK0zd5AvyTFUr88wpCpkO+Q4/AA9OGCzNpQUOt4=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=mOBqZ0S8ViR/w5lSvELgOEoMw6KSl1Rj2ihVkXs1PoB6C5yg2S/2ZD8UdRMVJn1eD\n\tQ+rdfGhXOVH+4eaYvhBe9uA+61o15wQ2NZGN5XEsSUbXRrZoawGTQvCaOESva8Qlf4\n\tJcMqgt0uEcM0Dra72xsB7vut7gGOAa6XFqeMfDnaBQf6DFwXLyqa2XF2BbZRUWKQbX\n\twYR7uLVyWfeFaKY4Pg3CdtWeySc7wn9yTqPA2zvnS6YdtYsvuRO/PwIhunB+jV1k05\n\tr3RbMM4S9H556/Vsy7un3ma2vNOh7av4X3i0UBphPzuChOpSY6T5D7NsonUpBFDD0S\n\tPAKh2tRAOPYWQ==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1666247026;\n\tbh=HqwrwK0zd5AvyTFUr88wpCpkO+Q4/AA9OGCzNpQUOt4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=FMaQ5QkF9y07ensXyqnIZszmYJF6/MtpksyTwTruZIIUaT79ZPy/BM4jWsvfiZlk2\n\tBCsuK5TbLq8Nsm61Dz2zsQvnnkjQSbYo8ceFx1JXc+qdYO4T7L531JCkgeaO1iC4OT\n\tN2WQTTakdgpIMd+OIlFbRaFxX0l5VEwMBe36aBEA="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"FMaQ5QkF\"; dkim-atps=neutral","Date":"Thu, 20 Oct 2022 15:23:39 +0900","To":"Jacopo Mondi <jacopo@jmondi.org>","Message-ID":"<20221020062339.GC3874866@pyrite.rasen.tech>","References":"<20220920173817.37821-1-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20220920173817.37821-1-jacopo@jmondi.org>","Subject":"Re: [libcamera-devel] [PATCH] cam: capture_script: Support parsing\n\tarray controls","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"paul.elder@ideasonboard.com","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":25497,"web_url":"https://patchwork.libcamera.org/comment/25497/","msgid":"<20221020074449.3kpjtxttkhgpqw45@uno.localdomain>","date":"2022-10-20T07:44:49","subject":"Re: [libcamera-devel] [PATCH] cam: capture_script: Support parsing\n\tarray controls","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Paul,\n  thanks for digging this out\n\nOn Thu, Oct 20, 2022 at 03:23:39PM +0900, paul.elder@ideasonboard.com wrote:\n> Hi Jacopo,\n>\n> On Tue, Sep 20, 2022 at 07:38:17PM +0200, Jacopo Mondi via libcamera-devel wrote:\n> > Add support for parsing array controls to the cam capture script.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > ---\n> >  src/cam/capture_script.cpp | 156 +++++++++++++++++++++++++++++++++----\n> >  src/cam/capture_script.h   |   5 ++\n> >  2 files changed, 144 insertions(+), 17 deletions(-)\n> >\n> > diff --git a/src/cam/capture_script.cpp b/src/cam/capture_script.cpp\n> > index 5a27361ce4d9..2feb0a535835 100644\n> > --- a/src/cam/capture_script.cpp\n> > +++ b/src/cam/capture_script.cpp\n> > @@ -454,24 +454,9 @@ void CaptureScript::unpackFailure(const ControlId *id, const std::string &repr)\n> >  \t\t  << typeName << \" control \" << id->name() << std::endl;\n> >  }\n> >\n> > -ControlValue CaptureScript::unpackControl(const ControlId *id)\n> > +ControlValue CaptureScript::parseScalarControl(const ControlId *id,\n> > +\t\t\t\t\t       const std::string repr)\n> >  {\n> > -\t/* Parse complex types. */\n> > -\tswitch (id->type()) {\n> > -\tcase ControlTypeRectangle:\n> > -\t\treturn parseRectangles();\n> > -\tcase ControlTypeSize:\n> > -\t\t/* \\todo Parse Sizes. */\n> > -\t\treturn {};\n> > -\tdefault:\n> > -\t\tbreak;\n> > -\t}\n> > -\n> > -\t/* Parse basic types represented by a single scalar. */\n> > -\tconst std::string repr = parseScalar();\n> > -\tif (repr.empty())\n> > -\t\treturn {};\n> > -\n> >  \tControlValue value{};\n> >\n> >  \tswitch (id->type()) {\n> > @@ -524,6 +509,143 @@ ControlValue CaptureScript::unpackControl(const ControlId *id)\n> >  \treturn value;\n> >  }\n> >\n> > +ControlValue CaptureScript::parseArrayControl(const ControlId *id,\n> > +\t\t\t\t\t      const std::vector<std::string> &repr)\n> > +{\n> > +\tControlValue value{};\n> > +\n> > +\tswitch (id->type()) {\n> > +\tcase ControlTypeNone:\n> > +\t\tbreak;\n> > +\tcase ControlTypeBool: {\n> > +\t\t/*\n> > +\t\t * This is unpleasant, but we cannot use an std::vector<> as its\n> > +\t\t * boolean type overload does not allow to access the raw data.\n> > +\t\t * As we need a contiguous memory region to wrap in a span,\n> > +\t\t * use an array instead but be strict about not overflowing it\n> > +\t\t * by limiting the number of controls we can store.\n> > +\t\t *\n> > +\t\t * Be loud but do not fail, as the issue would present at\n> > +\t\t * runtime only.\n> > +\t\t */\n> > +\t\tstatic constexpr unsigned int kMaxNumBooleanControls = 1024;\n> > +\t\tstd::array<bool, kMaxNumBooleanControls> values;\n> > +\t\tunsigned int idx = 0;\n> > +\n> > +\t\tfor (const std::string &s : repr) {\n> > +\t\t\tbool val;\n> > +\n> > +\t\t\tif (s == \"true\") {\n> > +\t\t\t\tval = true;\n> > +\t\t\t} else if (s == \"false\") {\n> > +\t\t\t\tval = false;\n> > +\t\t\t} else {\n> > +\t\t\t\tunpackFailure(id, s);\n> > +\t\t\t\treturn value;\n> > +\t\t\t}\n> > +\n> > +\t\t\tif (idx == kMaxNumBooleanControls) {\n> > +\t\t\t\tstd::cerr << \"Cannot parse more than \"\n> > +\t\t\t\t\t  << kMaxNumBooleanControls\n> > +\t\t\t\t\t  << \" boolean controls\" << std::endl;\n> > +\t\t\t\tbreak;\n> > +\t\t\t}\n> > +\n> > +\t\t\tvalues[idx++] = val;\n> > +\t\t}\n> > +\n> > +\t\tvalue = Span<bool>(values.data(), values.size());\n>\n> Wouldn't this make a Span with size kMaxNumBooleanControls?\n>\n\nI should probably use idx!\n\n>\n> Paul\n>\n> > +\t\tbreak;\n> > +\t}\n> > +\tcase ControlTypeByte: {\n> > +\t\tstd::vector<uint8_t> values;\n> > +\t\tfor (const std::string &s : repr) {\n> > +\t\t\tuint8_t val = strtoll(s.c_str(), NULL, 10);\n> > +\t\t\tvalues.push_back(val);\n> > +\t\t}\n> > +\n> > +\t\tvalue = Span<const uint8_t>(values.data(), values.size());\n> > +\t\tbreak;\n> > +\t}\n> > +\tcase ControlTypeInteger32: {\n> > +\t\tstd::vector<int32_t> values;\n> > +\t\tfor (const std::string &s : repr) {\n> > +\t\t\tint32_t val = strtoll(s.c_str(), NULL, 10);\n> > +\t\t\tvalues.push_back(val);\n> > +\t\t}\n> > +\n> > +\t\tvalue = Span<const int32_t>(values.data(), values.size());\n> > +\t\tbreak;\n> > +\t}\n> > +\tcase ControlTypeInteger64: {\n> > +\t\tstd::vector<int64_t> values;\n> > +\t\tfor (const std::string &s : repr) {\n> > +\t\t\tint64_t val = strtoll(s.c_str(), NULL, 10);\n> > +\t\t\tvalues.push_back(val);\n> > +\t\t}\n> > +\n> > +\t\tvalue = Span<const int64_t>(values.data(), values.size());\n> > +\t\tbreak;\n> > +\t}\n> > +\tcase ControlTypeFloat: {\n> > +\t\tstd::vector<float> values;\n> > +\t\tfor (const std::string &s : repr)\n> > +\t\t\tvalues.push_back(strtof(s.c_str(), NULL));\n> > +\n> > +\t\tvalue = Span<const float>(values.data(), values.size());\n> > +\t\tbreak;\n> > +\t}\n> > +\tcase ControlTypeString: {\n> > +\t\tvalue = Span<const std::string>(repr.data(), repr.size());\n> > +\t\tbreak;\n> > +\t}\n> > +\tdefault:\n> > +\t\tstd::cerr << \"Unsupported control type\" << std::endl;\n> > +\t\tbreak;\n> > +\t}\n> > +\n> > +\treturn value;\n> > +}\n> > +\n> > +ControlValue CaptureScript::unpackControl(const ControlId *id)\n> > +{\n> > +\t/* Parse complex types. */\n> > +\tswitch (id->type()) {\n> > +\tcase ControlTypeRectangle:\n> > +\t\treturn parseRectangles();\n> > +\tcase ControlTypeSize:\n> > +\t\t/* \\todo Parse Sizes. */\n> > +\t\treturn {};\n> > +\tdefault:\n> > +\t\tbreak;\n> > +\t}\n> > +\n> > +\t/* Check if the control has a single scalar value or is an array. */\n> > +\tEventPtr event = nextEvent();\n> > +\tif (!event)\n> > +\t\treturn {};\n> > +\n> > +\tswitch (event->type) {\n> > +\tcase YAML_SCALAR_EVENT: {\n> > +\t\tconst std::string repr = eventScalarValue(event);\n> > +\t\tif (repr.empty())\n> > +\t\t\treturn {};\n> > +\n> > +\t\treturn parseScalarControl(id, repr);\n> > +\t}\n> > +\tcase YAML_SEQUENCE_START_EVENT: {\n> > +\t\tstd::vector<std::string> array = parseSingleArray();\n> > +\t\tif (array.empty())\n> > +\t\t\treturn {};\n> > +\n> > +\t\treturn parseArrayControl(id, array);\n> > +\t}\n> > +\tdefault:\n> > +\t\tstd::cerr << \"Unexpected event type: \" << event->type << std::endl;\n> > +\t\treturn {};\n> > +\t}\n> > +}\n> > +\n> >  libcamera::Rectangle CaptureScript::unpackRectangle(const std::vector<std::string> &strVec)\n> >  {\n> >  \tint x = strtol(strVec[0].c_str(), NULL, 10);\n> > diff --git a/src/cam/capture_script.h b/src/cam/capture_script.h\n> > index 7a0ddebb00b5..40042c0330f0 100644\n> > --- a/src/cam/capture_script.h\n> > +++ b/src/cam/capture_script.h\n> > @@ -56,6 +56,11 @@ private:\n> >  \tint parseFrame(EventPtr event);\n> >  \tint parseControl(EventPtr event, libcamera::ControlList &controls);\n> >\n> > +\tlibcamera::ControlValue parseScalarControl(const libcamera::ControlId *id,\n> > +\t\t\t\t\t\t   const std::string repr);\n> > +\tlibcamera::ControlValue parseArrayControl(const libcamera::ControlId *id,\n> > +\t\t\t\t\t\t  const std::vector<std::string> &repr);\n> > +\n> >  \tstd::string parseScalar();\n> >  \tlibcamera::ControlValue parseRectangles();\n> >  \tstd::vector<std::vector<std::string>> parseArrays();\n> > --\n> > 2.30.2\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E670FC0DA4\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 20 Oct 2022 07:44:52 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 356AA62E99;\n\tThu, 20 Oct 2022 09:44:52 +0200 (CEST)","from relay7-d.mail.gandi.net (relay7-d.mail.gandi.net\n\t[217.70.183.200])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 25ABA62DFF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 20 Oct 2022 09:44:51 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby mail.gandi.net (Postfix) with ESMTPSA id 9B26B20018;\n\tThu, 20 Oct 2022 07:44:50 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1666251892;\n\tbh=xB66Ho8VARUy9ovYskeXIXgQqXuEqjHuy6ACJGf5ToY=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=plKc6YGkTtyk+HXTjUKZn47YdTdyCKj+1/GlybQjYBxo0cqC/K6bl9qoSsmXKwkxd\n\txvTO30ysrnLQt/LHVGz1Tqn4fcxZuWp6Dx8He77HmvYJ/N5egu5L0aTribYyFAIrgx\n\tjbWSE8m+toUFY+QYP6GZ+23AlnZWWNvKwvK1vaWLrQCSO8J5TU8MaulYhdM/r6Cg1H\n\t+MttFsK1s4FtpYKSkIhsdvzbqDsORW3q7TrQxBd6Q3uzz1aEq/wq8eRYzHNRUrrgSz\n\thUqSq1QkRgMBk6quKvnM+ZAvAlsL+FtxO3aJWiiAn1pnSgN4ZaelpWKP2UgDm5fh45\n\tGrDnkzcSqDobA==","Date":"Thu, 20 Oct 2022 09:44:49 +0200","To":"paul.elder@ideasonboard.com","Message-ID":"<20221020074449.3kpjtxttkhgpqw45@uno.localdomain>","References":"<20220920173817.37821-1-jacopo@jmondi.org>\n\t<20221020062339.GC3874866@pyrite.rasen.tech>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20221020062339.GC3874866@pyrite.rasen.tech>","Subject":"Re: [libcamera-devel] [PATCH] cam: capture_script: Support parsing\n\tarray controls","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]