pw-cli: support arbitrary large params and commands

Use a memstream to collect the arguments so that it can dynamically
allocate as much memory as necessary.

Use a dynamic pod builder to construct the pods so that they can be of
arbitrary size.

Fixes #4166
This commit is contained in:
Wim Taymans 2024-07-31 17:36:45 +02:00
parent 8fac16a594
commit b61765eaf4

View file

@ -32,7 +32,7 @@
#include <spa/debug/pod.h> #include <spa/debug/pod.h>
#include <spa/utils/keys.h> #include <spa/utils/keys.h>
#include <spa/utils/json-pod.h> #include <spa/utils/json-pod.h>
#include <spa/pod/builder.h> #include <spa/pod/dynamic.h>
#include <pipewire/impl.h> #include <pipewire/impl.h>
#include <pipewire/i18n.h> #include <pipewire/i18n.h>
@ -1777,10 +1777,12 @@ static bool do_set_param(struct data *data, const char *cmd, char *args, char **
uint32_t param_id; uint32_t param_id;
struct global *global; struct global *global;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); spa_auto(spa_pod_dynamic_builder) b = { 0 };
const struct spa_type_info *ti; const struct spa_type_info *ti;
struct spa_pod *pod; struct spa_pod *pod;
spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
n = pw_split_ip(args, WHITESPACE, 3, a); n = pw_split_ip(args, WHITESPACE, 3, a);
if (n < 3) { if (n < 3) {
*error = spa_aprintf("%s <object-id> <param-id> <param-json>", cmd); *error = spa_aprintf("%s <object-id> <param-id> <param-json>", cmd);
@ -1802,11 +1804,11 @@ 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]); *error = spa_aprintf("%s: unknown param type: %s", cmd, a[1]);
return false; return false;
} }
if ((res = spa_json_to_pod(&b, 0, ti, a[2], strlen(a[2]))) < 0) { if ((res = spa_json_to_pod(&b.b, 0, ti, a[2], strlen(a[2]))) < 0) {
*error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
return false; return false;
} }
if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) { if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) {
*error = spa_aprintf("%s: can't make pod", cmd); *error = spa_aprintf("%s: can't make pod", cmd);
return false; return false;
} }
@ -1911,10 +1913,12 @@ static bool do_send_command(struct data *data, const char *cmd, char *args, char
int res, n; int res, n;
struct global *global; struct global *global;
uint8_t buffer[1024]; uint8_t buffer[1024];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); spa_auto(spa_pod_dynamic_builder) b = { 0 };
const struct spa_type_info *ti; const struct spa_type_info *ti;
struct spa_pod *pod; struct spa_pod *pod;
spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096);
n = pw_split_ip(args, WHITESPACE, 3, a); n = pw_split_ip(args, WHITESPACE, 3, a);
if (n < 3) { if (n < 3) {
*error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd); *error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd);
@ -1943,11 +1947,11 @@ static bool do_send_command(struct data *data, const char *cmd, char *args, char
*error = spa_aprintf("%s: unknown node command type: %s", cmd, a[1]); *error = spa_aprintf("%s: unknown node command type: %s", cmd, a[1]);
return false; return false;
} }
if ((res = spa_json_to_pod(&b, 0, ti, a[2], strlen(a[2]))) < 0) { if ((res = spa_json_to_pod(&b.b, 0, ti, a[2], strlen(a[2]))) < 0) {
*error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
return false; return false;
} }
if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) { if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) {
*error = spa_aprintf("%s: can't make pod", cmd); *error = spa_aprintf("%s: can't make pod", cmd);
return false; return false;
} }
@ -2387,23 +2391,26 @@ int main(int argc, char *argv[])
readline_cleanup(); readline_cleanup();
#endif #endif
} else { } else {
char buf[4096], *p, *error; FILE *buf;
char *error, *ptr;
size_t size;
p = buf; buf = open_memstream(&ptr, &size);
for (i = optind; i < argc; i++) { for (i = optind; i < argc; i++)
p = stpcpy(p, argv[i]); fprintf(buf, "%s%s", i == optind ? "" : " ", argv[i]);
p = stpcpy(p, " "); fclose(buf);
}
// If we're monitoring, surface info changes as well // If we're monitoring, surface info changes as well
data.monitoring_info = monitor; data.monitoring_info = monitor;
pw_main_loop_run(data.loop); pw_main_loop_run(data.loop);
if (!parse(&data, buf, &error)) { if (!parse(&data, ptr, &error)) {
fprintf(stderr, "Error: \"%s\"\n", error); fprintf(stderr, "Error: \"%s\"\n", error);
free(error); free(error);
} }
free(ptr);
if (data.current != NULL) if (data.current != NULL)
data.current->prompt_pending = pw_core_sync(data.current->core, 0, 0); data.current->prompt_pending = pw_core_sync(data.current->core, 0, 0);