Message ID | 20220623144736.78537-4-tomi.valkeinen@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Quoting Tomi Valkeinen (2022-06-23 15:47:32) > Clean up the py_main.cpp a bit by moving the ControlValue helpers to a > separate file. > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > --- > src/py/libcamera/meson.build | 1 + > src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++ > src/py/libcamera/py_helpers.h | 13 +++++ > src/py/libcamera/py_main.cpp | 83 +--------------------------- > 4 files changed, 114 insertions(+), 81 deletions(-) > create mode 100644 src/py/libcamera/py_helpers.cpp > create mode 100644 src/py/libcamera/py_helpers.h > > diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build > index eb884538..04578bac 100644 > --- a/src/py/libcamera/meson.build > +++ b/src/py/libcamera/meson.build > @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep') > pycamera_sources = files([ > 'py_enums.cpp', > 'py_geometry.cpp', > + 'py_helpers.cpp', Should this be called py_controls? Or do you expect other support code to go in here too. Or maybe it's more about types, 'py_types' .. > 'py_main.cpp', > ]) > > diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp > new file mode 100644 > index 00000000..d0a8b5c4 > --- /dev/null > +++ b/src/py/libcamera/py_helpers.cpp > @@ -0,0 +1,98 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > + */ > + > +#include "py_helpers.h" > + > +#include <libcamera/libcamera.h> > + > +#include <pybind11/functional.h> > +#include <pybind11/smart_holder.h> You have this in the py_helpers header too, so I don't think it needs to be duplicated here. What's it used for? I thought it was just for the Camera destructor or something, I don't see Camera used here ? Anyway, the code move to it's own component file makes sense to me. Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> > +#include <pybind11/stl.h> > +#include <pybind11/stl_bind.h> > + > +namespace py = pybind11; > + > +using namespace libcamera; > + > +template<typename T> > +static py::object valueOrTuple(const ControlValue &cv) > +{ > + if (cv.isArray()) { > + const T *v = reinterpret_cast<const T *>(cv.data().data()); > + auto t = py::tuple(cv.numElements()); > + > + for (size_t i = 0; i < cv.numElements(); ++i) > + t[i] = v[i]; > + > + return std::move(t); > + } > + > + return py::cast(cv.get<T>()); > +} > + > +py::object controlValueToPy(const ControlValue &cv) > +{ > + switch (cv.type()) { > + case ControlTypeBool: > + return valueOrTuple<bool>(cv); > + case ControlTypeByte: > + return valueOrTuple<uint8_t>(cv); > + case ControlTypeInteger32: > + return valueOrTuple<int32_t>(cv); > + case ControlTypeInteger64: > + return valueOrTuple<int64_t>(cv); > + case ControlTypeFloat: > + return valueOrTuple<float>(cv); > + case ControlTypeString: > + return py::cast(cv.get<std::string>()); > + case ControlTypeRectangle: { > + const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); > + return py::cast(v); > + } > + case ControlTypeSize: { > + const Size *v = reinterpret_cast<const Size *>(cv.data().data()); > + return py::cast(v); > + } > + case ControlTypeNone: > + default: > + throw std::runtime_error("Unsupported ControlValue type"); > + } > +} > + > +template<typename T> > +static ControlValue controlValueMaybeArray(const py::object &ob) > +{ > + if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { > + std::vector<T> vec = ob.cast<std::vector<T>>(); > + return ControlValue(Span<const T>(vec)); > + } > + > + return ControlValue(ob.cast<T>()); > +} > + > +ControlValue pyToControlValue(const py::object &ob, ControlType type) > +{ > + switch (type) { > + case ControlTypeBool: > + return ControlValue(ob.cast<bool>()); > + case ControlTypeByte: > + return controlValueMaybeArray<uint8_t>(ob); > + case ControlTypeInteger32: > + return controlValueMaybeArray<int32_t>(ob); > + case ControlTypeInteger64: > + return controlValueMaybeArray<int64_t>(ob); > + case ControlTypeFloat: > + return controlValueMaybeArray<float>(ob); > + case ControlTypeString: > + return ControlValue(ob.cast<std::string>()); > + case ControlTypeRectangle: > + return ControlValue(ob.cast<Rectangle>()); > + case ControlTypeSize: > + return ControlValue(ob.cast<Size>()); > + case ControlTypeNone: > + default: > + throw std::runtime_error("Control type not implemented"); > + } > +} > diff --git a/src/py/libcamera/py_helpers.h b/src/py/libcamera/py_helpers.h > new file mode 100644 > index 00000000..cd31e2cc > --- /dev/null > +++ b/src/py/libcamera/py_helpers.h > @@ -0,0 +1,13 @@ > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > +/* > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > + */ > + > +#pragma once > + > +#include <libcamera/libcamera.h> > + > +#include <pybind11/smart_holder.h> > + > +pybind11::object controlValueToPy(const libcamera::ControlValue &cv); > +libcamera::ControlValue pyToControlValue(const pybind11::object &ob, libcamera::ControlType type); > diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp > index 17b17f60..5a423ece 100644 > --- a/src/py/libcamera/py_main.cpp > +++ b/src/py/libcamera/py_main.cpp > @@ -21,93 +21,14 @@ > #include <pybind11/stl.h> > #include <pybind11/stl_bind.h> > > +#include "py_helpers.h" > + > namespace py = pybind11; > > using namespace libcamera; > > LOG_DEFINE_CATEGORY(Python) > > -template<typename T> > -static py::object valueOrTuple(const ControlValue &cv) > -{ > - if (cv.isArray()) { > - const T *v = reinterpret_cast<const T *>(cv.data().data()); > - auto t = py::tuple(cv.numElements()); > - > - for (size_t i = 0; i < cv.numElements(); ++i) > - t[i] = v[i]; > - > - return std::move(t); > - } > - > - return py::cast(cv.get<T>()); > -} > - > -static py::object controlValueToPy(const ControlValue &cv) > -{ > - switch (cv.type()) { > - case ControlTypeBool: > - return valueOrTuple<bool>(cv); > - case ControlTypeByte: > - return valueOrTuple<uint8_t>(cv); > - case ControlTypeInteger32: > - return valueOrTuple<int32_t>(cv); > - case ControlTypeInteger64: > - return valueOrTuple<int64_t>(cv); > - case ControlTypeFloat: > - return valueOrTuple<float>(cv); > - case ControlTypeString: > - return py::cast(cv.get<std::string>()); > - case ControlTypeRectangle: { > - const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); > - return py::cast(v); > - } > - case ControlTypeSize: { > - const Size *v = reinterpret_cast<const Size *>(cv.data().data()); > - return py::cast(v); > - } > - case ControlTypeNone: > - default: > - throw std::runtime_error("Unsupported ControlValue type"); > - } > -} > - > -template<typename T> > -static ControlValue controlValueMaybeArray(const py::object &ob) > -{ > - if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { > - std::vector<T> vec = ob.cast<std::vector<T>>(); > - return ControlValue(Span<const T>(vec)); > - } > - > - return ControlValue(ob.cast<T>()); > -} > - > -static ControlValue pyToControlValue(const py::object &ob, ControlType type) > -{ > - switch (type) { > - case ControlTypeBool: > - return ControlValue(ob.cast<bool>()); > - case ControlTypeByte: > - return controlValueMaybeArray<uint8_t>(ob); > - case ControlTypeInteger32: > - return controlValueMaybeArray<int32_t>(ob); > - case ControlTypeInteger64: > - return controlValueMaybeArray<int64_t>(ob); > - case ControlTypeFloat: > - return controlValueMaybeArray<float>(ob); > - case ControlTypeString: > - return ControlValue(ob.cast<std::string>()); > - case ControlTypeRectangle: > - return ControlValue(ob.cast<Rectangle>()); > - case ControlTypeSize: > - return ControlValue(ob.cast<Size>()); > - case ControlTypeNone: > - default: > - throw std::runtime_error("Control type not implemented"); > - } > -} > - > static std::weak_ptr<CameraManager> gCameraManager; > static int gEventfd; > static std::mutex gReqlistMutex; > -- > 2.34.1 >
On Fri, Jun 24, 2022 at 09:22:17AM +0100, Kieran Bingham wrote: > Quoting Tomi Valkeinen (2022-06-23 15:47:32) > > Clean up the py_main.cpp a bit by moving the ControlValue helpers to a > > separate file. > > > > Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > > --- > > src/py/libcamera/meson.build | 1 + > > src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++ > > src/py/libcamera/py_helpers.h | 13 +++++ > > src/py/libcamera/py_main.cpp | 83 +--------------------------- > > 4 files changed, 114 insertions(+), 81 deletions(-) > > create mode 100644 src/py/libcamera/py_helpers.cpp > > create mode 100644 src/py/libcamera/py_helpers.h > > > > diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build > > index eb884538..04578bac 100644 > > --- a/src/py/libcamera/meson.build > > +++ b/src/py/libcamera/meson.build > > @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep') > > pycamera_sources = files([ > > 'py_enums.cpp', > > 'py_geometry.cpp', > > + 'py_helpers.cpp', > > Should this be called py_controls? Or do you expect other support code > to go in here too. Or maybe it's more about types, 'py_types' .. > > > 'py_main.cpp', > > ]) > > > > diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp > > new file mode 100644 > > index 00000000..d0a8b5c4 > > --- /dev/null > > +++ b/src/py/libcamera/py_helpers.cpp > > @@ -0,0 +1,98 @@ > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > +/* > > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > > + */ > > + > > +#include "py_helpers.h" > > + > > +#include <libcamera/libcamera.h> > > + > > +#include <pybind11/functional.h> > > +#include <pybind11/smart_holder.h> > > You have this in the py_helpers header too, so I don't think it needs to > be duplicated here. > > What's it used for? I thought it was just for the Camera destructor or > something, I don't see Camera used here ? > > Anyway, the code move to it's own component file makes sense to me. > > > Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > > +#include <pybind11/stl.h> > > +#include <pybind11/stl_bind.h> > > + > > +namespace py = pybind11; > > + > > +using namespace libcamera; > > + > > +template<typename T> > > +static py::object valueOrTuple(const ControlValue &cv) > > +{ > > + if (cv.isArray()) { > > + const T *v = reinterpret_cast<const T *>(cv.data().data()); > > + auto t = py::tuple(cv.numElements()); > > + > > + for (size_t i = 0; i < cv.numElements(); ++i) > > + t[i] = v[i]; > > + > > + return std::move(t); > > + } > > + > > + return py::cast(cv.get<T>()); > > +} > > + > > +py::object controlValueToPy(const ControlValue &cv) > > +{ > > + switch (cv.type()) { > > + case ControlTypeBool: > > + return valueOrTuple<bool>(cv); > > + case ControlTypeByte: > > + return valueOrTuple<uint8_t>(cv); > > + case ControlTypeInteger32: > > + return valueOrTuple<int32_t>(cv); > > + case ControlTypeInteger64: > > + return valueOrTuple<int64_t>(cv); > > + case ControlTypeFloat: > > + return valueOrTuple<float>(cv); > > + case ControlTypeString: > > + return py::cast(cv.get<std::string>()); > > + case ControlTypeRectangle: { > > + const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); > > + return py::cast(v); > > + } > > + case ControlTypeSize: { > > + const Size *v = reinterpret_cast<const Size *>(cv.data().data()); > > + return py::cast(v); > > + } > > + case ControlTypeNone: > > + default: > > + throw std::runtime_error("Unsupported ControlValue type"); > > + } > > +} > > + > > +template<typename T> > > +static ControlValue controlValueMaybeArray(const py::object &ob) > > +{ > > + if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { > > + std::vector<T> vec = ob.cast<std::vector<T>>(); > > + return ControlValue(Span<const T>(vec)); > > + } > > + > > + return ControlValue(ob.cast<T>()); > > +} > > + > > +ControlValue pyToControlValue(const py::object &ob, ControlType type) > > +{ > > + switch (type) { > > + case ControlTypeBool: > > + return ControlValue(ob.cast<bool>()); > > + case ControlTypeByte: > > + return controlValueMaybeArray<uint8_t>(ob); > > + case ControlTypeInteger32: > > + return controlValueMaybeArray<int32_t>(ob); > > + case ControlTypeInteger64: > > + return controlValueMaybeArray<int64_t>(ob); > > + case ControlTypeFloat: > > + return controlValueMaybeArray<float>(ob); > > + case ControlTypeString: > > + return ControlValue(ob.cast<std::string>()); > > + case ControlTypeRectangle: > > + return ControlValue(ob.cast<Rectangle>()); > > + case ControlTypeSize: > > + return ControlValue(ob.cast<Size>()); > > + case ControlTypeNone: > > + default: > > + throw std::runtime_error("Control type not implemented"); > > + } > > +} > > diff --git a/src/py/libcamera/py_helpers.h b/src/py/libcamera/py_helpers.h > > new file mode 100644 > > index 00000000..cd31e2cc > > --- /dev/null > > +++ b/src/py/libcamera/py_helpers.h > > @@ -0,0 +1,13 @@ > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > +/* > > + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> > > + */ > > + > > +#pragma once > > + > > +#include <libcamera/libcamera.h> > > + > > +#include <pybind11/smart_holder.h> > > + > > +pybind11::object controlValueToPy(const libcamera::ControlValue &cv); > > +libcamera::ControlValue pyToControlValue(const pybind11::object &ob, libcamera::ControlType type); > > diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp > > index 17b17f60..5a423ece 100644 > > --- a/src/py/libcamera/py_main.cpp > > +++ b/src/py/libcamera/py_main.cpp > > @@ -21,93 +21,14 @@ > > #include <pybind11/stl.h> > > #include <pybind11/stl_bind.h> > > > > +#include "py_helpers.h" > > + > > namespace py = pybind11; > > > > using namespace libcamera; > > > > LOG_DEFINE_CATEGORY(Python) > > > > -template<typename T> > > -static py::object valueOrTuple(const ControlValue &cv) > > -{ > > - if (cv.isArray()) { > > - const T *v = reinterpret_cast<const T *>(cv.data().data()); > > - auto t = py::tuple(cv.numElements()); > > - > > - for (size_t i = 0; i < cv.numElements(); ++i) > > - t[i] = v[i]; > > - > > - return std::move(t); > > - } > > - > > - return py::cast(cv.get<T>()); > > -} > > - > > -static py::object controlValueToPy(const ControlValue &cv) > > -{ > > - switch (cv.type()) { > > - case ControlTypeBool: > > - return valueOrTuple<bool>(cv); > > - case ControlTypeByte: > > - return valueOrTuple<uint8_t>(cv); > > - case ControlTypeInteger32: > > - return valueOrTuple<int32_t>(cv); > > - case ControlTypeInteger64: > > - return valueOrTuple<int64_t>(cv); > > - case ControlTypeFloat: > > - return valueOrTuple<float>(cv); > > - case ControlTypeString: > > - return py::cast(cv.get<std::string>()); > > - case ControlTypeRectangle: { > > - const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); > > - return py::cast(v); > > - } > > - case ControlTypeSize: { > > - const Size *v = reinterpret_cast<const Size *>(cv.data().data()); > > - return py::cast(v); > > - } > > - case ControlTypeNone: > > - default: > > - throw std::runtime_error("Unsupported ControlValue type"); > > - } > > -} > > - > > -template<typename T> > > -static ControlValue controlValueMaybeArray(const py::object &ob) > > -{ > > - if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { > > - std::vector<T> vec = ob.cast<std::vector<T>>(); > > - return ControlValue(Span<const T>(vec)); > > - } > > - > > - return ControlValue(ob.cast<T>()); > > -} > > - > > -static ControlValue pyToControlValue(const py::object &ob, ControlType type) > > -{ > > - switch (type) { > > - case ControlTypeBool: > > - return ControlValue(ob.cast<bool>()); > > - case ControlTypeByte: > > - return controlValueMaybeArray<uint8_t>(ob); > > - case ControlTypeInteger32: > > - return controlValueMaybeArray<int32_t>(ob); > > - case ControlTypeInteger64: > > - return controlValueMaybeArray<int64_t>(ob); > > - case ControlTypeFloat: > > - return controlValueMaybeArray<float>(ob); > > - case ControlTypeString: > > - return ControlValue(ob.cast<std::string>()); > > - case ControlTypeRectangle: > > - return ControlValue(ob.cast<Rectangle>()); > > - case ControlTypeSize: > > - return ControlValue(ob.cast<Size>()); > > - case ControlTypeNone: > > - default: > > - throw std::runtime_error("Control type not implemented"); > > - } > > -} > > - > > static std::weak_ptr<CameraManager> gCameraManager; > > static int gEventfd; > > static std::mutex gReqlistMutex;
On 24/06/2022 11:22, Kieran Bingham wrote: > Quoting Tomi Valkeinen (2022-06-23 15:47:32) >> Clean up the py_main.cpp a bit by moving the ControlValue helpers to a >> separate file. >> >> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> >> --- >> src/py/libcamera/meson.build | 1 + >> src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++ >> src/py/libcamera/py_helpers.h | 13 +++++ >> src/py/libcamera/py_main.cpp | 83 +--------------------------- >> 4 files changed, 114 insertions(+), 81 deletions(-) >> create mode 100644 src/py/libcamera/py_helpers.cpp >> create mode 100644 src/py/libcamera/py_helpers.h >> >> diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build >> index eb884538..04578bac 100644 >> --- a/src/py/libcamera/meson.build >> +++ b/src/py/libcamera/meson.build >> @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep') >> pycamera_sources = files([ >> 'py_enums.cpp', >> 'py_geometry.cpp', >> + 'py_helpers.cpp', > > Should this be called py_controls? Or do you expect other support code > to go in here too. Or maybe it's more about types, 'py_types' .. I felt that a dedicated file for just these controlvalue related functions is a bit too much, so I thought the file can be a holder of misc small things needed for the bindings. >> 'py_main.cpp', >> ]) >> >> diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp >> new file mode 100644 >> index 00000000..d0a8b5c4 >> --- /dev/null >> +++ b/src/py/libcamera/py_helpers.cpp >> @@ -0,0 +1,98 @@ >> +/* SPDX-License-Identifier: LGPL-2.1-or-later */ >> +/* >> + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> >> + */ >> + >> +#include "py_helpers.h" >> + >> +#include <libcamera/libcamera.h> >> + >> +#include <pybind11/functional.h> >> +#include <pybind11/smart_holder.h> > > You have this in the py_helpers header too, so I don't think it needs to > be duplicated here. Ok. > What's it used for? I thought it was just for the Camera destructor or > something, I don't see Camera used here ? It's the main pybind11 header file, when using the smart_holder branch. Although... Now that I think about it, we're using the "always use smart holder" mode, which probably means we don't need to include smart_holder.h but pybind11.h would be fine. Well, it doesn't really matter here which one we include to get the pybind11::object. Tomi
diff --git a/src/py/libcamera/meson.build b/src/py/libcamera/meson.build index eb884538..04578bac 100644 --- a/src/py/libcamera/meson.build +++ b/src/py/libcamera/meson.build @@ -15,6 +15,7 @@ pybind11_dep = pybind11_proj.get_variable('pybind11_dep') pycamera_sources = files([ 'py_enums.cpp', 'py_geometry.cpp', + 'py_helpers.cpp', 'py_main.cpp', ]) diff --git a/src/py/libcamera/py_helpers.cpp b/src/py/libcamera/py_helpers.cpp new file mode 100644 index 00000000..d0a8b5c4 --- /dev/null +++ b/src/py/libcamera/py_helpers.cpp @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> + */ + +#include "py_helpers.h" + +#include <libcamera/libcamera.h> + +#include <pybind11/functional.h> +#include <pybind11/smart_holder.h> +#include <pybind11/stl.h> +#include <pybind11/stl_bind.h> + +namespace py = pybind11; + +using namespace libcamera; + +template<typename T> +static py::object valueOrTuple(const ControlValue &cv) +{ + if (cv.isArray()) { + const T *v = reinterpret_cast<const T *>(cv.data().data()); + auto t = py::tuple(cv.numElements()); + + for (size_t i = 0; i < cv.numElements(); ++i) + t[i] = v[i]; + + return std::move(t); + } + + return py::cast(cv.get<T>()); +} + +py::object controlValueToPy(const ControlValue &cv) +{ + switch (cv.type()) { + case ControlTypeBool: + return valueOrTuple<bool>(cv); + case ControlTypeByte: + return valueOrTuple<uint8_t>(cv); + case ControlTypeInteger32: + return valueOrTuple<int32_t>(cv); + case ControlTypeInteger64: + return valueOrTuple<int64_t>(cv); + case ControlTypeFloat: + return valueOrTuple<float>(cv); + case ControlTypeString: + return py::cast(cv.get<std::string>()); + case ControlTypeRectangle: { + const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); + return py::cast(v); + } + case ControlTypeSize: { + const Size *v = reinterpret_cast<const Size *>(cv.data().data()); + return py::cast(v); + } + case ControlTypeNone: + default: + throw std::runtime_error("Unsupported ControlValue type"); + } +} + +template<typename T> +static ControlValue controlValueMaybeArray(const py::object &ob) +{ + if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { + std::vector<T> vec = ob.cast<std::vector<T>>(); + return ControlValue(Span<const T>(vec)); + } + + return ControlValue(ob.cast<T>()); +} + +ControlValue pyToControlValue(const py::object &ob, ControlType type) +{ + switch (type) { + case ControlTypeBool: + return ControlValue(ob.cast<bool>()); + case ControlTypeByte: + return controlValueMaybeArray<uint8_t>(ob); + case ControlTypeInteger32: + return controlValueMaybeArray<int32_t>(ob); + case ControlTypeInteger64: + return controlValueMaybeArray<int64_t>(ob); + case ControlTypeFloat: + return controlValueMaybeArray<float>(ob); + case ControlTypeString: + return ControlValue(ob.cast<std::string>()); + case ControlTypeRectangle: + return ControlValue(ob.cast<Rectangle>()); + case ControlTypeSize: + return ControlValue(ob.cast<Size>()); + case ControlTypeNone: + default: + throw std::runtime_error("Control type not implemented"); + } +} diff --git a/src/py/libcamera/py_helpers.h b/src/py/libcamera/py_helpers.h new file mode 100644 index 00000000..cd31e2cc --- /dev/null +++ b/src/py/libcamera/py_helpers.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2022, Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> + */ + +#pragma once + +#include <libcamera/libcamera.h> + +#include <pybind11/smart_holder.h> + +pybind11::object controlValueToPy(const libcamera::ControlValue &cv); +libcamera::ControlValue pyToControlValue(const pybind11::object &ob, libcamera::ControlType type); diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp index 17b17f60..5a423ece 100644 --- a/src/py/libcamera/py_main.cpp +++ b/src/py/libcamera/py_main.cpp @@ -21,93 +21,14 @@ #include <pybind11/stl.h> #include <pybind11/stl_bind.h> +#include "py_helpers.h" + namespace py = pybind11; using namespace libcamera; LOG_DEFINE_CATEGORY(Python) -template<typename T> -static py::object valueOrTuple(const ControlValue &cv) -{ - if (cv.isArray()) { - const T *v = reinterpret_cast<const T *>(cv.data().data()); - auto t = py::tuple(cv.numElements()); - - for (size_t i = 0; i < cv.numElements(); ++i) - t[i] = v[i]; - - return std::move(t); - } - - return py::cast(cv.get<T>()); -} - -static py::object controlValueToPy(const ControlValue &cv) -{ - switch (cv.type()) { - case ControlTypeBool: - return valueOrTuple<bool>(cv); - case ControlTypeByte: - return valueOrTuple<uint8_t>(cv); - case ControlTypeInteger32: - return valueOrTuple<int32_t>(cv); - case ControlTypeInteger64: - return valueOrTuple<int64_t>(cv); - case ControlTypeFloat: - return valueOrTuple<float>(cv); - case ControlTypeString: - return py::cast(cv.get<std::string>()); - case ControlTypeRectangle: { - const Rectangle *v = reinterpret_cast<const Rectangle *>(cv.data().data()); - return py::cast(v); - } - case ControlTypeSize: { - const Size *v = reinterpret_cast<const Size *>(cv.data().data()); - return py::cast(v); - } - case ControlTypeNone: - default: - throw std::runtime_error("Unsupported ControlValue type"); - } -} - -template<typename T> -static ControlValue controlValueMaybeArray(const py::object &ob) -{ - if (py::isinstance<py::list>(ob) || py::isinstance<py::tuple>(ob)) { - std::vector<T> vec = ob.cast<std::vector<T>>(); - return ControlValue(Span<const T>(vec)); - } - - return ControlValue(ob.cast<T>()); -} - -static ControlValue pyToControlValue(const py::object &ob, ControlType type) -{ - switch (type) { - case ControlTypeBool: - return ControlValue(ob.cast<bool>()); - case ControlTypeByte: - return controlValueMaybeArray<uint8_t>(ob); - case ControlTypeInteger32: - return controlValueMaybeArray<int32_t>(ob); - case ControlTypeInteger64: - return controlValueMaybeArray<int64_t>(ob); - case ControlTypeFloat: - return controlValueMaybeArray<float>(ob); - case ControlTypeString: - return ControlValue(ob.cast<std::string>()); - case ControlTypeRectangle: - return ControlValue(ob.cast<Rectangle>()); - case ControlTypeSize: - return ControlValue(ob.cast<Size>()); - case ControlTypeNone: - default: - throw std::runtime_error("Control type not implemented"); - } -} - static std::weak_ptr<CameraManager> gCameraManager; static int gEventfd; static std::mutex gReqlistMutex;
Clean up the py_main.cpp a bit by moving the ControlValue helpers to a separate file. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> --- src/py/libcamera/meson.build | 1 + src/py/libcamera/py_helpers.cpp | 98 +++++++++++++++++++++++++++++++++ src/py/libcamera/py_helpers.h | 13 +++++ src/py/libcamera/py_main.cpp | 83 +--------------------------- 4 files changed, 114 insertions(+), 81 deletions(-) create mode 100644 src/py/libcamera/py_helpers.cpp create mode 100644 src/py/libcamera/py_helpers.h