[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