From patchwork Fri May 6 14:54:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomi Valkeinen X-Patchwork-Id: 15816 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 6792AC326D for ; Fri, 6 May 2022 14:55:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 162B46564E; Fri, 6 May 2022 16:55:17 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1651848917; bh=DvgvXWPQWbX4CVyUuHozOyb5aagpwZHR4TxH96i+zlM=; 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=MijnuOqVDieHLv2JkfNoGyLf56FrjiIuLHnLdVrdmn5gZZeo3iHggYZwVvRD2CQ82 H4ojju2MzR256hhjjkazL67Wj1guQDwQfFMc6640JrAtnREoQa2lHqd/9ql6rAaxSk v/5XOxTBNLaHXcmlWgkEuKel0bEYWxPt9G1chV9GmS+LVToAlh3r1huWi6hFlw9cd5 Vcq+lbO53eyERiB8NxLNuqrx5NAu1L3/p0tiI14Kp+rYjuFcylWLJaAfpOxiKuZNm3 qSUQtTEc2LETKKDn0SgqZkbYJdR/1B2PghwZeTVOTkVFxaLuK7JEfYRLN4+CyiunQu IjrVl1xsckP6Q== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9A49E6564C for ; Fri, 6 May 2022 16:55:12 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="vqxMTxUQ"; 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 EEE86A43; Fri, 6 May 2022 16:55:11 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1651848912; bh=DvgvXWPQWbX4CVyUuHozOyb5aagpwZHR4TxH96i+zlM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vqxMTxUQ3qM4hcK9ebbea/j5uxXsSUhx5pwW0yqDnP1AA7OCgH3MThhmEB5j2afXZ Cecxzwj2JKZEWOTfDilt6Vqqilo/j+ucZa3ayWz1IqT7Ul7vxl1niJ7ssk/hQxwUEf sZGN1RuQX0x1I+JvZYCVa0XmoU147DqCmHmS6cec= To: libcamera-devel@lists.libcamera.org, David Plowman , Kieran Bingham , Laurent Pinchart , Jacopo Mondi Date: Fri, 6 May 2022 17:54:12 +0300 Message-Id: <20220506145414.99039-6-tomi.valkeinen@ideasonboard.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220506145414.99039-1-tomi.valkeinen@ideasonboard.com> References: <20220506145414.99039-1-tomi.valkeinen@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v8 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 e4abc34a..f4c7590c 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 8c3be8f4..aff672aa 100644 --- a/src/py/libcamera/pymain.cpp +++ b/src/py/libcamera/pymain.cpp @@ -131,10 +131,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 */