[{"id":470,"web_url":"https://patchwork.libcamera.org/comment/470/","msgid":"<20190122084634.mkwfixl2ndahuyjl@uno.localdomain>","date":"2019-01-22T08:46:34","subject":"Re: [libcamera-devel] [PATCH v2 2/4] libcamera: log: Get log levels\n\tfrom the environment","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent,\n\nOn Mon, Jan 21, 2019 at 09:56:04PM +0200, Laurent Pinchart wrote:\n> Set the log level for each log category from the environment variable\n> LIBCAMERA_LOG_LEVELS.\n>\n\nVery nice indeed, but aren't log level numbers supposed to be used the\nother way around?\n\nRight now LIBCAMERA_LOG_LEVELS=0 is \"DEBUG\" and LIBCAMERA_LOG_LEVELS=4\nis \"FATAL\" only. I would have expect to have 4 = maximum debug, 0 =\nonly fatal, right now is the other way around...\n\nAlso, stupid thing but, isn't LIBCAMERA_LOG_LEVELS a bit long?\ngstreamer has a more compact GST_DBG which is shorter to type...\nLIBCAM_DBG maybe?\n\nThe patch itself is good, please add my\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n> The variable contains a comma-separated list of category:level pairs,\n> and category names can include wildcards.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> ---\n>  src/libcamera/log.cpp | 202 ++++++++++++++++++++++++++++++++++++++++++\n>  1 file changed, 202 insertions(+)\n>\n> diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> index 20503fdcfcc1..23bb9edb9d14 100644\n> --- a/src/libcamera/log.cpp\n> +++ b/src/libcamera/log.cpp\n> @@ -9,7 +9,9 @@\n>  #include <cstdlib>\n>  #include <ctime>\n>  #include <iomanip>\n> +#include <list>\n>  #include <string.h>\n> +#include <unordered_set>\n>\n>  #include \"log.h\"\n>  #include \"utils.h\"\n> @@ -17,10 +19,208 @@\n>  /**\n>   * \\file log.h\n>   * \\brief Logging infrastructure\n> + *\n> + * libcamera includes a logging infrastructure used through the library that\n> + * allows inspection of internal operation in a user-configurable way. The log\n> + * messages are grouped in categories that represent areas of libcamera, and\n> + * output of messages for each category can be controlled by independent log\n> + * levels.\n> + *\n> + * The levels are configurable through the LIBCAMERA_LOG_LEVELS environment\n> + * variable that contains a comma-separated list of 'category=level' pairs.\n> + *\n> + * The category names are strings and can include a wildcard ('*') character at\n> + * the end to match multiple categories.\n> + *\n> + * The level are either numeric values, or strings containing the log level\n> + * name. The available log levels are DEBUG, INFO, WARN, ERROR and FATAL. Log\n> + * message with a level higher than or equal to the configured log level for\n> + * their category are output to the log, while other messages are silently\n> + * discarded.\n>   */\n>\n>  namespace libcamera {\n>\n> +/**\n> + * \\brief Message logger\n> + *\n> + * The Logger class handles log configuration.\n> + */\n> +class Logger\n> +{\n> +public:\n> +\tstatic Logger *instance();\n> +\n> +private:\n> +\tLogger();\n> +\n> +\tvoid parseLogLevels();\n> +\tstatic LogSeverity parseLogLevel(const std::string &level);\n> +\n> +\tfriend LogCategory;\n> +\tvoid registerCategory(LogCategory *category);\n> +\tvoid unregisterCategory(LogCategory *category);\n> +\n> +\tstd::unordered_set<LogCategory *> categories_;\n> +\tstd::list<std::pair<std::string, LogSeverity>> levels_;\n> +};\n> +\n> +/**\n> + * \\brief Retrieve the logger instance\n> + *\n> + * The Logger is a singleton and can't be constructed manually. This function\n> + * shall instead be used to retrieve the single global instance of the logger.\n> + *\n> + * \\return The logger instance\n> + */\n> +Logger *Logger::instance()\n> +{\n> +\tstatic Logger instance;\n> +\treturn &instance;\n> +}\n> +\n> +/**\n> + * \\brief Construct a logger\n> + */\n> +Logger::Logger()\n> +{\n> +\tparseLogLevels();\n> +}\n> +\n> +/**\n> + * \\brief Parse the log levels from the environment\n> + *\n> + * The logr levels are stored in LIBCAMERA_LOG_LEVELS environement variable as a list\n> + * of \"category=level\" pairs, separated by commas (','). Parse the variable and\n> + * store the levels to configure all log categories.\n> + */\n> +void Logger::parseLogLevels()\n> +{\n> +\tconst char *debug = secure_getenv(\"LIBCAMERA_LOG_LEVELS\");\n> +\tif (!debug)\n> +\t\treturn;\n> +\n> +\tfor (const char *pair = debug; *debug != '\\0'; pair = debug) {\n> +\t\tconst char *comma = strchrnul(debug, ',');\n> +\t\tsize_t len = comma - pair;\n> +\n> +\t\t/* Skip over the comma. */\n> +\t\tdebug = *comma == ',' ? comma + 1 : comma;\n> +\n> +\t\t/* Skip to the next pair if the pair is empty. */\n> +\t\tif (!len)\n> +\t\t\tcontinue;\n> +\n> +\t\tstd::string category;\n> +\t\tstd::string level;\n> +\n> +\t\tconst char *colon = static_cast<const char *>(memchr(pair, ':', len));\n> +\t\tif (!colon) {\n> +\t\t\t/* 'x' is a shortcut for '*:x'. */\n> +\t\t\tcategory = \"*\";\n> +\t\t\tlevel = std::string(pair, len);\n> +\t\t} else {\n> +\t\t\tcategory = std::string(pair, colon - pair);\n> +\t\t\tlevel = std::string(colon + 1, comma - colon - 1);\n> +\t\t}\n> +\n> +\t\t/* Both the category and the level must be specified. */\n> +\t\tif (category.empty() || level.empty())\n> +\t\t\tcontinue;\n> +\n> +\t\tLogSeverity severity = parseLogLevel(level);\n> +\t\tif (severity == -1)\n> +\t\t\tcontinue;\n> +\n> +\t\tlevels_.push_back({ category, severity });\n> +\t}\n> +}\n> +\n> +/**\n> + * \\brief Parse a log level string into a LogSeverity\n> + * \\param[in] level The log level string\n> + *\n> + * Log levels can be specified as an integer value in the range from LogDebug to\n> + * LogFatal, or as a string corresponding to the severity name in uppercase. Any\n> + * other value is invalid.\n> + *\n> + * \\return The log severity, or -1 if the string is invalid\n> + */\n> +LogSeverity Logger::parseLogLevel(const std::string &level)\n> +{\n> +\tstatic const char *const names[] = {\n> +\t\t\"DEBUG\",\n> +\t\t\"INFO\",\n> +\t\t\"WARN\",\n> +\t\t\"ERROR\",\n> +\t\t\"FATAL\",\n> +\t};\n> +\n> +\tint severity;\n> +\n> +\tif (std::isdigit(level[0])) {\n> +\t\tchar *endptr;\n> +\t\tseverity = strtoul(level.c_str(), &endptr, 10);\n> +\t\tif (*endptr != '\\0' || severity > LogFatal)\n> +\t\t\tseverity = -1;\n> +\t} else {\n> +\t\tseverity = -1;\n> +\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(names); ++i) {\n> +\t\t\tif (names[i] == level) {\n> +\t\t\t\tseverity = i;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t}\n> +\t}\n> +\n> +\treturn static_cast<LogSeverity>(severity);\n> +}\n> +\n> +/**\n> + * \\brief Register a log category with the logger\n> + * \\param[in] category The log category\n> + *\n> + * Log categories must have unique names. If a category with the same name\n> + * already exists this function performs no operation.\n> + */\n> +void Logger::registerCategory(LogCategory *category)\n> +{\n> +\tcategories_.insert(category);\n> +\n> +\tconst std::string &name = category->name();\n> +\tfor (const std::pair<std::string, LogSeverity> &level : levels_) {\n> +\t\tbool match = true;\n> +\n> +\t\tfor (unsigned int i = 0; i < level.first.size(); ++i) {\n> +\t\t\tif (level.first[i] == '*')\n> +\t\t\t\tbreak;\n> +\n> +\t\t\tif (i >= name.size() ||\n> +\t\t\t    name[i] != level.first[i]) {\n> +\t\t\t\tmatch = false;\n> +\t\t\t\tbreak;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (match) {\n> +\t\t\tcategory->setSeverity(level.second);\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n> +}\n> +\n> +/**\n> + * \\brief Unregister a log category from the logger\n> + * \\param[in] category The log category\n> + *\n> + * If the \\a category hasn't been registered with the logger this function\n> + * performs no operation.\n> + */\n> +void Logger::unregisterCategory(LogCategory *category)\n> +{\n> +\tcategories_.erase(category);\n> +}\n> +\n>  /**\n>   * \\enum LogSeverity\n>   * Log message severity\n> @@ -52,10 +252,12 @@ namespace libcamera {\n>  LogCategory::LogCategory(const char *name)\n>  \t: name_(name), severity_(LogSeverity::LogInfo)\n>  {\n> +\tLogger::instance()->registerCategory(this);\n>  }\n>\n>  LogCategory::~LogCategory()\n>  {\n> +\tLogger::instance()->unregisterCategory(this);\n>  }\n>\n>  /**\n> --\n> Regards,\n>\n> Laurent Pinchart\n>\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<jacopo@jmondi.org>","Received":["from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net\n\t[217.70.183.197])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9565A60C81\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 22 Jan 2019 09:46:22 +0100 (CET)","from uno.localdomain (2-224-242-101.ip172.fastwebnet.it\n\t[2.224.242.101]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay5-d.mail.gandi.net (Postfix) with ESMTPSA id 143E81C0002;\n\tTue, 22 Jan 2019 08:46:21 +0000 (UTC)"],"X-Originating-IP":"2.224.242.101","Date":"Tue, 22 Jan 2019 09:46:34 +0100","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190122084634.mkwfixl2ndahuyjl@uno.localdomain>","References":"<20190121195606.8526-1-laurent.pinchart@ideasonboard.com>\n\t<20190121195606.8526-3-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"f7twg7isidijfo5e\"","Content-Disposition":"inline","In-Reply-To":"<20190121195606.8526-3-laurent.pinchart@ideasonboard.com>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH v2 2/4] libcamera: log: Get log levels\n\tfrom the environment","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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, 22 Jan 2019 08:46:22 -0000"}},{"id":499,"web_url":"https://patchwork.libcamera.org/comment/499/","msgid":"<20190122142218.GG4455@pendragon.ideasonboard.com>","date":"2019-01-22T14:22:18","subject":"Re: [libcamera-devel] [PATCH v2 2/4] libcamera: log: Get log levels\n\tfrom the environment","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn Tue, Jan 22, 2019 at 09:46:34AM +0100, Jacopo Mondi wrote:\n> On Mon, Jan 21, 2019 at 09:56:04PM +0200, Laurent Pinchart wrote:\n> > Set the log level for each log category from the environment variable\n> > LIBCAMERA_LOG_LEVELS.\n> \n> Very nice indeed, but aren't log level numbers supposed to be used the\n> other way around?\n> \n> Right now LIBCAMERA_LOG_LEVELS=0 is \"DEBUG\" and LIBCAMERA_LOG_LEVELS=4\n> is \"FATAL\" only. I would have expect to have 4 = maximum debug, 0 =\n> only fatal, right now is the other way around...\n\nPatches are welcome :-) I don't mind handling numerical values the other\nway around. Make sure that, whatever you do, you don't allow disabling\nFatal messages, those should always be preinted.\n\n> Also, stupid thing but, isn't LIBCAMERA_LOG_LEVELS a bit long?\n> gstreamer has a more compact GST_DBG which is shorter to type...\n> LIBCAM_DBG maybe?\n\nI think it's GST_DEBUG in gstreamer. I initially went with\nLIBCAMERA_DEBUG, but having a common prefix for all log-related\nenvironment variables also has value.\n\n> The patch itself is good, please add my\n> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n> \n> > The variable contains a comma-separated list of category:level pairs,\n> > and category names can include wildcards.\n> >\n> > Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> > ---\n> >  src/libcamera/log.cpp | 202 ++++++++++++++++++++++++++++++++++++++++++\n> >  1 file changed, 202 insertions(+)\n> >\n> > diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> > index 20503fdcfcc1..23bb9edb9d14 100644\n> > --- a/src/libcamera/log.cpp\n> > +++ b/src/libcamera/log.cpp\n> > @@ -9,7 +9,9 @@\n> >  #include <cstdlib>\n> >  #include <ctime>\n> >  #include <iomanip>\n> > +#include <list>\n> >  #include <string.h>\n> > +#include <unordered_set>\n> >\n> >  #include \"log.h\"\n> >  #include \"utils.h\"\n> > @@ -17,10 +19,208 @@\n> >  /**\n> >   * \\file log.h\n> >   * \\brief Logging infrastructure\n> > + *\n> > + * libcamera includes a logging infrastructure used through the library that\n> > + * allows inspection of internal operation in a user-configurable way. The log\n> > + * messages are grouped in categories that represent areas of libcamera, and\n> > + * output of messages for each category can be controlled by independent log\n> > + * levels.\n> > + *\n> > + * The levels are configurable through the LIBCAMERA_LOG_LEVELS environment\n> > + * variable that contains a comma-separated list of 'category=level' pairs.\n> > + *\n> > + * The category names are strings and can include a wildcard ('*') character at\n> > + * the end to match multiple categories.\n> > + *\n> > + * The level are either numeric values, or strings containing the log level\n> > + * name. The available log levels are DEBUG, INFO, WARN, ERROR and FATAL. Log\n> > + * message with a level higher than or equal to the configured log level for\n> > + * their category are output to the log, while other messages are silently\n> > + * discarded.\n> >   */\n> >\n> >  namespace libcamera {\n> >\n> > +/**\n> > + * \\brief Message logger\n> > + *\n> > + * The Logger class handles log configuration.\n> > + */\n> > +class Logger\n> > +{\n> > +public:\n> > +\tstatic Logger *instance();\n> > +\n> > +private:\n> > +\tLogger();\n> > +\n> > +\tvoid parseLogLevels();\n> > +\tstatic LogSeverity parseLogLevel(const std::string &level);\n> > +\n> > +\tfriend LogCategory;\n> > +\tvoid registerCategory(LogCategory *category);\n> > +\tvoid unregisterCategory(LogCategory *category);\n> > +\n> > +\tstd::unordered_set<LogCategory *> categories_;\n> > +\tstd::list<std::pair<std::string, LogSeverity>> levels_;\n> > +};\n> > +\n> > +/**\n> > + * \\brief Retrieve the logger instance\n> > + *\n> > + * The Logger is a singleton and can't be constructed manually. This function\n> > + * shall instead be used to retrieve the single global instance of the logger.\n> > + *\n> > + * \\return The logger instance\n> > + */\n> > +Logger *Logger::instance()\n> > +{\n> > +\tstatic Logger instance;\n> > +\treturn &instance;\n> > +}\n> > +\n> > +/**\n> > + * \\brief Construct a logger\n> > + */\n> > +Logger::Logger()\n> > +{\n> > +\tparseLogLevels();\n> > +}\n> > +\n> > +/**\n> > + * \\brief Parse the log levels from the environment\n> > + *\n> > + * The logr levels are stored in LIBCAMERA_LOG_LEVELS environement variable as a list\n> > + * of \"category=level\" pairs, separated by commas (','). Parse the variable and\n> > + * store the levels to configure all log categories.\n> > + */\n> > +void Logger::parseLogLevels()\n> > +{\n> > +\tconst char *debug = secure_getenv(\"LIBCAMERA_LOG_LEVELS\");\n> > +\tif (!debug)\n> > +\t\treturn;\n> > +\n> > +\tfor (const char *pair = debug; *debug != '\\0'; pair = debug) {\n> > +\t\tconst char *comma = strchrnul(debug, ',');\n> > +\t\tsize_t len = comma - pair;\n> > +\n> > +\t\t/* Skip over the comma. */\n> > +\t\tdebug = *comma == ',' ? comma + 1 : comma;\n> > +\n> > +\t\t/* Skip to the next pair if the pair is empty. */\n> > +\t\tif (!len)\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tstd::string category;\n> > +\t\tstd::string level;\n> > +\n> > +\t\tconst char *colon = static_cast<const char *>(memchr(pair, ':', len));\n> > +\t\tif (!colon) {\n> > +\t\t\t/* 'x' is a shortcut for '*:x'. */\n> > +\t\t\tcategory = \"*\";\n> > +\t\t\tlevel = std::string(pair, len);\n> > +\t\t} else {\n> > +\t\t\tcategory = std::string(pair, colon - pair);\n> > +\t\t\tlevel = std::string(colon + 1, comma - colon - 1);\n> > +\t\t}\n> > +\n> > +\t\t/* Both the category and the level must be specified. */\n> > +\t\tif (category.empty() || level.empty())\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tLogSeverity severity = parseLogLevel(level);\n> > +\t\tif (severity == -1)\n> > +\t\t\tcontinue;\n> > +\n> > +\t\tlevels_.push_back({ category, severity });\n> > +\t}\n> > +}\n> > +\n> > +/**\n> > + * \\brief Parse a log level string into a LogSeverity\n> > + * \\param[in] level The log level string\n> > + *\n> > + * Log levels can be specified as an integer value in the range from LogDebug to\n> > + * LogFatal, or as a string corresponding to the severity name in uppercase. Any\n> > + * other value is invalid.\n> > + *\n> > + * \\return The log severity, or -1 if the string is invalid\n> > + */\n> > +LogSeverity Logger::parseLogLevel(const std::string &level)\n> > +{\n> > +\tstatic const char *const names[] = {\n> > +\t\t\"DEBUG\",\n> > +\t\t\"INFO\",\n> > +\t\t\"WARN\",\n> > +\t\t\"ERROR\",\n> > +\t\t\"FATAL\",\n> > +\t};\n> > +\n> > +\tint severity;\n> > +\n> > +\tif (std::isdigit(level[0])) {\n> > +\t\tchar *endptr;\n> > +\t\tseverity = strtoul(level.c_str(), &endptr, 10);\n> > +\t\tif (*endptr != '\\0' || severity > LogFatal)\n> > +\t\t\tseverity = -1;\n> > +\t} else {\n> > +\t\tseverity = -1;\n> > +\t\tfor (unsigned int i = 0; i < ARRAY_SIZE(names); ++i) {\n> > +\t\t\tif (names[i] == level) {\n> > +\t\t\t\tseverity = i;\n> > +\t\t\t\tbreak;\n> > +\t\t\t}\n> > +\t\t}\n> > +\t}\n> > +\n> > +\treturn static_cast<LogSeverity>(severity);\n> > +}\n> > +\n> > +/**\n> > + * \\brief Register a log category with the logger\n> > + * \\param[in] category The log category\n> > + *\n> > + * Log categories must have unique names. If a category with the same name\n> > + * already exists this function performs no operation.\n> > + */\n> > +void Logger::registerCategory(LogCategory *category)\n> > +{\n> > +\tcategories_.insert(category);\n> > +\n> > +\tconst std::string &name = category->name();\n> > +\tfor (const std::pair<std::string, LogSeverity> &level : levels_) {\n> > +\t\tbool match = true;\n> > +\n> > +\t\tfor (unsigned int i = 0; i < level.first.size(); ++i) {\n> > +\t\t\tif (level.first[i] == '*')\n> > +\t\t\t\tbreak;\n> > +\n> > +\t\t\tif (i >= name.size() ||\n> > +\t\t\t    name[i] != level.first[i]) {\n> > +\t\t\t\tmatch = false;\n> > +\t\t\t\tbreak;\n> > +\t\t\t}\n> > +\t\t}\n> > +\n> > +\t\tif (match) {\n> > +\t\t\tcategory->setSeverity(level.second);\n> > +\t\t\tbreak;\n> > +\t\t}\n> > +\t}\n> > +}\n> > +\n> > +/**\n> > + * \\brief Unregister a log category from the logger\n> > + * \\param[in] category The log category\n> > + *\n> > + * If the \\a category hasn't been registered with the logger this function\n> > + * performs no operation.\n> > + */\n> > +void Logger::unregisterCategory(LogCategory *category)\n> > +{\n> > +\tcategories_.erase(category);\n> > +}\n> > +\n> >  /**\n> >   * \\enum LogSeverity\n> >   * Log message severity\n> > @@ -52,10 +252,12 @@ namespace libcamera {\n> >  LogCategory::LogCategory(const char *name)\n> >  \t: name_(name), severity_(LogSeverity::LogInfo)\n> >  {\n> > +\tLogger::instance()->registerCategory(this);\n> >  }\n> >\n> >  LogCategory::~LogCategory()\n> >  {\n> > +\tLogger::instance()->unregisterCategory(this);\n> >  }\n> >\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 D7A3560B1B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue, 22 Jan 2019 15:22:19 +0100 (CET)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 6794553E;\n\tTue, 22 Jan 2019 15:22:19 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1548166939;\n\tbh=9DXBIXOkm3i3T/RSGIHSvHu6tpbAm49+h3tLLNmJ3HQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=r3eDgdku0dxAGw3KXoj9W0JO9A0GDZ+j7BXg9XSE/kmqwuZ4CBlx4TkFkx4lbv/ax\n\tNeau3hpuZcN3fZYksC78ut9rlpGu0UmqUfok+XrHe6WiVczkxb3JbHwXZF/i0HAz6q\n\tOl2ksTyipEwwFxpJSqa4Giz3SkU5qVsBtdV5hMMo=","Date":"Tue, 22 Jan 2019 16:22:18 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190122142218.GG4455@pendragon.ideasonboard.com>","References":"<20190121195606.8526-1-laurent.pinchart@ideasonboard.com>\n\t<20190121195606.8526-3-laurent.pinchart@ideasonboard.com>\n\t<20190122084634.mkwfixl2ndahuyjl@uno.localdomain>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190122084634.mkwfixl2ndahuyjl@uno.localdomain>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v2 2/4] libcamera: log: Get log levels\n\tfrom the environment","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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, 22 Jan 2019 14:22:20 -0000"}}]