mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
pw-cli: implement set_param
You can do something like this to set some params:
pw-cli set-param 46 13 '{ "index": 5,
"props": { "mute": false,
"channelMap": [ "FL", "LFE" ]
},
"direction": "Output"
}'
This commit is contained in:
parent
967a5e06b0
commit
95718792c4
1 changed files with 182 additions and 1 deletions
|
|
@ -37,6 +37,8 @@
|
||||||
#include <spa/debug/pod.h>
|
#include <spa/debug/pod.h>
|
||||||
#include <spa/debug/format.h>
|
#include <spa/debug/format.h>
|
||||||
#include <spa/utils/keys.h>
|
#include <spa/utils/keys.h>
|
||||||
|
#include <spa/utils/json.h>
|
||||||
|
#include <spa/pod/builder.h>
|
||||||
|
|
||||||
#include <pipewire/impl.h>
|
#include <pipewire/impl.h>
|
||||||
|
|
||||||
|
|
@ -213,6 +215,7 @@ static bool do_destroy(struct data *data, const char *cmd, char *args, char **er
|
||||||
static bool do_create_link(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_create_link(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_export_node(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_export_node(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_enum_params(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_enum_params(struct data *data, const char *cmd, char *args, char **error);
|
||||||
|
static bool do_set_param(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_dump(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_dump(struct data *data, const char *cmd, char *args, char **error);
|
||||||
|
|
@ -234,7 +237,8 @@ static struct command command_list[] = {
|
||||||
{ "destroy", "d", "Destroy a global object. <object-id>", do_destroy },
|
{ "destroy", "d", "Destroy a global object. <object-id>", do_destroy },
|
||||||
{ "create-link", "cl", "Create a link between nodes. <node-id> <port-id> <node-id> <port-id> [<properties>]", do_create_link },
|
{ "create-link", "cl", "Create a link between nodes. <node-id> <port-id> <node-id> <port-id> [<properties>]", do_create_link },
|
||||||
{ "export-node", "en", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
|
{ "export-node", "en", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
|
||||||
{ "enum-params", "e", "Enumerate params of an object <object-id> [<param-id-name>]", do_enum_params },
|
{ "enum-params", "e", "Enumerate params of an object <object-id> <param-id>", do_enum_params },
|
||||||
|
{ "set-param", "s", "Set param of an object <object-id> <param-id> <param-json>", do_set_param },
|
||||||
{ "permissions", "sp", "Set permissions for a client <client-id> <object> <permission>", do_permissions },
|
{ "permissions", "sp", "Set permissions for a client <client-id> <object> <permission>", do_permissions },
|
||||||
{ "get-permissions", "gp", "Get permissions of a client <client-id>", do_get_permissions },
|
{ "get-permissions", "gp", "Get permissions of a client <client-id>", do_get_permissions },
|
||||||
{ "dump", "D", "Dump objects in ways that are cleaner for humans to understand "
|
{ "dump", "D", "Dump objects in ways that are cleaner for humans to understand "
|
||||||
|
|
@ -1525,6 +1529,183 @@ static bool do_enum_params(struct data *data, const char *cmd, char *args, char
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct spa_type_info *find_type_info(const struct spa_type_info *info, const char *name)
|
||||||
|
{
|
||||||
|
while (info && info->name) {
|
||||||
|
if (strcmp(info->name, name) == 0)
|
||||||
|
return info;
|
||||||
|
if (strcmp(spa_debug_type_short_name(info->name), name) == 0)
|
||||||
|
return info;
|
||||||
|
if (info->type != 0 && info->type == (uint32_t)atoi(name))
|
||||||
|
return info;
|
||||||
|
info++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
const char *v;
|
||||||
|
|
||||||
|
if (spa_json_is_object(value, len)) {
|
||||||
|
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)-1) > 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)
|
||||||
|
continue;
|
||||||
|
spa_pod_builder_prop(b, pi->type, 0);
|
||||||
|
json_to_pod(b, id, pi, &it[0], v, l);
|
||||||
|
}
|
||||||
|
spa_pod_builder_pop(b, &f[0]);
|
||||||
|
}
|
||||||
|
else if (spa_json_is_array(value, len)) {
|
||||||
|
spa_pod_builder_push_array(b, &f[0]);
|
||||||
|
spa_json_enter(iter, &it[0]);
|
||||||
|
while ((l = spa_json_next(&it[0], &v)) > 0)
|
||||||
|
json_to_pod(b, id, info, &it[0], v, l);
|
||||||
|
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->parent) {
|
||||||
|
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_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_string(value, len)) {
|
||||||
|
char *val = alloca(len);
|
||||||
|
spa_json_parse_string(value, len, val);
|
||||||
|
switch (info->parent) {
|
||||||
|
case SPA_TYPE_Id:
|
||||||
|
if ((ti = find_type_info(info ? info->values : info, val)) != NULL)
|
||||||
|
spa_pod_builder_id(b, ti->type);
|
||||||
|
break;
|
||||||
|
case SPA_TYPE_String:
|
||||||
|
spa_pod_builder_string(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
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
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;
|
||||||
|
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));
|
||||||
|
const struct spa_type_info *ti;
|
||||||
|
struct spa_pod *pod;
|
||||||
|
|
||||||
|
n = pw_split_ip(args, WHITESPACE, 3, a);
|
||||||
|
if (n < 3) {
|
||||||
|
*error = spa_aprintf("%s <object-id> <param-id> <param-json>", cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = atoi(a[0]);
|
||||||
|
param_id = atoi(a[1]);
|
||||||
|
|
||||||
|
global = pw_map_lookup(&rd->globals, id);
|
||||||
|
if (global == NULL) {
|
||||||
|
*error = spa_aprintf("%s: unknown global %d", cmd, id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (global->proxy == NULL) {
|
||||||
|
if (!bind_global(rd, global, error))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ti = spa_debug_type_find(spa_type_param, param_id);
|
||||||
|
if (ti == NULL) {
|
||||||
|
*error = spa_aprintf("%s: unknown param type: %d", cmd, param_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
*error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) {
|
||||||
|
*error = spa_aprintf("%s: can't make pod", cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
spa_debug_pod(0, NULL, pod);
|
||||||
|
|
||||||
|
if (strcmp(global->type, PW_TYPE_INTERFACE_Node) == 0)
|
||||||
|
pw_node_set_param((struct pw_node*)global->proxy,
|
||||||
|
param_id, 0, pod);
|
||||||
|
else if (strcmp(global->type, PW_TYPE_INTERFACE_Device) == 0)
|
||||||
|
pw_device_set_param((struct pw_device*)global->proxy,
|
||||||
|
param_id, 0, pod);
|
||||||
|
else if (strcmp(global->type, PW_TYPE_INTERFACE_Endpoint) == 0)
|
||||||
|
pw_endpoint_set_param((struct pw_endpoint*)global->proxy,
|
||||||
|
param_id, 0, pod);
|
||||||
|
else {
|
||||||
|
*error = spa_aprintf("set-param not implemented on object %d type:%s",
|
||||||
|
atoi(a[0]), global->type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error)
|
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error)
|
||||||
{
|
{
|
||||||
struct remote_data *rd = data->current;
|
struct remote_data *rd = data->current;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue