summaryrefslogtreecommitdiff
path: root/src/py/libcamera/gen-py-controls.py
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2022-05-27 17:44:29 +0300
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-05-27 22:03:34 +0300
commit3c82ae3821798794873be939bb46c507d4ebde7c (patch)
tree13ec729394b33b59a544bd3afee00ff9b674ab15 /src/py/libcamera/gen-py-controls.py
parent6eb1143e27d284200a672f957c8e5efbf87aafcc (diff)
py: Re-implement controls geneneration
The Python bindings controls generation was not very good. It only covered the enums and they were in the main namespace. This adds the controls somewhat similarly to the C++ side. We will have e.g.: libcamera.controls.Brightness libcamera.controls.AeMeteringModeEnum.CentreWeighted Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/py/libcamera/gen-py-controls.py')
-rwxr-xr-xsrc/py/libcamera/gen-py-controls.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/src/py/libcamera/gen-py-controls.py b/src/py/libcamera/gen-py-controls.py
new file mode 100755
index 00000000..4c072e60
--- /dev/null
+++ b/src/py/libcamera/gen-py-controls.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Generate Python bindings 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()
+
+ if ctrl.get('draft'):
+ ns = 'libcamera::controls::draft::'
+ container = 'draft'
+ else:
+ ns = 'libcamera::controls::'
+ container = 'controls'
+
+ out += f'\t{container}.def_readonly_static("{name}", static_cast<const libcamera::ControlId *>(&{ns}{name}));\n\n'
+
+ enum = ctrl.get('enum')
+ if not enum:
+ continue
+
+ cpp_enum = name + 'Enum'
+
+ out += '\tpy::enum_<{}{}>({}, \"{}\")\n'.format(ns, cpp_enum, container, cpp_enum)
+
+ if name == 'LensShadingMapMode':
+ prefix = 'LensShadingMapMode'
+ elif name == 'SceneFlicker':
+ # If we strip the prefix, we would get '50Hz', which is illegal name
+ prefix = ''
+ 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\n'
+
+ return {'controls': 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))