From patchwork Thu May 5 10:40:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 15788 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 37B87C326C for ; Thu, 5 May 2022 10:41:35 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 757946564D; Thu, 5 May 2022 12:41:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1651747291; bh=drreAiTzVPj/8papvYf8Ka9q5BVWu4HwHS0fgUN0E98=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=gT7b5PZGK0NsjEHODW0R6lUDh9U5FD5HItULVaY5IiXFvGDVyl8a9F2MnjtSy8W3+ lQIFEHuBfGp2qge6w5p05YfErpN6BC1oTEkupEcAVpls9CKjp0UoRuxOIlAwH9Je0D pFzGYrGOEGl72BbzFh+dMnJmPbncLvz/2m/eHAm1ISyWzDQLhHekMuM4kpUQ160oLn LpXhYThsqE1EG7pqQTFSa+0AHm3q9tRxrNLoIIBs38LnQVT85W0g+JZic343YaY0Cs Rs1JB92w6EEclZv/hsXCqwo2DEOrzdxWA5MNFJNK/wMKbjwt/UyaFFWhz77aqw4ylp 4RkCrN2YA+0mQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D1B5C65649 for ; Thu, 5 May 2022 12:41:27 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="GqT4NQpM"; dkim-atps=neutral Received: from deskari.lan (91-156-85-209.elisa-laajakaista.fi [91.156.85.209]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4D658492; Thu, 5 May 2022 12:41:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1651747287; bh=drreAiTzVPj/8papvYf8Ka9q5BVWu4HwHS0fgUN0E98=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GqT4NQpMjtvaN8AY8KJbWqeXFJjc1R4UBNKPxcX3FOYgDAk4Phgb9WBvJzVstUeJe qsKQBWfH3IOwHjopFv780TrwQuv5PCYrn1Z94YHN7wJeQaorpyvEwzOI2RGKywHm7n EjXt6V1SnE7R8ZCpZNiB3T0DfkClxmQIb+irnkD8= To: libcamera-devel@lists.libcamera.org, David Plowman , Kieran Bingham , Laurent Pinchart , Jacopo Mondi Date: Thu, 5 May 2022 13:40:56 +0300 Message-Id: <20220505104104.70841-6-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220505104104.70841-1-tomi.valkeinen@ideasonboard.com> References: <20220505104104.70841-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v7 05/13] py: generate control enums from yaml X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Tomi Valkeinen via libcamera-devel From: Tomi Valkeinen Reply-To: Tomi Valkeinen Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Generate enums for controls from control_ids.yaml. The generator script has some heuristics to generate nicer enum names. E.g. instead of having "LensShadingMapMode.LensShadingMapModeOff" we get "LensShadingMapMode.Off". This heuristics may need to be updated when the yaml file is changed or new controls are added. Signed-off-by: Tomi Valkeinen Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart --- src/py/libcamera/gen-py-control-enums.py | 95 +++++++++++++++++++++++ src/py/libcamera/meson.build | 9 +++ src/py/libcamera/pyenums_generated.cpp.in | 21 +++++ src/py/libcamera/pymain.cpp | 2 + 4 files changed, 127 insertions(+) create mode 100755 src/py/libcamera/gen-py-control-enums.py create mode 100644 src/py/libcamera/pyenums_generated.cpp.in diff --git a/src/py/libcamera/gen-py-control-enums.py b/src/py/libcamera/gen-py-control-enums.py new file mode 100755 index 00000000..f1b18389 --- /dev/null +++ b/src/py/libcamera/gen-py-control-enums.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Generate Python bindings enums for controls from YAML + +import argparse +import string +import sys +import yaml + + +def find_common_prefix(strings): + prefix = strings[0] + + for string in strings[1:]: + while string[:len(prefix)] != prefix and prefix: + prefix = prefix[:len(prefix) - 1] + if not prefix: + break + + return prefix + + +def generate_py(controls): + out = "" + + for ctrl in controls: + name, ctrl = ctrl.popitem() + + enum = ctrl.get('enum') + if not enum: + continue + + if ctrl.get('draft'): + ns = "libcamera::controls::draft::" + else: + ns = "libcamera::controls::" + + cpp_enum = name + "Enum" + + out += "\tpy::enum_<{}{}>(m, \"{}\")\n".format(ns, cpp_enum, name) + + if name == "LensShadingMapMode": + prefix = "LensShadingMapMode" + else: + prefix = find_common_prefix([e["name"] for e in enum]) + + for entry in enum: + cpp_enum = entry["name"] + py_enum = entry["name"][len(prefix):] + + out += "\t\t.value(\"{}\", {}{})\n".format(py_enum, ns, cpp_enum) + + out += "\t;\n" + + return {"enums": out} + + +def fill_template(template, data): + template = open(template, 'rb').read() + template = template.decode('utf-8') + template = string.Template(template) + return template.substitute(data) + + +def main(argv): + # Parse command line arguments + parser = argparse.ArgumentParser() + parser.add_argument('-o', dest='output', metavar='file', type=str, + help='Output file name. Defaults to standard output if not specified.') + parser.add_argument('input', type=str, + help='Input file name.') + parser.add_argument('template', type=str, + help='Template file name.') + args = parser.parse_args(argv[1:]) + + data = open(args.input, 'rb').read() + controls = yaml.safe_load(data)['controls'] + + data = generate_py(controls) + + data = fill_template(args.template, data) + + if args.output: + output = open(args.output, 'wb') + output.write(data.encode('utf-8')) + output.close() + else: + sys.stdout.write(data) + + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index e1f5cf21..42988e55 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -17,6 +17,15 @@ pycamera_sources = files([ 'pyenums.cpp', ]) +gen_input_files = [meson.project_source_root() / 'src/libcamera/control_ids.yaml', 'pyenums_generated.cpp.in'] + +generated_sources = custom_target('py_gen_controls', + input : gen_input_files, + output : ['pyenums_generated.cpp'], + command : ['gen-py-control-enums.py', '-o', '@OUTPUT@', '@INPUT@']) + +pycamera_sources += generated_sources + pycamera_deps = [ libcamera_public, py3_dep, diff --git a/src/py/libcamera/pyenums_generated.cpp.in b/src/py/libcamera/pyenums_generated.cpp.in new file mode 100644 index 00000000..96daf257 --- /dev/null +++ b/src/py/libcamera/pyenums_generated.cpp.in @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Tomi Valkeinen + * + * Python bindings + * + * This file is auto-generated. Do not edit. + */ + +#include + +#include + +namespace py = pybind11; + +using namespace libcamera; + +void init_pyenums_generated(py::module& m) +{ +${enums} +} diff --git a/src/py/libcamera/pymain.cpp b/src/py/libcamera/pymain.cpp index 54674caf..81d48a20 100644 --- a/src/py/libcamera/pymain.cpp +++ b/src/py/libcamera/pymain.cpp @@ -115,10 +115,12 @@ static void handleRequestCompleted(Request *req) } void init_pyenums(py::module &m); +void init_pyenums_generated(py::module &m); PYBIND11_MODULE(_libcamera, m) { init_pyenums(m); + init_pyenums_generated(m); /* Forward declarations */