From 5ebbe093711a9e133a3276e331dd0f5ef4e7d5a7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 18 Jan 2022 10:38:11 +0100 Subject: [PATCH] pw-cli: move json to pod code to SPA --- spa/include/spa/utils/json-pod.h | 191 +++++++++++++++++++++++++++++++ src/tools/pw-cli.c | 128 +-------------------- 2 files changed, 197 insertions(+), 122 deletions(-) create mode 100644 spa/include/spa/utils/json-pod.h diff --git a/spa/include/spa/utils/json-pod.h b/spa/include/spa/utils/json-pod.h new file mode 100644 index 000000000..18acb1149 --- /dev/null +++ b/spa/include/spa/utils/json-pod.h @@ -0,0 +1,191 @@ +/* Simple Plugin API + * + * Copyright © 2022 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_UTILS_JSON_POD_H +#define SPA_UTILS_JSON_POD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +/** \defgroup spa_json_pod JSON to POD + * JSON to POD conversion + */ + +/** + * \addtogroup spa_json_pod + * \{ + */ + +static inline const struct spa_type_info *spa_debug_type_info_short(const struct spa_type_info *info, const char *name) +{ + while (info && info->name) { + if (spa_streq(info->name, name)) + return info; + if (spa_streq(spa_debug_type_short_name(info->name), name)) + return info; + if (info->type != 0 && info->type == (uint32_t)atoi(name)) + return info; + info++; + } + return NULL; +} + +static inline int spa_json_to_pod_part(struct spa_pod_builder *b, uint32_t flags, uint32_t id, + const struct spa_type_info *info, struct spa_json *iter, const char *value, int len) +{ + const struct spa_type_info *ti; + char key[256]; + struct spa_pod_frame f[1]; + struct spa_json it[1]; + int l, res; + const char *v; + uint32_t type; + + if (spa_json_is_object(value, len) && info != NULL) { + if ((ti = spa_debug_type_find(NULL, info->parent)) == NULL) + return -EINVAL; + + spa_pod_builder_push_object(b, &f[0], info->parent, id); + + spa_json_enter(iter, &it[0]); + while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { + const struct spa_type_info *pi; + if ((l = spa_json_next(&it[0], &v)) <= 0) + break; + if ((pi = spa_debug_type_info_short(ti->values, key)) != NULL) + type = pi->type; + else if (!spa_atou32(key, &type, 0)) + continue; + spa_pod_builder_prop(b, type, 0); + if ((res = spa_json_to_pod_part(b, flags, id, pi, &it[0], v, l)) < 0) + return res; + } + spa_pod_builder_pop(b, &f[0]); + } + else if (spa_json_is_array(value, len)) { + if (info == NULL || info->parent == SPA_TYPE_Struct) { + spa_pod_builder_push_struct(b, &f[0]); + } else { + spa_pod_builder_push_array(b, &f[0]); + info = info->values; + } + spa_json_enter(iter, &it[0]); + while ((l = spa_json_next(&it[0], &v)) > 0) + if ((res = spa_json_to_pod_part(b, flags, id, info, &it[0], v, l)) < 0) + return res; + spa_pod_builder_pop(b, &f[0]); + } + else if (spa_json_is_float(value, len)) { + float val = 0.0f; + spa_json_parse_float(value, len, &val); + switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) { + case SPA_TYPE_Bool: + spa_pod_builder_bool(b, val >= 0.5f); + break; + case SPA_TYPE_Id: + spa_pod_builder_id(b, val); + break; + case SPA_TYPE_Int: + spa_pod_builder_int(b, val); + break; + case SPA_TYPE_Long: + spa_pod_builder_long(b, val); + break; + case SPA_TYPE_Struct: + if (spa_json_is_int(value, len)) + spa_pod_builder_int(b, val); + else + spa_pod_builder_float(b, val); + break; + case SPA_TYPE_Float: + spa_pod_builder_float(b, val); + break; + case SPA_TYPE_Double: + spa_pod_builder_double(b, val); + break; + default: + spa_pod_builder_none(b); + break; + } + } + else if (spa_json_is_bool(value, len)) { + bool val = false; + spa_json_parse_bool(value, len, &val); + spa_pod_builder_bool(b, val); + } + else if (spa_json_is_null(value, len)) { + spa_pod_builder_none(b); + } + else { + char *val = (char*)alloca(len+1); + spa_json_parse_stringn(value, len, val, len+1); + switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) { + case SPA_TYPE_Id: + if ((ti = spa_debug_type_info_short(info->values, val)) != NULL) + type = ti->type; + else if (!spa_atou32(val, &type, 0)) + return -EINVAL; + spa_pod_builder_id(b, type); + break; + case SPA_TYPE_Struct: + case SPA_TYPE_String: + spa_pod_builder_string(b, val); + break; + default: + spa_pod_builder_none(b); + break; + } + } + return 0; +} + +static inline int spa_json_to_pod(struct spa_pod_builder *b, uint32_t flags, + const struct spa_type_info *info, const char *value, int len) +{ + struct spa_json iter; + const char *val; + + spa_json_init(&iter, value, len); + if ((len = spa_json_next(&iter, &val)) <= 0) + return -EINVAL; + + return spa_json_to_pod_part(b, flags, info->type, info, &iter, val, len); +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_UTILS_JSON_POD_H */ diff --git a/src/tools/pw-cli.c b/src/tools/pw-cli.c index a8f5d76d3..efade2c9a 100644 --- a/src/tools/pw-cli.c +++ b/src/tools/pw-cli.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include @@ -1544,126 +1544,15 @@ static bool do_enum_params(struct data *data, const char *cmd, char *args, char return true; } -static int json_to_pod(struct spa_pod_builder *b, uint32_t id, - const struct spa_type_info *info, struct spa_json *iter, const char *value, int len) -{ - const struct spa_type_info *ti; - char key[256]; - struct spa_pod_frame f[1]; - struct spa_json it[1]; - int l, res; - const char *v; - uint32_t type; - - if (spa_json_is_object(value, len) && info != NULL) { - if ((ti = spa_debug_type_find(NULL, info->parent)) == NULL) - return -EINVAL; - - spa_pod_builder_push_object(b, &f[0], info->parent, id); - - spa_json_enter(iter, &it[0]); - while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { - const struct spa_type_info *pi; - if ((l = spa_json_next(&it[0], &v)) <= 0) - break; - if ((pi = find_type_info(ti->values, key)) != NULL) - type = pi->type; - else if ((type = atoi(key)) == 0) - continue; - spa_pod_builder_prop(b, type, 0); - if ((res = json_to_pod(b, id, pi, &it[0], v, l)) < 0) - return res; - } - spa_pod_builder_pop(b, &f[0]); - } - else if (spa_json_is_array(value, len)) { - if (info == NULL || info->parent == SPA_TYPE_Struct) { - spa_pod_builder_push_struct(b, &f[0]); - } else { - spa_pod_builder_push_array(b, &f[0]); - info = info->values; - } - spa_json_enter(iter, &it[0]); - while ((l = spa_json_next(&it[0], &v)) > 0) - if ((res = json_to_pod(b, id, info, &it[0], v, l)) < 0) - return res; - spa_pod_builder_pop(b, &f[0]); - } - else if (spa_json_is_float(value, len)) { - float val = 0.0f; - spa_json_parse_float(value, len, &val); - switch (info ? info->parent : SPA_TYPE_Struct) { - case SPA_TYPE_Bool: - spa_pod_builder_bool(b, val >= 0.5f); - break; - case SPA_TYPE_Id: - spa_pod_builder_id(b, val); - break; - case SPA_TYPE_Int: - spa_pod_builder_int(b, val); - break; - case SPA_TYPE_Long: - spa_pod_builder_long(b, val); - break; - case SPA_TYPE_Struct: - if (spa_json_is_int(value, len)) - spa_pod_builder_int(b, val); - else - spa_pod_builder_float(b, val); - break; - case SPA_TYPE_Float: - spa_pod_builder_float(b, val); - break; - case SPA_TYPE_Double: - spa_pod_builder_double(b, val); - break; - default: - spa_pod_builder_none(b); - break; - } - } - else if (spa_json_is_bool(value, len)) { - bool val = false; - spa_json_parse_bool(value, len, &val); - spa_pod_builder_bool(b, val); - } - else if (spa_json_is_null(value, len)) { - spa_pod_builder_none(b); - } - else { - char *val = alloca(len+1); - spa_json_parse_stringn(value, len, val, len+1); - switch (info ? info->parent : SPA_TYPE_Struct) { - case SPA_TYPE_Id: - if ((ti = find_type_info(info->values, val)) != NULL) - type = ti->type; - else if ((type = atoi(val)) == 0) - return -EINVAL; - spa_pod_builder_id(b, type); - break; - case SPA_TYPE_Struct: - case SPA_TYPE_String: - spa_pod_builder_string(b, val); - break; - default: - spa_pod_builder_none(b); - break; - } - } - return 0; -} - static bool do_set_param(struct data *data, const char *cmd, char *args, char **error) { struct remote_data *rd = data->current; char *a[3]; - const char *val; - int res, n, len; + int res, n; uint32_t id, param_id; struct global *global; - struct spa_json it[3]; uint8_t buffer[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); const struct spa_type_info *ti; struct spa_pod *pod; @@ -1690,14 +1579,7 @@ static bool do_set_param(struct data *data, const char *cmd, char *args, char ** *error = spa_aprintf("%s: unknown param type: %s", cmd, a[1]); return false; } - param_id = ti->type; - - spa_json_init(&it[0], a[2], strlen(a[2])); - if ((len = spa_json_next(&it[0], &val)) <= 0) { - *error = spa_aprintf("%s: not a JSON object: %s", cmd, a[2]); - return false; - } - if ((res = json_to_pod(&b, param_id, ti, &it[0], val, len)) < 0) { + if ((res = spa_json_to_pod(&b, 0, ti, a[2], strlen(a[2]))) < 0) { *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); return false; } @@ -1707,6 +1589,8 @@ static bool do_set_param(struct data *data, const char *cmd, char *args, char ** } spa_debug_pod(0, NULL, pod); + param_id = ti->type; + if (spa_streq(global->type, PW_TYPE_INTERFACE_Node)) pw_node_set_param((struct pw_node*)global->proxy, param_id, 0, pod);