py: Generate control enums from yaml

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 <tomi.valkeinen@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
Tomi Valkeinen 2022-05-09 13:10:21 +03:00 committed by Kieran Bingham
parent 8aa02271fd
commit 6e92cb9dc4
4 changed files with 130 additions and 0 deletions

View file

@ -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))

View file

@ -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,

View file

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
*
* Python bindings - Auto-generated enums
*
* This file is auto-generated. Do not edit.
*/
#include <libcamera/libcamera.h>
#include <pybind11/smart_holder.h>
namespace py = pybind11;
using namespace libcamera;
void init_pyenums_generated(py::module& m)
{
${enums}
}

View file

@ -137,10 +137,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 */