mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -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/format.h>
 | 
			
		||||
#include <spa/utils/keys.h>
 | 
			
		||||
#include <spa/utils/json.h>
 | 
			
		||||
#include <spa/pod/builder.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_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_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_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);
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +237,8 @@ static struct command command_list[] = {
 | 
			
		|||
	{ "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 },
 | 
			
		||||
	{ "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 },
 | 
			
		||||
	{ "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 "
 | 
			
		||||
| 
						 | 
				
			
			@ -1525,6 +1529,183 @@ static bool do_enum_params(struct data *data, const char *cmd, char *args, char
 | 
			
		|||
	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)
 | 
			
		||||
{
 | 
			
		||||
	struct remote_data *rd = data->current;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue