diff --git a/spa/plugins/libcamera/libcamera-source.cpp b/spa/plugins/libcamera/libcamera-source.cpp index d36acaff6..a983a9de2 100644 --- a/spa/plugins/libcamera/libcamera-source.cpp +++ b/spa/plugins/libcamera/libcamera-source.cpp @@ -742,6 +742,32 @@ uint32_t prop_id_to_control(uint32_t prop_id) return SPA_ID_INVALID; } +[[nodiscard]] +bool control_value_to_pod(spa_pod_builder& b, const libcamera::ControlValue& cv) +{ + if (cv.isArray()) + return false; + + switch (cv.type()) { + case libcamera::ControlTypeBool: { + spa_pod_builder_bool(&b, cv.get()); + break; + } + case libcamera::ControlTypeInteger32: { + spa_pod_builder_int(&b, cv.get()); + break; + } + case libcamera::ControlTypeFloat: { + spa_pod_builder_float(&b, cv.get()); + break; + } + default: + return false; + } + + return true; +} + template [[nodiscard]] std::array control_info_to_range(const libcamera::ControlInfo& cinfo) @@ -775,41 +801,62 @@ spa_pod *control_details_to_pod(spa_pod_builder& b, SPA_PROP_INFO_description, SPA_POD_String(cid.name().c_str()), 0); - switch (cid.type()) { - case ControlTypeBool: { - auto min = cinfo.min().get(); - auto max = cinfo.max().get(); - auto def = !cinfo.def().isNone() - ? cinfo.def().get() - : min; + if (cinfo.values().empty()) { + switch (cid.type()) { + case ControlTypeBool: { + auto min = cinfo.min().get(); + auto max = cinfo.max().get(); + auto def = !cinfo.def().isNone() + ? cinfo.def().get() + : min; + spa_pod_frame f; + + spa_pod_builder_prop(&b, SPA_PROP_INFO_type, 0); + spa_pod_builder_push_choice(&b, &f, SPA_CHOICE_Enum, 0); + spa_pod_builder_bool(&b, def); + spa_pod_builder_bool(&b, min); + if (max != min) + spa_pod_builder_bool(&b, max); + spa_pod_builder_pop(&b, &f); + break; + } + case ControlTypeFloat: { + auto [ min, max, def ] = control_info_to_range(cinfo); + + spa_pod_builder_add(&b, + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( + def, min, max), + 0); + break; + } + case ControlTypeInteger32: { + auto [ min, max, def ] = control_info_to_range(cinfo); + + spa_pod_builder_add(&b, + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int( + def, min, max), + 0); + break; + } + default: + return nullptr; + } + } + else { spa_pod_frame f; spa_pod_builder_prop(&b, SPA_PROP_INFO_type, 0); spa_pod_builder_push_choice(&b, &f, SPA_CHOICE_Enum, 0); - spa_pod_builder_bool(&b, def); - spa_pod_builder_bool(&b, min); - if (max != min) - spa_pod_builder_bool(&b, max); + + if (!control_value_to_pod(b, cinfo.def())) + return nullptr; + + for (const auto& cv : cinfo.values()) { + if (!control_value_to_pod(b, cv)) + return nullptr; + } + spa_pod_builder_pop(&b, &f); - } break; - case ControlTypeFloat: { - auto [ min, max, def ] = control_info_to_range(cinfo); - - spa_pod_builder_add(&b, - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( - def, min, max), - 0); - } break; - case ControlTypeInteger32: { - auto [ min, max, def ] = control_info_to_range(cinfo); - - spa_pod_builder_add(&b, - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int( - def, min, max), - 0); - } break; - default: - return nullptr; } return reinterpret_cast(spa_pod_builder_pop(&b, &f));