[PATCH 08/10] utils: codegen: gen-controls.py: Move helper classes to separate file

Paul Elder paul.elder at ideasonboard.com
Thu Aug 15 06:34:04 CEST 2024


On Thu, Aug 15, 2024 at 01:21:02PM +0900, Paul Elder wrote:
> On Fri, Aug 09, 2024 at 03:59:12AM +0300, 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
> 
> Where is the python build environment being extended?

Oh I see it's in the next patch.


Paul

> 
> > module to PYTHONPATH, 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