libcamera v0.3.2+99-1230f78d
Supporting cameras in Linux since 2019
controls.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * Copyright (C) 2019, Google Inc.
4 *
5 * Control handling
6 */
7
8#pragma once
9
10#include <assert.h>
11#include <map>
12#include <optional>
13#include <set>
14#include <stdint.h>
15#include <string>
16#include <unordered_map>
17#include <vector>
18
20#include <libcamera/base/span.h>
21
22#include <libcamera/geometry.h>
23
24namespace libcamera {
25
26class ControlValidator;
27
36 ControlTypeRectangle,
37 ControlTypeSize,
38 ControlTypePoint,
39};
40
41namespace details {
42
43template<typename T, typename = std::void_t<>>
44struct control_type {
45};
46
47template<>
48struct control_type<void> {
49 static constexpr ControlType value = ControlTypeNone;
50 static constexpr std::size_t size = 0;
51};
52
53template<>
54struct control_type<bool> {
55 static constexpr ControlType value = ControlTypeBool;
56 static constexpr std::size_t size = 0;
57};
58
59template<>
60struct control_type<uint8_t> {
61 static constexpr ControlType value = ControlTypeByte;
62 static constexpr std::size_t size = 0;
63};
64
65template<>
66struct control_type<int32_t> {
67 static constexpr ControlType value = ControlTypeInteger32;
68 static constexpr std::size_t size = 0;
69};
70
71template<>
72struct control_type<int64_t> {
73 static constexpr ControlType value = ControlTypeInteger64;
74 static constexpr std::size_t size = 0;
75};
76
77template<>
78struct control_type<float> {
79 static constexpr ControlType value = ControlTypeFloat;
80 static constexpr std::size_t size = 0;
81};
82
83template<>
84struct control_type<std::string> {
85 static constexpr ControlType value = ControlTypeString;
86 static constexpr std::size_t size = 0;
87};
88
89template<>
90struct control_type<Rectangle> {
91 static constexpr ControlType value = ControlTypeRectangle;
92 static constexpr std::size_t size = 0;
93};
94
95template<>
96struct control_type<Size> {
97 static constexpr ControlType value = ControlTypeSize;
98 static constexpr std::size_t size = 0;
99};
100
101template<>
102struct control_type<Point> {
103 static constexpr ControlType value = ControlTypePoint;
104 static constexpr std::size_t size = 0;
105};
106
107template<typename T, std::size_t N>
108struct control_type<Span<T, N>> : public control_type<std::remove_cv_t<T>> {
109 static constexpr std::size_t size = N;
110};
111
112template<typename T>
113struct control_type<T, std::enable_if_t<std::is_enum_v<T>>> : public control_type<int32_t> {
114};
115
116} /* namespace details */
117
119{
120public:
121 ControlValue();
122
123#ifndef __DOXYGEN__
124 template<typename T, std::enable_if_t<!details::is_span<T>::value &&
125 details::control_type<T>::value &&
126 !std::is_same<std::string, std::remove_cv_t<T>>::value,
127 std::nullptr_t> = nullptr>
128 ControlValue(const T &value)
129 : type_(ControlTypeNone), numElements_(0)
130 {
131 set(details::control_type<std::remove_cv_t<T>>::value, false,
132 &value, 1, sizeof(T));
133 }
134
135 template<typename T, std::enable_if_t<details::is_span<T>::value ||
136 std::is_same<std::string, std::remove_cv_t<T>>::value,
137 std::nullptr_t> = nullptr>
138#else
139 template<typename T>
140#endif
141 ControlValue(const T &value)
142 : type_(ControlTypeNone), numElements_(0)
143 {
144 set(details::control_type<std::remove_cv_t<T>>::value, true,
145 value.data(), value.size(), sizeof(typename T::value_type));
146 }
147
149
150 ControlValue(const ControlValue &other);
151 ControlValue &operator=(const ControlValue &other);
152
153 ControlType type() const { return type_; }
154 bool isNone() const { return type_ == ControlTypeNone; }
155 bool isArray() const { return isArray_; }
156 std::size_t numElements() const { return numElements_; }
157 Span<const uint8_t> data() const;
158 Span<uint8_t> data();
159
160 std::string toString() const;
161
162 bool operator==(const ControlValue &other) const;
163 bool operator!=(const ControlValue &other) const
164 {
165 return !(*this == other);
166 }
167
168#ifndef __DOXYGEN__
169 template<typename T, std::enable_if_t<!details::is_span<T>::value &&
170 !std::is_same<std::string, std::remove_cv_t<T>>::value,
171 std::nullptr_t> = nullptr>
172 T get() const
173 {
174 assert(type_ == details::control_type<std::remove_cv_t<T>>::value);
175 assert(!isArray_);
176
177 return *reinterpret_cast<const T *>(data().data());
178 }
179
180 template<typename T, std::enable_if_t<details::is_span<T>::value ||
181 std::is_same<std::string, std::remove_cv_t<T>>::value,
182 std::nullptr_t> = nullptr>
183#else
184 template<typename T>
185#endif
186 T get() const
187 {
188 assert(type_ == details::control_type<std::remove_cv_t<T>>::value);
189 assert(isArray_);
190
191 using V = typename T::value_type;
192 const V *value = reinterpret_cast<const V *>(data().data());
193 return T{ value, numElements_ };
194 }
195
196#ifndef __DOXYGEN__
197 template<typename T, std::enable_if_t<!details::is_span<T>::value &&
198 !std::is_same<std::string, std::remove_cv_t<T>>::value,
199 std::nullptr_t> = nullptr>
200 void set(const T &value)
201 {
202 set(details::control_type<std::remove_cv_t<T>>::value, false,
203 reinterpret_cast<const void *>(&value), 1, sizeof(T));
204 }
205
206 template<typename T, std::enable_if_t<details::is_span<T>::value ||
207 std::is_same<std::string, std::remove_cv_t<T>>::value,
208 std::nullptr_t> = nullptr>
209#else
210 template<typename T>
211#endif
212 void set(const T &value)
213 {
214 set(details::control_type<std::remove_cv_t<T>>::value, true,
215 value.data(), value.size(), sizeof(typename T::value_type));
216 }
217
218 void reserve(ControlType type, bool isArray = false,
219 std::size_t numElements = 1);
220
221private:
222 ControlType type_ : 8;
223 bool isArray_;
224 std::size_t numElements_ : 32;
225 union {
226 uint64_t value_;
227 void *storage_;
228 };
229
230 void release();
231 void set(ControlType type, bool isArray, const void *data,
232 std::size_t numElements, std::size_t elementSize);
233};
234
236{
237public:
238 ControlId(unsigned int id, const std::string &name, const std::string &vendor,
239 ControlType type, std::size_t size = 0,
240 const std::map<std::string, int32_t> &enumStrMap = {});
241
242 unsigned int id() const { return id_; }
243 const std::string &name() const { return name_; }
244 const std::string &vendor() const { return vendor_; }
245 ControlType type() const { return type_; }
246 bool isArray() const { return size_ > 0; }
247 std::size_t size() const { return size_; }
248 const std::map<int32_t, std::string> &enumerators() const { return reverseMap_; }
249
250private:
252
253 unsigned int id_;
254 std::string name_;
255 std::string vendor_;
256 ControlType type_;
257 std::size_t size_;
258 std::map<std::string, int32_t> enumStrMap_;
259 std::map<int32_t, std::string> reverseMap_;
260};
261
262static inline bool operator==(unsigned int lhs, const ControlId &rhs)
263{
264 return lhs == rhs.id();
265}
266
267static inline bool operator!=(unsigned int lhs, const ControlId &rhs)
268{
269 return !(lhs == rhs);
270}
271
272static inline bool operator==(const ControlId &lhs, unsigned int rhs)
273{
274 return lhs.id() == rhs;
275}
276
277static inline bool operator!=(const ControlId &lhs, unsigned int rhs)
278{
279 return !(lhs == rhs);
280}
281
282template<typename T>
283class Control : public ControlId
284{
285public:
286 using type = T;
287
288 Control(unsigned int id, const char *name, const char *vendor,
289 const std::map<std::string, int32_t> &enumStrMap = {})
290 : ControlId(id, name, vendor, details::control_type<std::remove_cv_t<T>>::value,
291 details::control_type<std::remove_cv_t<T>>::size, enumStrMap)
292 {
293 }
294
295private:
297};
298
300{
301public:
302 explicit ControlInfo(const ControlValue &min = {},
303 const ControlValue &max = {},
304 const ControlValue &def = {});
305 explicit ControlInfo(Span<const ControlValue> values,
306 const ControlValue &def = {});
307 explicit ControlInfo(std::set<bool> values, bool def);
308 explicit ControlInfo(bool value);
309
310 const ControlValue &min() const { return min_; }
311 const ControlValue &max() const { return max_; }
312 const ControlValue &def() const { return def_; }
313 const std::vector<ControlValue> &values() const { return values_; }
314
315 std::string toString() const;
316
317 bool operator==(const ControlInfo &other) const
318 {
319 return min_ == other.min_ && max_ == other.max_;
320 }
321
322 bool operator!=(const ControlInfo &other) const
323 {
324 return !(*this == other);
325 }
326
327private:
328 ControlValue min_;
329 ControlValue max_;
330 ControlValue def_;
331 std::vector<ControlValue> values_;
332};
333
334using ControlIdMap = std::unordered_map<unsigned int, const ControlId *>;
335
336class ControlInfoMap : private std::unordered_map<const ControlId *, ControlInfo>
337{
338public:
339 using Map = std::unordered_map<const ControlId *, ControlInfo>;
340
341 ControlInfoMap() = default;
342 ControlInfoMap(const ControlInfoMap &other) = default;
343 ControlInfoMap(std::initializer_list<Map::value_type> init,
344 const ControlIdMap &idmap);
345 ControlInfoMap(Map &&info, const ControlIdMap &idmap);
346
347 ControlInfoMap &operator=(const ControlInfoMap &other) = default;
348
349 using Map::key_type;
350 using Map::mapped_type;
351 using Map::value_type;
352 using Map::size_type;
353 using Map::iterator;
354 using Map::const_iterator;
355
356 using Map::begin;
357 using Map::cbegin;
358 using Map::end;
359 using Map::cend;
360 using Map::at;
361 using Map::empty;
362 using Map::size;
363 using Map::count;
364 using Map::find;
365
366 mapped_type &at(unsigned int key);
367 const mapped_type &at(unsigned int key) const;
368 size_type count(unsigned int key) const;
369 iterator find(unsigned int key);
370 const_iterator find(unsigned int key) const;
371
372 const ControlIdMap &idmap() const { return *idmap_; }
373
374private:
375 bool validate();
376
377 const ControlIdMap *idmap_ = nullptr;
378};
379
381{
382private:
383 using ControlListMap = std::unordered_map<unsigned int, ControlValue>;
384
385public:
386 enum class MergePolicy {
387 KeepExisting = 0,
388 OverwriteExisting,
389 };
390
391 ControlList();
392 ControlList(const ControlIdMap &idmap, const ControlValidator *validator = nullptr);
393 ControlList(const ControlInfoMap &infoMap, const ControlValidator *validator = nullptr);
394
395 using iterator = ControlListMap::iterator;
396 using const_iterator = ControlListMap::const_iterator;
397
398 iterator begin() { return controls_.begin(); }
399 iterator end() { return controls_.end(); }
400 const_iterator begin() const { return controls_.begin(); }
401 const_iterator end() const { return controls_.end(); }
402
403 bool empty() const { return controls_.empty(); }
404 std::size_t size() const { return controls_.size(); }
405
406 void clear() { controls_.clear(); }
407 void merge(const ControlList &source, MergePolicy policy = MergePolicy::KeepExisting);
408
409 bool contains(unsigned int id) const;
410
411 template<typename T>
412 std::optional<T> get(const Control<T> &ctrl) const
413 {
414 const auto entry = controls_.find(ctrl.id());
415 if (entry == controls_.end())
416 return std::nullopt;
417
418 const ControlValue &val = entry->second;
419 return val.get<T>();
420 }
421
422 template<typename T, typename V>
423 void set(const Control<T> &ctrl, const V &value)
424 {
425 ControlValue *val = find(ctrl.id());
426 if (!val)
427 return;
428
429 val->set<T>(value);
430 }
431
432 template<typename T, typename V, size_t Size>
433 void set(const Control<Span<T, Size>> &ctrl, const std::initializer_list<V> &value)
434 {
435 ControlValue *val = find(ctrl.id());
436 if (!val)
437 return;
438
439 val->set(Span<const typename std::remove_cv_t<V>, Size>{ value.begin(), value.size() });
440 }
441
442 const ControlValue &get(unsigned int id) const;
443 void set(unsigned int id, const ControlValue &value);
444
445 const ControlInfoMap *infoMap() const { return infoMap_; }
446 const ControlIdMap *idMap() const { return idmap_; }
447
448private:
449 const ControlValue *find(unsigned int id) const;
450 ControlValue *find(unsigned int id);
451
452 const ControlValidator *validator_;
453 const ControlIdMap *idmap_;
454 const ControlInfoMap *infoMap_;
455
456 ControlListMap controls_;
457};
458
459} /* namespace libcamera */
Utilities to help constructing class interfaces.
#define LIBCAMERA_DISABLE_COPY_AND_MOVE(klass)
Disable copy and move construction and assignment of the klass.
Control static metadata.
Definition: controls.h:236
ControlId(unsigned int id, const std::string &name, const std::string &vendor, ControlType type, std::size_t size=0, const std::map< std::string, int32_t > &enumStrMap={})
Construct a ControlId instance.
Definition: controls.cpp:402
const std::map< int32_t, std::string > & enumerators() const
Retrieve the map of enum values to enum names.
Definition: controls.h:248
ControlType type() const
Retrieve the control data type.
Definition: controls.h:245
const std::string & vendor() const
Retrieve the vendor name.
Definition: controls.h:244
bool isArray() const
Determine if the control is an array control.
Definition: controls.h:246
const std::string & name() const
Retrieve the control name.
Definition: controls.h:243
std::size_t size() const
Retrieve the size of the control if it is an array control.
Definition: controls.h:247
unsigned int id() const
Retrieve the control numerical ID.
Definition: controls.h:242
A map of ControlId to ControlInfo.
Definition: controls.h:337
mapped_type & at(unsigned int key)
Access specified element by numerical ID.
Definition: controls.cpp:768
const ControlIdMap & idmap() const
Retrieve the ControlId map.
Definition: controls.h:372
ControlInfoMap & operator=(const ControlInfoMap &other)=default
Copy assignment operator, replace the contents with a copy of other.
std::unordered_map< const ControlId *, ControlInfo > Map
The base std::unsorted_map<> container.
Definition: controls.h:339
iterator find(unsigned int key)
Find the element matching a numerical ID.
Definition: controls.cpp:811
ControlInfoMap(const ControlInfoMap &other)=default
Copy constructor, construct a ControlInfoMap from a copy of other.
size_type count(unsigned int key) const
Count the number of elements matching a numerical ID.
Definition: controls.cpp:792
Describe the limits of valid values for a Control.
Definition: controls.h:300
const std::vector< ControlValue > & values() const
Retrieve the list of valid values.
Definition: controls.h:313
std::string toString() const
Provide a string representation of the ControlInfo.
Definition: controls.cpp:633
ControlInfo(const ControlValue &min={}, const ControlValue &max={}, const ControlValue &def={})
Construct a ControlInfo with minimum and maximum range parameters.
Definition: controls.cpp:533
bool operator==(const ControlInfo &other) const
Compare ControlInfo instances for equality.
Definition: controls.h:317
bool operator!=(const ControlInfo &other) const
Compare ControlInfo instances for non equality.
Definition: controls.h:322
const ControlValue & max() const
Retrieve the maximum value of the control.
Definition: controls.h:311
const ControlValue & def() const
Retrieve the default value of the control.
Definition: controls.h:312
const ControlValue & min() const
Retrieve the minimum value of the control.
Definition: controls.h:310
Associate a list of ControlId with their values for an object.
Definition: controls.h:381
void merge(const ControlList &source, MergePolicy policy=MergePolicy::KeepExisting)
Merge the source into the ControlList.
Definition: controls.cpp:983
void clear()
Removes all controls from the list.
Definition: controls.h:406
const ControlInfoMap * infoMap() const
Retrieve the ControlInfoMap used to construct the ControlList.
Definition: controls.h:445
const ControlIdMap * idMap() const
Retrieve the ControlId map used to construct the ControlList.
Definition: controls.h:446
void set(const Control< Span< T, Size > > &ctrl, const std::initializer_list< V > &value)
Definition: controls.h:433
ControlListMap::const_iterator const_iterator
Const iterator for the controls contained within the list.
Definition: controls.h:396
iterator end()
Retrieve an iterator pointing to the past-the-end control in the list.
Definition: controls.h:399
MergePolicy
The policy used by the merge function.
Definition: controls.h:386
@ KeepExisting
Existing controls in the target list are kept.
std::size_t size() const
Retrieve the number of controls in the list.
Definition: controls.h:404
ControlListMap::iterator iterator
Iterator for the controls contained within the list.
Definition: controls.h:395
std::optional< T > get(const Control< T > &ctrl) const
Get the value of control ctrl.
Definition: controls.h:412
bool empty() const
Identify if the list is empty.
Definition: controls.h:403
void set(const Control< T > &ctrl, const V &value)
Set the control ctrl value to value.
Definition: controls.h:423
iterator begin()
Retrieve an iterator to the first Control in the list.
Definition: controls.h:398
bool contains(unsigned int id) const
Check if the list contains a control with the specified id.
Definition: controls.cpp:1015
const_iterator begin() const
Retrieve a const_iterator to the first Control in the list.
Definition: controls.h:400
ControlList()
Construct a ControlList not associated with any object.
Definition: controls.cpp:871
const_iterator end() const
Retrieve a const iterator pointing to the past-the-end control in the list.
Definition: controls.h:401
Interface for the control validator.
Definition: control_validator.h:17
Abstract type representing the value of a control.
Definition: controls.h:119
T get() const
Get the control value.
Definition: controls.h:186
bool isArray() const
Determine if the value stores an array.
Definition: controls.h:155
ControlValue & operator=(const ControlValue &other)
Replace the content of the ControlValue with a copy of the content of other.
Definition: controls.cpp:146
void reserve(ControlType type, bool isArray=false, std::size_t numElements=1)
Set the control type and reserve memory.
Definition: controls.cpp:360
bool operator==(const ControlValue &other) const
Compare ControlValue instances for equality.
Definition: controls.cpp:284
void set(const T &value)
Set the control value to value.
Definition: controls.h:212
ControlValue()
Construct an empty ControlValue.
Definition: controls.cpp:98
bool operator!=(const ControlValue &other) const
Compare ControlValue instances for non equality.
Definition: controls.h:163
ControlValue(const T &value)
Construct a ControlValue of type T.
Definition: controls.h:141
ControlType type() const
Retrieve the data type of the value.
Definition: controls.h:153
std::string toString() const
Assemble and return a string describing the value.
Definition: controls.cpp:208
bool isNone() const
Determine if the value is not initialised.
Definition: controls.h:154
std::size_t numElements() const
Retrieve the number of elements stored in the ControlValue.
Definition: controls.h:156
Span< const uint8_t > data() const
Retrieve the raw data of a control value.
Definition: controls.cpp:186
Describe a control and its intrinsic properties.
Definition: controls.h:284
T type
The Control template type T.
Definition: controls.h:286
Control(unsigned int id, const char *name, const char *vendor, const std::map< std::string, int32_t > &enumStrMap={})
Construct a Control instance.
Definition: controls.h:288
Describe a two-dimensional size.
Definition: geometry.h:53
Data structures related to geometric objects.
Top-level libcamera namespace.
Definition: backtrace.h:17
ControlType
Define the data type of a Control.
Definition: controls.h:28
@ ControlTypeNone
Definition: controls.h:29
@ ControlTypeFloat
Definition: controls.h:34
@ ControlTypeBool
Definition: controls.h:30
@ ControlTypeInteger32
Definition: controls.h:32
@ ControlTypeString
Definition: controls.h:35
@ ControlTypeInteger64
Definition: controls.h:33
@ ControlTypeByte
Definition: controls.h:31
std::unordered_map< unsigned int, const ControlId * > ControlIdMap
A map of numerical control ID to ControlId.
Definition: controls.h:334
bool operator==(const ColorSpace &lhs, const ColorSpace &rhs)
Compare color spaces for equality.
Definition: color_space.cpp:506