/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. * * controls.h - Control handling */ #ifndef __LIBCAMERA_CONTROLS_H__ #define __LIBCAMERA_CONTROLS_H__ #include #include #include #include #include #include #include #include #include namespace libcamera { class ControlValidator; enum ControlType { ControlTypeNone, ControlTypeBool, ControlTypeByte, ControlTypeInteger32, ControlTypeInteger64, ControlTypeFloat, ControlTypeString, ControlTypeRectangle, ControlTypeSize, }; namespace details { template struct control_type { }; template<> struct control_type { static constexpr ControlType value = ControlTypeNone; }; template<> struct control_type { static constexpr ControlType value = ControlTypeBool; }; template<> struct control_type { static constexpr ControlType value = ControlTypeByte; }; template<> struct control_type { static constexpr ControlType value = ControlTypeInteger32; }; template<> struct control_type { static constexpr ControlType value = ControlTypeInteger64; }; template<> struct control_type { static constexpr ControlType value = ControlTypeFloat; }; template<> struct control_type { static constexpr ControlType value = ControlTypeString; }; template<> struct control_type { static constexpr ControlType value = ControlTypeRectangle; }; template<> struct control_type { static constexpr ControlType value = ControlTypeSize; }; template struct control_type> : public control_type> { }; } /* namespace details */ class ControlValue { public: ControlValue(); #ifndef __DOXYGEN__ template::value && details::control_type::value && !std::is_same>::value, std::nullptr_t> = nullptr> ControlValue(const T &value) : type_(ControlTypeNone), numElements_(0) { set(details::control_type>::value, false, &value, 1, sizeof(T)); } template::value || std::is_same>::value, std::nullptr_t> = nullptr> #else template #endif ControlValue(const T &value) : type_(ControlTypeNone), numElements_(0) { set(details::control_type>::value, true, value.data(), value.size(), sizeof(typename T::value_type)); } ~ControlValue(); ControlValue(const ControlValue &other); ControlValue &operator=(const ControlValue &other); ControlType type() const { return type_; } bool isNone() const { return type_ == ControlTypeNone; } bool isArray() const { return isArray_; } std::size_t numElements() const { return numElements_; } Span data() const; Span data(); std::string toString() const; bool operator==(const ControlValue &other) const; bool operator!=(const ControlValue &other) const { return !(*this == other); } #ifndef __DOXYGEN__ template::value && !std::is_same>::value, std::nullptr_t> = nullptr> T get() const { assert(type_ == details::control_type>::value); assert(!isArray_); return *reinterpret_cast(data().data()); } template::value || std::is_same>::value, std::nullptr_t> = nullptr> #else template #endif T get() const { assert(type_ == details::control_type>::value); assert(isArray_); using V = typename T::value_type; const V *value = reinterpret_cast(data().data()); return { value, numElements_ }; } #ifndef __DOXYGEN__ template::value && !std::is_same>::value, std::nullptr_t> = nullptr> void set(const T &value) { set(details::control_type>::value, false, reinterpret_cast(&value), 1, sizeof(T)); } template::value || std::is_same>::value, std::nullptr_t> = nullptr> #else template #endif void set(const T &value) { set(details::control_type>::value, true, value.data(), value.size(), sizeof(typename T::value_type)); } void reserve(ControlType type, bool isArray = false, std::size_t numElements = 1); private: ControlType type_ : 8; bool isArray_; std::size_t numElements_ : 32; union { uint64_t value_; void *storage_; }; void release(); void set(ControlType type, bool isArray, const void *data, std::size_t numElements, std::size_t elementSize); }; class ControlId { public: ControlId(unsigned int id, const std::string &name, ControlType type) : id_(id), name_(name), type_(type) { } unsigned int id() const { return id_; } const std::string &name() const { return name_; } ControlType type() const { return type_; } private: LIBCAMERA_DISABLE_COPY_AND_MOVE(ControlId) unsigned int id_; std::string name_; ControlType type_; }; static inline bool operator==(unsigned int lhs, const ControlId &rhs) { return lhs == rhs.id(); } static inline bool operator!=(unsigned int lhs, const ControlId &rhs) { return !(lhs == rhs); } static inline bool operator==(const ControlId &lhs, unsigned int rhs) { return lhs.id() == rhs; } static inline bool operator!=(const ControlId &lhs, unsigned int rhs) { return !(lhs == rhs); } template class Control : public ControlId { public: using type = T; Control(unsigned int id, const char *name) : ControlId(id, name, details::control_type>::value) { } private: LIBCAMERA_DISABLE_COPY_AND_MOVE(Control) }; class ControlInfo { public: explicit ControlInfo(const ControlValue &min = 0, const ControlValue &max = 0, const ControlValue &def = 0); explicit ControlInfo(Span values, const ControlValue &def = {}); explicit ControlInfo(std::set values, bool def); explicit ControlInfo(bool value); const ControlValue &min() const { return min_; } const ControlValue &max() const { return max_; } const ControlValue &def() const { return def_; } const std::vector &values() const { return values_; } std::string toString() const; bool operator==(const ControlInfo &other) const { return min_ == other.min_ && max_ == other.max_; } bool operator!=(const ControlInfo &other) const { return !(*this == other); } private: ControlValue min_; ControlValue max_; ControlValue def_; std::vector values_; }; using ControlIdMap = std::unordered_map; class ControlInfoMap : private std::unordered_map { public: using Map = std::unordered_map; ControlInfoMap() = default; ControlInfoMap(const ControlInfoMap &other) = default; ControlInfoMap(std::initializer_list init); ControlInfoMap(Map &&info); ControlInfoMap &operator=(const ControlInfoMap &other) = default; ControlInfoMap &operator=(std::initializer_list init); ControlInfoMap &operator=(Map &&info); using Map::key_type; using Map::mapped_type; using Map::value_type; using Map::size_type; using Map::iterator; using Map::const_iterator; using Map::begin; using Map::cbegin; using Map::end; using Map::cend; using Map::at; using Map::empty; using Map::size; using Map::count; using Map::find; mapped_type &at(unsigned int key); const mapped_type &at(unsigned int key) const; size_type count(unsigned int key) const; iterator find(unsigned int key); const_iterator find(unsigned int key) const; const ControlIdMap &idmap() const { return idmap_; } private: void generateIdmap(); ControlIdMap idmap_; }; class ControlList { private: using ControlListMap = std::unordered_map; public: ControlList(); ControlList(const ControlIdMap &idmap, ControlValidator *validator = nullptr); ControlList(const ControlInfoMap &infoMap, ControlValidator *validator = nullptr); using iterator = ControlListMap::iterator; using const_iterator = ControlListMap::const_iterator; iterator begin() { return controls_.begin(); } iterator end() { return controls_.end(); } const_iterator begin() const { return controls_.begin(); } const_iterator end() const { return controls_.end(); } bool empty() const { return controls_.empty(); } std::size_t size() const { return controls_.size(); } void clear() { controls_.clear(); } void merge(const ControlList &source); bool contains(const ControlId &id) const; bool contains(unsigned int id) const; template T get(const Control &ctrl) const { const ControlValue *val = find(ctrl.id()); if (!val) return T{}; return val->get(); } template void set(const Control &ctrl, const V &value) { ControlValue *val = find(ctrl.id()); if (!val) return; val->set(value); } template void set(const Control &ctrl, const std::initializer_list &value) { ControlValue *val = find(ctrl.id()); if (!val) return; val->set(Span>{ value.begin(), value.size() }); } const ControlValue &get(unsigned int id) const; void set(unsigned int id, const ControlValue &value); const ControlInfoMap *infoMap() const { return infoMap_; } private: const ControlValue *find(unsigned int id) const; ControlValue *find(unsigned int id); ControlValidator *validator_; const ControlIdMap *idmap_; const ControlInfoMap *infoMap_; ControlListMap controls_; }; } /* namespace libcamera */ #endif /* __LIBCAMERA_CONTROLS_H__ */