[PATCH 08/10] utils: codegen: gen-controls.py: Move helper classes to separate file
Dan Scally
dan.scally at ideasonboard.com
Thu Aug 15 00:34:25 CEST 2024
Hi Laurent
On 09/08/2024 01:59, Laurent Pinchart wrote:
> The ControlEnum and Control helper classes defined in gen-controls.py
> are useful for other generator scripts. Move them to a separate file to
> make it possible to share them.
>
> Extend the Python build environment to add the path to the new Python
> module to PYTHONPATH
This doesn't happen in this patch...though given they're in the same directory the import works
anyway, so it isn't causing harm. With the commit message corrected:
Reviewed-by: Daniel Scally <dan.scally at ideasonboard.com>
> , and use it when invoking the gen-controls.py
> script.
>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> include/libcamera/meson.build | 1 +
> src/libcamera/meson.build | 3 +-
> utils/codegen/controls.py | 112 ++++++++++++++++++++++++++++++++++
> utils/codegen/gen-controls.py | 105 +------------------------------
> 4 files changed, 116 insertions(+), 105 deletions(-)
> create mode 100644 utils/codegen/controls.py
>
> diff --git a/include/libcamera/meson.build b/include/libcamera/meson.build
> index d90a8615e52d..a969a95dbf7a 100644
> --- a/include/libcamera/meson.build
> +++ b/include/libcamera/meson.build
> @@ -88,6 +88,7 @@ foreach mode, entry : controls_map
> command : [gen_controls, '-o', '@OUTPUT@',
> '--mode', mode, '-t', template_file,
> '-r', ranges_file, '@INPUT@'],
> + env : py_build_env,
> install : true,
> install_dir : libcamera_headers_install_dir)
> endforeach
> diff --git a/src/libcamera/meson.build b/src/libcamera/meson.build
> index 3fd3a87e9f95..aa9ab0291854 100644
> --- a/src/libcamera/meson.build
> +++ b/src/libcamera/meson.build
> @@ -151,7 +151,8 @@ foreach mode, inout_files : controls_mode_files
> output : output_file,
> command : [gen_controls, '-o', '@OUTPUT@',
> '--mode', mode, '-t', template_file,
> - '-r', ranges_file, '@INPUT@'])
> + '-r', ranges_file, '@INPUT@'],
> + env : py_build_env)
> endforeach
>
> libcamera_public_sources += control_sources
> diff --git a/utils/codegen/controls.py b/utils/codegen/controls.py
> new file mode 100644
> index 000000000000..7bafee599c80
> --- /dev/null
> +++ b/utils/codegen/controls.py
> @@ -0,0 +1,112 @@
> +#!/usr/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +# Copyright (C) 2019, Google Inc.
> +#
> +# Author: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> +#
> +# Helper classes to handle source code generation for libcamera controls
> +
> +
> +class ControlEnum(object):
> + def __init__(self, data):
> + self.__data = data
> +
> + @property
> + def description(self):
> + """The enum description"""
> + return self.__data.get('description')
> +
> + @property
> + def name(self):
> + """The enum name"""
> + return self.__data.get('name')
> +
> + @property
> + def value(self):
> + """The enum value"""
> + return self.__data.get('value')
> +
> +
> +class Control(object):
> + def __init__(self, name, data, vendor):
> + self.__name = name
> + self.__data = data
> + self.__enum_values = None
> + self.__size = None
> + self.__vendor = vendor
> +
> + enum_values = data.get('enum')
> + if enum_values is not None:
> + self.__enum_values = [ControlEnum(enum) for enum in enum_values]
> +
> + size = self.__data.get('size')
> + if size is not None:
> + if len(size) == 0:
> + raise RuntimeError(f'Control `{self.__name}` size must have at least one dimension')
> +
> + # Compute the total number of elements in the array. If any of the
> + # array dimension is a string, the array is variable-sized.
> + num_elems = 1
> + for dim in size:
> + if type(dim) is str:
> + num_elems = 0
> + break
> +
> + dim = int(dim)
> + if dim <= 0:
> + raise RuntimeError(f'Control `{self.__name}` size must have positive values only')
> +
> + num_elems *= dim
> +
> + self.__size = num_elems
> +
> + @property
> + def description(self):
> + """The control description"""
> + return self.__data.get('description')
> +
> + @property
> + def enum_values(self):
> + """The enum values, if the control is an enumeration"""
> + if self.__enum_values is None:
> + return
> + for enum in self.__enum_values:
> + yield enum
> +
> + @property
> + def enum_values_count(self):
> + """The number of enum values, if the control is an enumeration"""
> + if self.__enum_values is None:
> + return 0
> + return len(self.__enum_values)
> +
> + @property
> + def is_enum(self):
> + """Is the control an enumeration"""
> + return self.__enum_values is not None
> +
> + @property
> + def vendor(self):
> + """The vendor string, or None"""
> + return self.__vendor
> +
> + @property
> + def name(self):
> + """The control name (CamelCase)"""
> + return self.__name
> +
> + @property
> + def type(self):
> + typ = self.__data.get('type')
> + size = self.__data.get('size')
> +
> + if typ == 'string':
> + return 'std::string'
> +
> + if self.__size is None:
> + return typ
> +
> + if self.__size:
> + return f"Span<const {typ}, {self.__size}>"
> + else:
> + return f"Span<const {typ}>"
> diff --git a/utils/codegen/gen-controls.py b/utils/codegen/gen-controls.py
> index 685ef7a00d5f..2968eb9a5d4e 100755
> --- a/utils/codegen/gen-controls.py
> +++ b/utils/codegen/gen-controls.py
> @@ -12,110 +12,7 @@ import os
> import sys
> import yaml
>
> -
> -class ControlEnum(object):
> - def __init__(self, data):
> - self.__data = data
> -
> - @property
> - def description(self):
> - """The enum description"""
> - return self.__data.get('description')
> -
> - @property
> - def name(self):
> - """The enum name"""
> - return self.__data.get('name')
> -
> - @property
> - def value(self):
> - """The enum value"""
> - return self.__data.get('value')
> -
> -
> -class Control(object):
> - def __init__(self, name, data, vendor):
> - self.__name = name
> - self.__data = data
> - self.__enum_values = None
> - self.__size = None
> - self.__vendor = vendor
> -
> - enum_values = data.get('enum')
> - if enum_values is not None:
> - self.__enum_values = [ControlEnum(enum) for enum in enum_values]
> -
> - size = self.__data.get('size')
> - if size is not None:
> - if len(size) == 0:
> - raise RuntimeError(f'Control `{self.__name}` size must have at least one dimension')
> -
> - # Compute the total number of elements in the array. If any of the
> - # array dimension is a string, the array is variable-sized.
> - num_elems = 1
> - for dim in size:
> - if type(dim) is str:
> - num_elems = 0
> - break
> -
> - dim = int(dim)
> - if dim <= 0:
> - raise RuntimeError(f'Control `{self.__name}` size must have positive values only')
> -
> - num_elems *= dim
> -
> - self.__size = num_elems
> -
> - @property
> - def description(self):
> - """The control description"""
> - return self.__data.get('description')
> -
> - @property
> - def enum_values(self):
> - """The enum values, if the control is an enumeration"""
> - if self.__enum_values is None:
> - return
> - for enum in self.__enum_values:
> - yield enum
> -
> - @property
> - def enum_values_count(self):
> - """The number of enum values, if the control is an enumeration"""
> - if self.__enum_values is None:
> - return 0
> - return len(self.__enum_values)
> -
> - @property
> - def is_enum(self):
> - """Is the control an enumeration"""
> - return self.__enum_values is not None
> -
> - @property
> - def vendor(self):
> - """The vendor string, or None"""
> - return self.__vendor
> -
> - @property
> - def name(self):
> - """The control name (CamelCase)"""
> - return self.__name
> -
> - @property
> - def type(self):
> - typ = self.__data.get('type')
> - size = self.__data.get('size')
> -
> - if typ == 'string':
> - return 'std::string'
> -
> - if self.__size is None:
> - return typ
> -
> - if self.__size:
> - return f"Span<const {typ}, {self.__size}>"
> - else:
> - return f"Span<const {typ}>"
> +from controls import Control
>
>
> def snake_case(s):
More information about the libcamera-devel
mailing list