From patchwork Sat May 7 10:11:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 15825 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 2E8C5C326C for ; Sat, 7 May 2022 10:12:24 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5649B6565D; Sat, 7 May 2022 12:12:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1651918342; bh=6KhgX00/sdi6qbHUgQe4dwPTjt60KVZmG/ufYckdHSk=; 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=x+QJlDLxh8FF308YIFPtXAuDo1oz6/8Y9TyBM58Fxo3GEBkRTYvtRhkDK0V6R0bMK DQc3gOucWwKW+3uVZeXKUMWjM34nDAr1CMRBQqrHbDuieEQiL/2GySvd4x3rHPX5jK Oe694WIRq/f1uqimjcdRH//5ZGqmR4n7IV5IxkoByKH5A4QWqUR8bj/J0Cnp2jedRM tJgZx+vWKc6FtpQLW0m9pzZE/1iUBxSDJNOo/H5jfNrKxYEiWWbn5RCQcMGsASIj3i QuDpXZvscafRixaJ/cuxyRuEKJwkXoKHS81O61KJmW8g1HFP314O6/HBdMFiF34Zd6 XemRJZ1QpVZ2w== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id DAA676564B for ; Sat, 7 May 2022 12:12:17 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Kq2bxYPA"; 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 3895055A; Sat, 7 May 2022 12:12:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1651918337; bh=6KhgX00/sdi6qbHUgQe4dwPTjt60KVZmG/ufYckdHSk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Kq2bxYPAfF4R+AieTHCh1/nJYSC/I6vWV7NwecAjK8HBFFvYGB1XwOLDyK7sH8iZD PdrUyXgJfi9AOCvVaQsHitQ1MrKJhRkifdINVk9GuhSwCE37H0yp/kLhG42Ws0712p OvFI1frjc2s4KcYg2DNsKZhKKN9Ryfb0v+6gq34w= To: libcamera-devel@lists.libcamera.org, David Plowman , Kieran Bingham , Laurent Pinchart , Jacopo Mondi Date: Sat, 7 May 2022 13:11:50 +0300 Message-Id: <20220507101152.31412-6-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220507101152.31412-1-tomi.valkeinen@ideasonboard.com> References: <20220507101152.31412-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v9 5/7] 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 | 12 +++ src/py/libcamera/pyenums_generated.cpp.in | 21 +++++ src/py/libcamera/pymain.cpp | 2 + 4 files changed, 130 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..dcc28b1a --- /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 fce9fd5e..b4ee0171 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -17,6 +17,18 @@ pycamera_sources = files([ 'pymain.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 ee306186..de1e9fd9 100644 --- a/src/py/libcamera/pymain.cpp +++ b/src/py/libcamera/pymain.cpp @@ -130,10 +130,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 */