Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 63 additions & 52 deletions device/libcamera/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,20 @@ static const std::map<unsigned, std::string> *libcamera_find_control_ids(unsigne
return &iter->second.enum_values;
}

static long long libcamera_find_control_id_named_value(unsigned control_id, const char *name)
static std::pair<long long, const char*> libcamera_find_control_id_named_value(unsigned control_id, const char *value)
{
auto named_values = libcamera_find_control_ids(control_id);
if (named_values) {
for (const auto & named_value : *named_values) {
if (device_option_is_equal(named_value.second.c_str(), name))
return named_value.first;
if (device_option_is_equal(named_value.second.c_str(), value)) {
return std::make_pair(named_value.first, value + named_value.second.length());
}
}
}

return strtoll(name, NULL, 10);
char *endptr = NULL;
auto res = strtoll(value, &endptr, 10);
return std::make_pair(res, endptr);
}

static libcamera::ControlInfoMap::Map libcamera_control_list(device_t *dev)
Expand Down Expand Up @@ -140,9 +143,9 @@ void libcamera_device_dump_options(device_t *dev, FILE *stream)
auto control_key = libcamera_device_option_normalize(control_id->name());
auto control_info = control.second;

fprintf(stream, "- available option: %s (%08x, type=%s): %s\n",
fprintf(stream, "- available option: %s (%08x, type=%s%s): %s\n",
control_id->name().c_str(), control_id->id(),
control_type_values[control_id->type()].c_str(),
control_type_values[control_id->type()].c_str(), control_id->isArray() ? " Array" : "",
control_info.toString().c_str());

auto named_values = libcamera_find_control_ids(control_id->id());
Expand Down Expand Up @@ -321,101 +324,105 @@ int libcamera_device_dump_options2(device_t *dev, device_option_fn fn, void *opa
return n;
}

static libcamera::Rectangle libcamera_parse_rectangle(const char *value)
static std::pair<float, const char*> libcamera_parse_float(const char *value)
{
char *endptr = NULL;
auto res = strtof(value, &endptr);
return std::make_pair(res, endptr);
}

static std::pair<libcamera::Rectangle, const char*> libcamera_parse_rectangle(const char *value)
{
static const char *RECTANGLE_PATTERNS[] =
{
"(%d,%d)/%ux%u",
"%d,%d,%u,%u",
"(%d,%d)/%ux%u%n",
"%d,%d,%u,%u%n",
NULL
};

for (int i = 0; RECTANGLE_PATTERNS[i]; i++) {
libcamera::Rectangle rectangle;
int read = 0;

if (4 == sscanf(value, RECTANGLE_PATTERNS[i],
&rectangle.x, &rectangle.y,
&rectangle.width, &rectangle.height)) {
return rectangle;
&rectangle.width, &rectangle.height, &read)) {
return std::make_pair(rectangle, value + read);
}
}

return libcamera::Rectangle();
return std::make_pair(libcamera::Rectangle(), (const char*)NULL);
}

static libcamera::Size libcamera_parse_size(const char *value)
static std::pair<libcamera::Size, const char*> libcamera_parse_size(const char *value)
{
static const char *SIZE_PATTERNS[] =
{
"%ux%u",
"%u,%u",
"%ux%u%n",
"%u,%u%n",
NULL
};

for (int i = 0; SIZE_PATTERNS[i]; i++) {
libcamera::Size size;
int read = 0;

if (2 == sscanf(value, SIZE_PATTERNS[i], &size.width, &size.height)) {
return size;
if (2 == sscanf(value, SIZE_PATTERNS[i], &size.width, &size.height, &read)) {
return std::make_pair(size, value + read);
}
}

return libcamera::Size();
return std::make_pair(libcamera::Size(), (const char*)NULL);
}

#if LIBCAMERA_VERSION_MAJOR == 0 && LIBCAMERA_VERSION_MINOR > 3 && LIBCAMERA_VERSION_PATCH >= 2 // Support for older libcamera versions
static libcamera::Point libcamera_parse_point(const char *value)
{
static const char *POINT_PATTERNS[] =
{
"(%d,%d)",
"%d,%d",
"(%d,%d)%n",
"%d,%d%n",
NULL
};

for (int i = 0; POINT_PATTERNS[i]; i++) {
libcamera::Point point;
int read = 0;

if (2 == sscanf(value, POINT_PATTERNS[i],
&point.x, &point.y)) {
return point;
&point.x, &point.y, &read)) {
return std::make_pair(point, value + read);
}
}

return libcamera::Point();
return std::make_pair(libcamera::Point(), NULL);
}
#endif

template<typename T, typename F>
static bool libcamera_parse_control_value(libcamera::ControlValue &control_value, const char *value, const F &fn)
static bool libcamera_parse_control_value(libcamera::ControlValue &control_value, bool control_array, const char *value, const F& fn)
{
std::vector<T> parsed;
std::vector<T> items;

while (value && *value) {
std::string current_value;

if (const char *next = strchr(value, ',')) {
current_value.assign(value, next);
value = &next[1];
} else {
current_value.assign(value);
value = NULL;
}

if (current_value.empty())
continue;

parsed.push_back(fn(current_value.c_str()));
auto [item, next] = fn(value);
if (!next)
return false; // failed to parse
items.push_back(item);

if (!*next)
break; // reached end of elements
if (*next != ',')
return false; // expected comma to split items
value = next;
}

if (parsed.empty()) {
if (items.empty()) {
return false;
}

if (parsed.size() > 1) {
control_value.set<libcamera::Span<T> >(parsed);
} else if (control_array) {
control_value.set<libcamera::Span<T> >(items);
} else {
control_value.set<T>(parsed[0]);
control_value.set<T>(items[0]);
}

return true;
Expand All @@ -433,42 +440,46 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val
continue;

libcamera::ControlValue control_value;
bool control_array = control_id->isArray();

switch (control_id->type()) {
case libcamera::ControlTypeNone:
break;

case libcamera::ControlTypeBool:
if (control_array) {
throw std::runtime_error("Array ControlType for boolean is not supported");
}
control_value.set<bool>(atoi(value));
break;

case libcamera::ControlTypeByte:
libcamera_parse_control_value<unsigned char>(control_value, value,
libcamera_parse_control_value<unsigned char>(control_value, control_array, value,
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
break;

case libcamera::ControlTypeInteger32:
libcamera_parse_control_value<int32_t>(control_value, value,
libcamera_parse_control_value<int32_t>(control_value, control_array, value,
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
break;

case libcamera::ControlTypeInteger64:
libcamera_parse_control_value<int64_t>(control_value, value,
libcamera_parse_control_value<int64_t>(control_value, control_array, value,
[control_id](const char *value) { return libcamera_find_control_id_named_value(control_id->id(), value); });
break;

case libcamera::ControlTypeFloat:
libcamera_parse_control_value<float>(control_value, value, atof);
libcamera_parse_control_value<float>(control_value, control_array, value, libcamera_parse_float);
break;

case libcamera::ControlTypeRectangle:
libcamera_parse_control_value<libcamera::Rectangle>(
control_value, value, libcamera_parse_rectangle);
control_value, control_array, value, libcamera_parse_rectangle);
break;

case libcamera::ControlTypeSize:
libcamera_parse_control_value<libcamera::Size>(
control_value, value, libcamera_parse_size);
control_value, control_array, value, libcamera_parse_size);
break;

case libcamera::ControlTypeString:
Expand All @@ -477,7 +488,7 @@ int libcamera_device_set_option(device_t *dev, const char *keyp, const char *val
#if LIBCAMERA_VERSION_MAJOR == 0 && LIBCAMERA_VERSION_MINOR > 3 && LIBCAMERA_VERSION_PATCH >= 2 // Support for older libcamera versions
case libcamera::ControlTypePoint:
libcamera_parse_control_value<libcamera::Point>(
control_value, value, libcamera_parse_point);
control_value, control_array, value, libcamera_parse_point);
break;
#endif

Expand Down
Loading