[{"id":3796,"web_url":"https://patchwork.libcamera.org/comment/3796/","msgid":"<20200218010332.GN4830@pendragon.ideasonboard.com>","date":"2020-02-18T01:03:32","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: controls: Add\n\tstd::string and double ControlValue type.","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Naush,\n\nThank you for the patch.\n\nOn Mon, Feb 17, 2020 at 02:26:07PM +0000, Naushir Patuck wrote:\n> Strings are a convenient control type for controls such as\n> AWB mode (\"indoor\", \"outdoor\", \"halogen\", etc.) or AGC mode (\"sports\",\n> \"long exposure\", \"spot\", etc.).\n> \n> Double control values are useful for control values such as EV and even\n> gains.\n> \n> This commit adds support for std::string and double control types.\n> Functionality such as ControlRange on std::string types do not really\n> make sense, so do nothing with that for now. Also add appropriate test\n> for the new ControlValue types.\n\nJacopo has posted a patch that adds support for Float controls. I'm\ncurrently reworking it as part of the work on compound controls. Do you\nthink there's a need to support both float and double, or is one of the\n\nFor strings, the feature is useful, but I'd like to implement it as part\nof the compound controls work (or on top of it) if you don't mind, as\nI'm already adding support for dynamic allocation of control data which\ncan be useful for strings. Would that be OK with you ?\n\n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> ---\n>  include/libcamera/controls.h    |  6 +++\n>  src/libcamera/controls.cpp      | 72 ++++++++++++++++++++++++++++++++-\n>  test/controls/control_value.cpp | 26 ++++++++++++\n>  3 files changed, 103 insertions(+), 1 deletion(-)\n> \n> diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h\n> index 458b84e..ac74122 100644\n> --- a/include/libcamera/controls.h\n> +++ b/include/libcamera/controls.h\n> @@ -20,6 +20,8 @@ enum ControlType {\n>  \tControlTypeBool,\n>  \tControlTypeInteger32,\n>  \tControlTypeInteger64,\n> +\tControlTypeString,\n> +\tControlTypeDouble,\n>  };\n>  \n>  class ControlValue\n> @@ -29,6 +31,8 @@ public:\n>  \tControlValue(bool value);\n>  \tControlValue(int32_t value);\n>  \tControlValue(int64_t value);\n> +\tControlValue(std::string value);\n> +\tControlValue(double value);\n>  \n>  \tControlType type() const { return type_; }\n>  \tbool isNone() const { return type_ == ControlTypeNone; }\n> @@ -53,7 +57,9 @@ private:\n>  \t\tbool bool_;\n>  \t\tint32_t integer32_;\n>  \t\tint64_t integer64_;\n> +\t\tdouble double_;\n>  \t};\n> +\tstd::string string_;\n>  };\n>  \n>  class ControlId\n> diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp\n> index 0031cd0..6eb79c9 100644\n> --- a/src/libcamera/controls.cpp\n> +++ b/src/libcamera/controls.cpp\n> @@ -58,6 +58,10 @@ LOG_DEFINE_CATEGORY(Controls)\n>   * The control stores a 32-bit integer value\n>   * \\var ControlTypeInteger64\n>   * The control stores a 64-bit integer value\n> + * \\var ControlTypeString\n> + * The control stores a std::string value\n> + * \\var ControlTypeDouble\n> + * The control stores a double value\n>   */\n>  \n>  /**\n> @@ -100,6 +104,24 @@ ControlValue::ControlValue(int64_t value)\n>  {\n>  }\n>  \n> +/**\n> + * \\brief Construct a std::string ControlValue\n> + * \\param[in] value String value to store\n> + */\n> +ControlValue::ControlValue(std::string value)\n> +\t: type_(ControlTypeString), string_(value)\n> +{\n> +}\n> +\n> +/**\n> + * \\brief Construct a double ControlValue\n> + * \\param[in] value Double value to store\n> + */\n> +ControlValue::ControlValue(double value)\n> +\t: type_(ControlTypeDouble), double_(value)\n> +{\n> +}\n> +\n>  /**\n>   * \\fn ControlValue::type()\n>   * \\brief Retrieve the data type of the value\n> @@ -153,6 +175,18 @@ const int64_t &ControlValue::get<int64_t>() const\n>  \treturn integer64_;\n>  }\n>  \n> +template<>\n> +const std::string &ControlValue::get<std::string>() const\n> +{\n> +\treturn string_;\n> +}\n> +\n> +template<>\n> +const double &ControlValue::get<double>() const\n> +{\n> +\treturn double_;\n> +}\n> +\n>  template<>\n>  void ControlValue::set<bool>(const bool &value)\n>  {\n> @@ -173,6 +207,21 @@ void ControlValue::set<int64_t>(const int64_t &value)\n>  \ttype_ = ControlTypeInteger64;\n>  \tinteger64_ = value;\n>  }\n> +\n> +template<>\n> +void ControlValue::set<std::string>(const std::string &value)\n> +{\n> +\ttype_ = ControlTypeString;\n> +\tstring_ = value;\n> +}\n> +\n> +template<>\n> +void ControlValue::set<double>(const double &value)\n> +{\n> +\ttype_ = ControlTypeDouble;\n> +\tdouble_ = value;\n> +}\n> +\n>  #endif /* __DOXYGEN__ */\n>  \n>  /**\n> @@ -190,6 +239,10 @@ std::string ControlValue::toString() const\n>  \t\treturn std::to_string(integer32_);\n>  \tcase ControlTypeInteger64:\n>  \t\treturn std::to_string(integer64_);\n> +\tcase ControlTypeString:\n> +\t\treturn string_;\n> +\tcase ControlTypeDouble:\n> +\t\treturn std::to_string(double_);\n>  \t}\n>  \n>  \treturn \"<ValueType Error>\";\n> @@ -211,6 +264,10 @@ bool ControlValue::operator==(const ControlValue &other) const\n>  \t\treturn integer32_ == other.integer32_;\n>  \tcase ControlTypeInteger64:\n>  \t\treturn integer64_ == other.integer64_;\n> +\tcase ControlTypeString:\n> +\t\treturn string_ == other.string_;\n> +\tcase ControlTypeDouble:\n> +\t\treturn double_ == other.double_;\n>  \tdefault:\n>  \t\treturn false;\n>  \t}\n> @@ -341,6 +398,18 @@ Control<int64_t>::Control(unsigned int id, const char *name)\n>  \t: ControlId(id, name, ControlTypeInteger64)\n>  {\n>  }\n> +\n> +template<>\n> +Control<std::string>::Control(unsigned int id, const char *name)\n> +\t: ControlId(id, name, ControlTypeString)\n> +{\n> +}\n> +\n> +template<>\n> +Control<double>::Control(unsigned int id, const char *name)\n> +\t: ControlId(id, name, ControlTypeDouble)\n> +{\n> +}\n>  #endif /* __DOXYGEN__ */\n>  \n>  /**\n> @@ -583,7 +652,8 @@ void ControlInfoMap::generateIdmap()\n>  \tidmap_.clear();\n>  \n>  \tfor (const auto &ctrl : *this) {\n> -\t\tif (ctrl.first->type() != ctrl.second.min().type()) {\n> +\t\tif (ctrl.first->type() != ControlTypeString &&\n> +\t\t\t(ctrl.first->type() != ctrl.second.min().type())) {\n>  \t\t\tLOG(Controls, Error)\n>  \t\t\t\t<< \"Control \" << utils::hex(ctrl.first->id())\n>  \t\t\t\t<< \" type and range type mismatch\";\n> diff --git a/test/controls/control_value.cpp b/test/controls/control_value.cpp\n> index a1ffa84..55174da 100644\n> --- a/test/controls/control_value.cpp\n> +++ b/test/controls/control_value.cpp\n> @@ -21,10 +21,14 @@ protected:\n>  \t{\n>  \t\tControlValue integer(1234);\n>  \t\tControlValue boolean(true);\n> +\t\tControlValue fractional(3.142);\n\nLet's not name this fractional, as I think we'll need rational controls\nin the future. Maybe s/fractional/real/ ?\n\n> +\t\tControlValue string(std::string(\"MyString\"));\n>  \n>  \t\t/* Just a string conversion output test... no validation */\n>  \t\tcout << \"Int: \" << integer.toString()\n>  \t\t     << \" Bool: \" << boolean.toString()\n> +\t\t     << \" Frac: \" << fractional.toString()\n> +\t\t     << \" String: \" << string.toString()\n>  \t\t     << endl;\n>  \n>  \t\tif (integer.get<int32_t>() != 1234) {\n> @@ -37,6 +41,16 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> +\t\tif (fractional.get<double>() != 3.142) {\n> +\t\t\tcerr << \"Failed to get Fractional\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif (string.get<std::string>() != std::string(\"MyString\")) {\n> +\t\t\tcerr << \"Failed to get String\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n>  \t\t/* Test an uninitialised value, and updating it. */\n>  \n>  \t\tControlValue value;\n> @@ -62,6 +76,18 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> +\t\tvalue.set<double>(2.718);\n> +\t\tif (value.get<double>() != 2.718) {\n> +\t\t\tcerr << \"Failed to get Fractional\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tvalue.set<std::string>(std::string(\"Test\"));\n> +\t\tif (value.get<std::string>() != std::string(\"Test\")) {\n> +\t\t\tcerr << \"Failed to get String\" << endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n>  \t\treturn TestPass;\n>  \t}\n>  };","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 619E961A44\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 18 Feb 2020 02:03:52 +0100 (CET)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 718211220;\n\tTue, 18 Feb 2020 02:03:51 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1581987832;\n\tbh=du9BW1rdQyFXSHP2YzyMpPSL1vBW8r/FjdB+J+79xUg=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=kb4oL9A+7jjv3v15MTkUab7GtOWWaFJXafCE3QbxhEhV862uvIFI9xnhPVhE19Opr\n\tFupfaQaS7W7W0VgsfQzfGDnonQQqwSxXTEZdsagCm9ApFjrUrlZ3sRV7xRCMczdIxR\n\tverHDGSozkwBaZE8oJHGHw82urJWK0+tg5rNM7uU=","Date":"Tue, 18 Feb 2020 03:03:32 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Naushir Patuck <naush@raspberrypi.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200218010332.GN4830@pendragon.ideasonboard.com>","References":"<20200217142609.22837-1-naush@raspberrypi.com>\n\t<20200217142609.22837-2-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20200217142609.22837-2-naush@raspberrypi.com>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: controls: Add\n\tstd::string and double ControlValue type.","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>","X-List-Received-Date":"Tue, 18 Feb 2020 01:03:52 -0000"}},{"id":3804,"web_url":"https://patchwork.libcamera.org/comment/3804/","msgid":"<CAEmqJPrEp=rMw3YHT11nM8qTE5BwmZSJ4oRjpLQVDQ4iV2+Okg@mail.gmail.com>","date":"2020-02-18T09:36:39","subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: controls: Add\n\tstd::string and double ControlValue type.","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Laurent,\n\nOn Tue, 18 Feb 2020 at 01:03, Laurent Pinchart\n<laurent.pinchart@ideasonboard.com> wrote:\n>\n> Hi Naush,\n>\n> Thank you for the patch.\n>\n> On Mon, Feb 17, 2020 at 02:26:07PM +0000, Naushir Patuck wrote:\n> > Strings are a convenient control type for controls such as\n> > AWB mode (\"indoor\", \"outdoor\", \"halogen\", etc.) or AGC mode (\"sports\",\n> > \"long exposure\", \"spot\", etc.).\n> >\n> > Double control values are useful for control values such as EV and even\n> > gains.\n> >\n> > This commit adds support for std::string and double control types.\n> > Functionality such as ControlRange on std::string types do not really\n> > make sense, so do nothing with that for now. Also add appropriate test\n> > for the new ControlValue types.\n>\n> Jacopo has posted a patch that adds support for Float controls. I'm\n> currently reworking it as part of the work on compound controls. Do you\n> think there's a need to support both float and double, or is one of the\n>\n\nNo need to support both, floats will be adequate for our needs.\n\n> For strings, the feature is useful, but I'd like to implement it as part\n> of the compound controls work (or on top of it) if you don't mind, as\n> I'm already adding support for dynamic allocation of control data which\n> can be useful for strings. Would that be OK with you ?\n>\n\nYes, that seems reasonable.  I will rework the patchset to switch from\nstrings to enums for AWB/AE modes, so we will not need string support\njust yet.  When do you think you will be able to merge the addition of\nfloats - I will rebase this patchset on top of that change when it is\nmerged.\n\n\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> > ---\n> >  include/libcamera/controls.h    |  6 +++\n> >  src/libcamera/controls.cpp      | 72 ++++++++++++++++++++++++++++++++-\n> >  test/controls/control_value.cpp | 26 ++++++++++++\n> >  3 files changed, 103 insertions(+), 1 deletion(-)\n> >\n> > diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h\n> > index 458b84e..ac74122 100644\n> > --- a/include/libcamera/controls.h\n> > +++ b/include/libcamera/controls.h\n> > @@ -20,6 +20,8 @@ enum ControlType {\n> >       ControlTypeBool,\n> >       ControlTypeInteger32,\n> >       ControlTypeInteger64,\n> > +     ControlTypeString,\n> > +     ControlTypeDouble,\n> >  };\n> >\n> >  class ControlValue\n> > @@ -29,6 +31,8 @@ public:\n> >       ControlValue(bool value);\n> >       ControlValue(int32_t value);\n> >       ControlValue(int64_t value);\n> > +     ControlValue(std::string value);\n> > +     ControlValue(double value);\n> >\n> >       ControlType type() const { return type_; }\n> >       bool isNone() const { return type_ == ControlTypeNone; }\n> > @@ -53,7 +57,9 @@ private:\n> >               bool bool_;\n> >               int32_t integer32_;\n> >               int64_t integer64_;\n> > +             double double_;\n> >       };\n> > +     std::string string_;\n> >  };\n> >\n> >  class ControlId\n> > diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp\n> > index 0031cd0..6eb79c9 100644\n> > --- a/src/libcamera/controls.cpp\n> > +++ b/src/libcamera/controls.cpp\n> > @@ -58,6 +58,10 @@ LOG_DEFINE_CATEGORY(Controls)\n> >   * The control stores a 32-bit integer value\n> >   * \\var ControlTypeInteger64\n> >   * The control stores a 64-bit integer value\n> > + * \\var ControlTypeString\n> > + * The control stores a std::string value\n> > + * \\var ControlTypeDouble\n> > + * The control stores a double value\n> >   */\n> >\n> >  /**\n> > @@ -100,6 +104,24 @@ ControlValue::ControlValue(int64_t value)\n> >  {\n> >  }\n> >\n> > +/**\n> > + * \\brief Construct a std::string ControlValue\n> > + * \\param[in] value String value to store\n> > + */\n> > +ControlValue::ControlValue(std::string value)\n> > +     : type_(ControlTypeString), string_(value)\n> > +{\n> > +}\n> > +\n> > +/**\n> > + * \\brief Construct a double ControlValue\n> > + * \\param[in] value Double value to store\n> > + */\n> > +ControlValue::ControlValue(double value)\n> > +     : type_(ControlTypeDouble), double_(value)\n> > +{\n> > +}\n> > +\n> >  /**\n> >   * \\fn ControlValue::type()\n> >   * \\brief Retrieve the data type of the value\n> > @@ -153,6 +175,18 @@ const int64_t &ControlValue::get<int64_t>() const\n> >       return integer64_;\n> >  }\n> >\n> > +template<>\n> > +const std::string &ControlValue::get<std::string>() const\n> > +{\n> > +     return string_;\n> > +}\n> > +\n> > +template<>\n> > +const double &ControlValue::get<double>() const\n> > +{\n> > +     return double_;\n> > +}\n> > +\n> >  template<>\n> >  void ControlValue::set<bool>(const bool &value)\n> >  {\n> > @@ -173,6 +207,21 @@ void ControlValue::set<int64_t>(const int64_t &value)\n> >       type_ = ControlTypeInteger64;\n> >       integer64_ = value;\n> >  }\n> > +\n> > +template<>\n> > +void ControlValue::set<std::string>(const std::string &value)\n> > +{\n> > +     type_ = ControlTypeString;\n> > +     string_ = value;\n> > +}\n> > +\n> > +template<>\n> > +void ControlValue::set<double>(const double &value)\n> > +{\n> > +     type_ = ControlTypeDouble;\n> > +     double_ = value;\n> > +}\n> > +\n> >  #endif /* __DOXYGEN__ */\n> >\n> >  /**\n> > @@ -190,6 +239,10 @@ std::string ControlValue::toString() const\n> >               return std::to_string(integer32_);\n> >       case ControlTypeInteger64:\n> >               return std::to_string(integer64_);\n> > +     case ControlTypeString:\n> > +             return string_;\n> > +     case ControlTypeDouble:\n> > +             return std::to_string(double_);\n> >       }\n> >\n> >       return \"<ValueType Error>\";\n> > @@ -211,6 +264,10 @@ bool ControlValue::operator==(const ControlValue &other) const\n> >               return integer32_ == other.integer32_;\n> >       case ControlTypeInteger64:\n> >               return integer64_ == other.integer64_;\n> > +     case ControlTypeString:\n> > +             return string_ == other.string_;\n> > +     case ControlTypeDouble:\n> > +             return double_ == other.double_;\n> >       default:\n> >               return false;\n> >       }\n> > @@ -341,6 +398,18 @@ Control<int64_t>::Control(unsigned int id, const char *name)\n> >       : ControlId(id, name, ControlTypeInteger64)\n> >  {\n> >  }\n> > +\n> > +template<>\n> > +Control<std::string>::Control(unsigned int id, const char *name)\n> > +     : ControlId(id, name, ControlTypeString)\n> > +{\n> > +}\n> > +\n> > +template<>\n> > +Control<double>::Control(unsigned int id, const char *name)\n> > +     : ControlId(id, name, ControlTypeDouble)\n> > +{\n> > +}\n> >  #endif /* __DOXYGEN__ */\n> >\n> >  /**\n> > @@ -583,7 +652,8 @@ void ControlInfoMap::generateIdmap()\n> >       idmap_.clear();\n> >\n> >       for (const auto &ctrl : *this) {\n> > -             if (ctrl.first->type() != ctrl.second.min().type()) {\n> > +             if (ctrl.first->type() != ControlTypeString &&\n> > +                     (ctrl.first->type() != ctrl.second.min().type())) {\n> >                       LOG(Controls, Error)\n> >                               << \"Control \" << utils::hex(ctrl.first->id())\n> >                               << \" type and range type mismatch\";\n> > diff --git a/test/controls/control_value.cpp b/test/controls/control_value.cpp\n> > index a1ffa84..55174da 100644\n> > --- a/test/controls/control_value.cpp\n> > +++ b/test/controls/control_value.cpp\n> > @@ -21,10 +21,14 @@ protected:\n> >       {\n> >               ControlValue integer(1234);\n> >               ControlValue boolean(true);\n> > +             ControlValue fractional(3.142);\n>\n> Let's not name this fractional, as I think we'll need rational controls\n> in the future. Maybe s/fractional/real/ ?\n>\n> > +             ControlValue string(std::string(\"MyString\"));\n> >\n> >               /* Just a string conversion output test... no validation */\n> >               cout << \"Int: \" << integer.toString()\n> >                    << \" Bool: \" << boolean.toString()\n> > +                  << \" Frac: \" << fractional.toString()\n> > +                  << \" String: \" << string.toString()\n> >                    << endl;\n> >\n> >               if (integer.get<int32_t>() != 1234) {\n> > @@ -37,6 +41,16 @@ protected:\n> >                       return TestFail;\n> >               }\n> >\n> > +             if (fractional.get<double>() != 3.142) {\n> > +                     cerr << \"Failed to get Fractional\" << endl;\n> > +                     return TestFail;\n> > +             }\n> > +\n> > +             if (string.get<std::string>() != std::string(\"MyString\")) {\n> > +                     cerr << \"Failed to get String\" << endl;\n> > +                     return TestFail;\n> > +             }\n> > +\n> >               /* Test an uninitialised value, and updating it. */\n> >\n> >               ControlValue value;\n> > @@ -62,6 +76,18 @@ protected:\n> >                       return TestFail;\n> >               }\n> >\n> > +             value.set<double>(2.718);\n> > +             if (value.get<double>() != 2.718) {\n> > +                     cerr << \"Failed to get Fractional\" << endl;\n> > +                     return TestFail;\n> > +             }\n> > +\n> > +             value.set<std::string>(std::string(\"Test\"));\n> > +             if (value.get<std::string>() != std::string(\"Test\")) {\n> > +                     cerr << \"Failed to get String\" << endl;\n> > +                     return TestFail;\n> > +             }\n> > +\n> >               return TestPass;\n> >       }\n> >  };\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\n\nRegards,\nNaush","headers":{"Return-Path":"<naush@raspberrypi.com>","Received":["from mail-lj1-x241.google.com (mail-lj1-x241.google.com\n\t[IPv6:2a00:1450:4864:20::241])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 62A2461D61\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 18 Feb 2020 10:36:55 +0100 (CET)","by mail-lj1-x241.google.com with SMTP id e18so22062563ljn.12\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 18 Feb 2020 01:36:55 -0800 (PST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=MxtthLho3uq65HIky28jNGp4ljmsZmeUwR1IvbMBkus=;\n\tb=k15/JIUWHHNY41F3MVLLrPZCkO4WOc3yyxKE1Ifvc6q7jS+40hDsh6O64lUeB3qCP/\n\tKjTGAnE+N0BvbBsAMX6GlcIwUIhdYAGfuA51vc2HcIlgGS87N2CM5U+WcklDqyRQYrmw\n\t954SWUT+GLJBm4tL6eR6GvwZs7U7ut+Jdvc3iBnlTt4ZE9BSDFMg46bAaQUfGQcF8o8V\n\t9Lrmo/FyiO0vet2H0igEGwRF8af3KTyggA9O9DpbG/cjGGWc/3n0ahw0/8NlotbEJ3Zy\n\tKQ5ymghwoWjkT8WTfYh3IM4XfTgoVAmgzJoGH3ryxN/I91mNGtDSF0lJNXEVrOoTu0rp\n\tB0dg==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=MxtthLho3uq65HIky28jNGp4ljmsZmeUwR1IvbMBkus=;\n\tb=QTY+VXjZ7686Xf+YWGOF2fMoqkZhOD9aeoLa3vY91bXmUaT7LzqfHZJoisbESx6stS\n\t6E7Dhp6L03V7k2JR0TjHH0rDpym9UFqTJp4Vsvpm4lZYoa7vT4oaPUJXElOfM6LzZQ0f\n\tjGfi1s3mJAkisHCb7ae24GwOueqLNFNr4UpLu0y5tc36Rr+gx7NVKjhO7xPY8laQ5dFh\n\t3OxUppZTkneaAbKU2kptY+kelCVuD+mGsam7vlYeq0IdxyhRUcZi7hAgpDnWfSrxTe7T\n\t1UH5L2I8Lj1eXSNBDucaNoHFL9zcNDYp9yUW7IlC6rXEJR+Bm0bHZAMYbbp2bpU7Plch\n\tIOJg==","X-Gm-Message-State":"APjAAAUiV/mJYHAtkHa8MxR5xA7LuEM6AYUZE/XG9RA4ZTEiTizPasOt\n\tKD27XC6N1sVPMoqZQ6va/khyS0eCosdN3C4hPIruuw==","X-Google-Smtp-Source":"APXvYqz0xgwuB1Ra82CMfDNU0SxvVHAtmx4oWk/N+qT8J6VajwhHTnFanknntt+irLWRTZgrvNsqpX1FGjkhpnhWn9M=","X-Received":"by 2002:a2e:8944:: with SMTP id b4mr11303723ljk.90.1582018614641;\n\tTue, 18 Feb 2020 01:36:54 -0800 (PST)","MIME-Version":"1.0","References":"<20200217142609.22837-1-naush@raspberrypi.com>\n\t<20200217142609.22837-2-naush@raspberrypi.com>\n\t<20200218010332.GN4830@pendragon.ideasonboard.com>","In-Reply-To":"<20200218010332.GN4830@pendragon.ideasonboard.com>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Tue, 18 Feb 2020 09:36:39 +0000","Message-ID":"<CAEmqJPrEp=rMw3YHT11nM8qTE5BwmZSJ4oRjpLQVDQ4iV2+Okg@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"UTF-8\"","Subject":"Re: [libcamera-devel] [PATCH 1/3] libcamera: controls: Add\n\tstd::string and double ControlValue type.","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>","X-List-Received-Date":"Tue, 18 Feb 2020 09:36:55 -0000"}}]