mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-02 09:01:50 -05:00
protocol: add more methods on client
Add method to get and set permissions on a client Add method to send error to client.
This commit is contained in:
parent
bbf718cc98
commit
e026f55c97
6 changed files with 410 additions and 46 deletions
|
|
@ -1017,6 +1017,155 @@ static int client_demarshal_info(void *object, void *data, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void client_marshal_permissions(void *object, const struct spa_dict *dict)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct spa_pod_builder *b;
|
||||||
|
uint32_t i, n_items;
|
||||||
|
|
||||||
|
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_PROXY_EVENT_PERMISSIONS);
|
||||||
|
|
||||||
|
n_items = dict ? dict->n_items : 0;
|
||||||
|
|
||||||
|
spa_pod_builder_add(b,
|
||||||
|
"[",
|
||||||
|
"i", n_items, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < n_items; i++) {
|
||||||
|
spa_pod_builder_add(b,
|
||||||
|
"s", dict->items[i].key,
|
||||||
|
"s", dict->items[i].value, NULL);
|
||||||
|
}
|
||||||
|
spa_pod_builder_add(b, "]", NULL);
|
||||||
|
|
||||||
|
pw_protocol_native_end_resource(resource, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_demarshal_permissions(void *object, void *data, size_t size)
|
||||||
|
{
|
||||||
|
struct pw_proxy *proxy = object;
|
||||||
|
struct spa_dict props;
|
||||||
|
struct spa_pod_parser prs;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
spa_pod_parser_init(&prs, data, size, 0);
|
||||||
|
if (spa_pod_parser_get(&prs, "[ i", &props.n_items, NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||||
|
for (i = 0; i < props.n_items; i++) {
|
||||||
|
if (spa_pod_parser_get(&prs,
|
||||||
|
"s", &props.items[i].key,
|
||||||
|
"s", &props.items[i].value,
|
||||||
|
NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pw_proxy_notify(proxy, struct pw_client_proxy_events, permissions, 0, &props);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_marshal_error(void *object, uint32_t id, int res, const char *error)
|
||||||
|
{
|
||||||
|
struct pw_proxy *proxy = object;
|
||||||
|
struct spa_pod_builder *b;
|
||||||
|
|
||||||
|
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_ERROR);
|
||||||
|
spa_pod_builder_add_struct(b,
|
||||||
|
"i", id,
|
||||||
|
"i", res,
|
||||||
|
"s", error);
|
||||||
|
pw_protocol_native_end_proxy(proxy, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_demarshal_error(void *object, void *data, size_t size)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct spa_pod_parser prs;
|
||||||
|
uint32_t id, res;
|
||||||
|
const char *error;
|
||||||
|
|
||||||
|
spa_pod_parser_init(&prs, data, size, 0);
|
||||||
|
if (spa_pod_parser_get(&prs,
|
||||||
|
"[ i", &id,
|
||||||
|
"i", &res,
|
||||||
|
"s", &error, NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pw_resource_do(resource, struct pw_client_proxy_methods, error, 0, id, res, error);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_marshal_get_permissions(void *object)
|
||||||
|
{
|
||||||
|
struct pw_proxy *proxy = object;
|
||||||
|
struct spa_pod_builder *b;
|
||||||
|
|
||||||
|
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_GET_PERMISSIONS);
|
||||||
|
|
||||||
|
spa_pod_builder_add_struct(b, "P", NULL);
|
||||||
|
|
||||||
|
pw_protocol_native_end_proxy(proxy, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_demarshal_get_permissions(void *object, void *data, size_t size)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct spa_pod_parser prs;
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
|
spa_pod_parser_init(&prs, data, size, 0);
|
||||||
|
if (spa_pod_parser_get(&prs, "[P]", &ptr, NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
pw_resource_do(resource, struct pw_client_proxy_methods, get_permissions, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_marshal_update_permissions(void *object, const struct spa_dict *props)
|
||||||
|
{
|
||||||
|
struct pw_proxy *proxy = object;
|
||||||
|
struct spa_pod_builder *b;
|
||||||
|
int i, n_items;
|
||||||
|
|
||||||
|
b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS);
|
||||||
|
|
||||||
|
n_items = props ? props->n_items : 0;
|
||||||
|
|
||||||
|
spa_pod_builder_add(b, "[ i", n_items, NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < n_items; i++) {
|
||||||
|
spa_pod_builder_add(b,
|
||||||
|
"s", props->items[i].key,
|
||||||
|
"s", props->items[i].value, NULL);
|
||||||
|
}
|
||||||
|
spa_pod_builder_add(b, "]", NULL);
|
||||||
|
|
||||||
|
pw_protocol_native_end_proxy(proxy, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int client_demarshal_update_permissions(void *object, void *data, size_t size)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct spa_dict props;
|
||||||
|
struct spa_pod_parser prs;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
spa_pod_parser_init(&prs, data, size, 0);
|
||||||
|
if (spa_pod_parser_get(&prs, "[ i", &props.n_items, NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||||
|
for (i = 0; i < props.n_items; i++) {
|
||||||
|
if (spa_pod_parser_get(&prs,
|
||||||
|
"s", &props.items[i].key,
|
||||||
|
"s", &props.items[i].value,
|
||||||
|
NULL) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pw_resource_do(resource, struct pw_client_proxy_methods, update_permissions, 0, &props);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void link_marshal_info(void *object, struct pw_link_info *info)
|
static void link_marshal_info(void *object, struct pw_link_info *info)
|
||||||
{
|
{
|
||||||
struct pw_resource *resource = object;
|
struct pw_resource *resource = object;
|
||||||
|
|
@ -1342,19 +1491,36 @@ static const struct pw_protocol_marshal pw_protocol_native_port_marshal = {
|
||||||
PW_PORT_PROXY_EVENT_NUM,
|
PW_PORT_PROXY_EVENT_NUM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct pw_client_proxy_methods pw_protocol_native_client_method_marshal = {
|
||||||
|
PW_VERSION_CLIENT_PROXY_METHODS,
|
||||||
|
&client_marshal_error,
|
||||||
|
&client_marshal_get_permissions,
|
||||||
|
&client_marshal_update_permissions,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pw_protocol_native_demarshal pw_protocol_native_client_method_demarshal[] = {
|
||||||
|
{ &client_demarshal_error, PW_PROTOCOL_NATIVE_PERM_W, },
|
||||||
|
{ &client_demarshal_get_permissions, 0, },
|
||||||
|
{ &client_demarshal_update_permissions, PW_PROTOCOL_NATIVE_PERM_W, },
|
||||||
|
};
|
||||||
|
|
||||||
static const struct pw_client_proxy_events pw_protocol_native_client_event_marshal = {
|
static const struct pw_client_proxy_events pw_protocol_native_client_event_marshal = {
|
||||||
PW_VERSION_CLIENT_PROXY_EVENTS,
|
PW_VERSION_CLIENT_PROXY_EVENTS,
|
||||||
&client_marshal_info,
|
&client_marshal_info,
|
||||||
|
&client_marshal_permissions,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pw_protocol_native_demarshal pw_protocol_native_client_event_demarshal[] = {
|
static const struct pw_protocol_native_demarshal pw_protocol_native_client_event_demarshal[] = {
|
||||||
{ &client_demarshal_info, 0, },
|
{ &client_demarshal_info, 0, },
|
||||||
|
{ &client_demarshal_permissions, 0, }
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct pw_protocol_marshal pw_protocol_native_client_marshal = {
|
static const struct pw_protocol_marshal pw_protocol_native_client_marshal = {
|
||||||
PW_TYPE_INTERFACE_Client,
|
PW_TYPE_INTERFACE_Client,
|
||||||
PW_VERSION_CLIENT,
|
PW_VERSION_CLIENT,
|
||||||
NULL, NULL, 0,
|
&pw_protocol_native_client_method_marshal,
|
||||||
|
pw_protocol_native_client_method_demarshal,
|
||||||
|
PW_CLIENT_PROXY_METHOD_NUM,
|
||||||
&pw_protocol_native_client_event_marshal,
|
&pw_protocol_native_client_event_marshal,
|
||||||
pw_protocol_native_client_event_demarshal,
|
pw_protocol_native_client_event_demarshal,
|
||||||
PW_CLIENT_PROXY_EVENT_NUM,
|
PW_CLIENT_PROXY_EVENT_NUM,
|
||||||
|
|
|
||||||
|
|
@ -47,21 +47,42 @@ struct resource_data {
|
||||||
|
|
||||||
/** find a specific permission for a global or NULL when there is none */
|
/** find a specific permission for a global or NULL when there is none */
|
||||||
static struct permission *
|
static struct permission *
|
||||||
find_permission(struct pw_client *client, struct pw_global *global)
|
find_permission(struct pw_client *client, uint32_t id)
|
||||||
{
|
{
|
||||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
struct permission *p;
|
struct permission *p;
|
||||||
|
|
||||||
if (!pw_array_check_index(&impl->permissions, global->id, struct permission))
|
if (!pw_array_check_index(&impl->permissions, id, struct permission))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
p = pw_array_get_unchecked(&impl->permissions, global->id, struct permission);
|
p = pw_array_get_unchecked(&impl->permissions, id, struct permission);
|
||||||
if (p->permissions == -1)
|
if (p->permissions == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct permission *ensure_permissions(struct pw_client *client, uint32_t id)
|
||||||
|
{
|
||||||
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
|
struct permission *p;
|
||||||
|
size_t len, i;
|
||||||
|
|
||||||
|
len = pw_array_get_len(&impl->permissions, struct permission);
|
||||||
|
if (len <= id) {
|
||||||
|
size_t diff = id - len + 1;
|
||||||
|
|
||||||
|
p = pw_array_add(&impl->permissions, diff * sizeof(struct permission));
|
||||||
|
if (p == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < diff; i++)
|
||||||
|
p[i].permissions = -1;
|
||||||
|
}
|
||||||
|
p = pw_array_get_unchecked(&impl->permissions, id, struct permission);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/** \endcond */
|
/** \endcond */
|
||||||
|
|
||||||
static uint32_t
|
static uint32_t
|
||||||
|
|
@ -71,13 +92,111 @@ client_permission_func(struct pw_global *global,
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
struct permission *p;
|
struct permission *p;
|
||||||
|
|
||||||
p = find_permission(client, global);
|
p = find_permission(client, global->id);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
return impl->permissions_default;
|
return impl->permissions_default;
|
||||||
else
|
else
|
||||||
return p->permissions;
|
return p->permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t parse_mask(const char *str)
|
||||||
|
{
|
||||||
|
uint32_t mask = 0;
|
||||||
|
|
||||||
|
while (*str != '\0') {
|
||||||
|
switch (*str++) {
|
||||||
|
case 'r':
|
||||||
|
mask |= PW_PERM_R;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
mask |= PW_PERM_W;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
mask |= PW_PERM_X;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_error(void *object, uint32_t id, int res, const char *error)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||||
|
struct pw_client *client = data->client;
|
||||||
|
pw_resource_error(client->core_resource, id, res, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_get_permissions(void *object)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||||
|
struct pw_client *client = data->client;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_update_permissions(void *object, const struct spa_dict *props)
|
||||||
|
{
|
||||||
|
struct pw_resource *resource = object;
|
||||||
|
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||||
|
struct pw_client *client = data->client;
|
||||||
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
|
const char *str;
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
for (i = 0; i < props->n_items; i++) {
|
||||||
|
str = props->items[i].value;
|
||||||
|
|
||||||
|
pw_log_debug("client %p: %s %s", client, props->items[i].key, str);
|
||||||
|
|
||||||
|
if (strcmp(props->items[i].key, PW_CORE_PROXY_PERMISSIONS_DEFAULT) == 0) {
|
||||||
|
impl->permissions_default = parse_mask(str);
|
||||||
|
pw_log_debug("client %p: set default permissions to %08x",
|
||||||
|
client, impl->permissions_default);
|
||||||
|
}
|
||||||
|
else if (strcmp(props->items[i].key, PW_CORE_PROXY_PERMISSIONS_GLOBAL) == 0) {
|
||||||
|
struct pw_global *global;
|
||||||
|
uint32_t global_id, old_perm, new_perm;
|
||||||
|
struct permission *p;
|
||||||
|
|
||||||
|
/* permissions.update=<global-id>:[r][w][x] */
|
||||||
|
len = strcspn(str, ":");
|
||||||
|
if (len == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
global_id = atoi(str);
|
||||||
|
global = pw_core_find_global(client->core, global_id);
|
||||||
|
if (global == NULL) {
|
||||||
|
pw_log_warn("client %p: invalid global %d", client, global_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = ensure_permissions(client, global_id);
|
||||||
|
old_perm = p->permissions == -1 ? impl->permissions_default : p->permissions;
|
||||||
|
new_perm = parse_mask(str + len);
|
||||||
|
|
||||||
|
pw_log_debug("client %p: %08x %08x", client, old_perm, new_perm);
|
||||||
|
|
||||||
|
p->permissions = new_perm;
|
||||||
|
|
||||||
|
if (PW_PERM_IS_R(old_perm) && !PW_PERM_IS_R(new_perm)) {
|
||||||
|
pw_global_revoke(global, client);
|
||||||
|
}
|
||||||
|
else if (!PW_PERM_IS_R(old_perm) && PW_PERM_IS_R(new_perm)) {
|
||||||
|
pw_global_grant(global, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (impl->permissions_default != 0)
|
||||||
|
pw_client_set_busy(client, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pw_client_proxy_methods client_methods = {
|
||||||
|
PW_VERSION_CLIENT_PROXY_METHODS,
|
||||||
|
.error = client_error,
|
||||||
|
.get_permissions = client_get_permissions,
|
||||||
|
.update_permissions = client_update_permissions
|
||||||
|
};
|
||||||
|
|
||||||
static void client_unbind_func(void *data)
|
static void client_unbind_func(void *data)
|
||||||
{
|
{
|
||||||
struct pw_resource *resource = data;
|
struct pw_resource *resource = data;
|
||||||
|
|
@ -89,7 +208,6 @@ static const struct pw_resource_events resource_events = {
|
||||||
.destroy = client_unbind_func,
|
.destroy = client_unbind_func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
global_bind(void *_data, struct pw_client *client, uint32_t permissions,
|
global_bind(void *_data, struct pw_client *client, uint32_t permissions,
|
||||||
uint32_t version, uint32_t id)
|
uint32_t version, uint32_t id)
|
||||||
|
|
@ -131,7 +249,7 @@ core_global_removed(void *data, struct pw_global *global)
|
||||||
struct pw_client *client = &impl->this;
|
struct pw_client *client = &impl->this;
|
||||||
struct permission *p;
|
struct permission *p;
|
||||||
|
|
||||||
p = find_permission(client, global);
|
p = find_permission(client, global->id);
|
||||||
pw_log_debug("client %p: global %d removed, %p", client, global->id, p);
|
pw_log_debug("client %p: global %d removed, %p", client, global->id, p);
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
p->permissions = -1;
|
p->permissions = -1;
|
||||||
|
|
@ -385,21 +503,10 @@ static int do_permissions(void *data, struct pw_global *global)
|
||||||
struct pw_client *client = update->client;
|
struct pw_client *client = update->client;
|
||||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
struct permission *p;
|
struct permission *p;
|
||||||
size_t len, i;
|
|
||||||
|
|
||||||
len = pw_array_get_len(&impl->permissions, struct permission);
|
p = ensure_permissions(client, global->id);
|
||||||
if (len <= global->id) {
|
if (p == NULL)
|
||||||
size_t diff = global->id - len + 1;
|
return -ENOMEM;
|
||||||
|
|
||||||
p = pw_array_add(&impl->permissions, diff * sizeof(struct permission));
|
|
||||||
if (p == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
for (i = 0; i < diff; i++)
|
|
||||||
p[i].permissions = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = pw_array_get_unchecked(&impl->permissions, global->id, struct permission);
|
|
||||||
if (p->permissions == -1)
|
if (p->permissions == -1)
|
||||||
p->permissions = impl->permissions_default;
|
p->permissions = impl->permissions_default;
|
||||||
else if (update->only_new)
|
else if (update->only_new)
|
||||||
|
|
@ -411,26 +518,6 @@ static int do_permissions(void *data, struct pw_global *global)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t parse_mask(const char *str)
|
|
||||||
{
|
|
||||||
uint32_t mask = 0;
|
|
||||||
|
|
||||||
while (*str != '\0') {
|
|
||||||
switch (*str++) {
|
|
||||||
case 'r':
|
|
||||||
mask |= PW_PERM_R;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
mask |= PW_PERM_W;
|
|
||||||
break;
|
|
||||||
case 'x':
|
|
||||||
mask |= PW_PERM_X;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pw_client_update_permissions(struct pw_client *client, const struct spa_dict *dict)
|
int pw_client_update_permissions(struct pw_client *client, const struct spa_dict *dict)
|
||||||
{
|
{
|
||||||
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
|
|
@ -500,3 +587,11 @@ void pw_client_set_busy(struct pw_client *client, bool busy)
|
||||||
pw_client_events_busy_changed(client, busy);
|
pw_client_events_busy_changed(client, busy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pw_client_set_permissions(struct pw_client *client, uint32_t permissions)
|
||||||
|
{
|
||||||
|
struct impl *impl = SPA_CONTAINER_OF(client, struct impl, this);
|
||||||
|
pw_log_debug("client %p: permissions %08x", client, permissions);
|
||||||
|
impl->permissions_default = permissions;
|
||||||
|
pw_client_set_busy(client, false);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,8 @@ void pw_client_add_listener(struct pw_client *client,
|
||||||
* started and no further processing is allowed to happen for the client */
|
* started and no further processing is allowed to happen for the client */
|
||||||
void pw_client_set_busy(struct pw_client *client, bool busy);
|
void pw_client_set_busy(struct pw_client *client, bool busy);
|
||||||
|
|
||||||
|
void pw_client_set_permissions(struct pw_client *client, uint32_t permissions);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -678,7 +678,8 @@ pw_factory_proxy_add_listener(struct pw_factory_proxy *factory,
|
||||||
#define PW_VERSION_CLIENT 0
|
#define PW_VERSION_CLIENT 0
|
||||||
|
|
||||||
#define PW_CLIENT_PROXY_EVENT_INFO 0
|
#define PW_CLIENT_PROXY_EVENT_INFO 0
|
||||||
#define PW_CLIENT_PROXY_EVENT_NUM 1
|
#define PW_CLIENT_PROXY_EVENT_PERMISSIONS 1
|
||||||
|
#define PW_CLIENT_PROXY_EVENT_NUM 2
|
||||||
|
|
||||||
/** Client events */
|
/** Client events */
|
||||||
struct pw_client_proxy_events {
|
struct pw_client_proxy_events {
|
||||||
|
|
@ -690,6 +691,14 @@ struct pw_client_proxy_events {
|
||||||
* \param info info about the client
|
* \param info info about the client
|
||||||
*/
|
*/
|
||||||
void (*info) (void *object, struct pw_client_info *info);
|
void (*info) (void *object, struct pw_client_info *info);
|
||||||
|
/**
|
||||||
|
* Notify a client permission
|
||||||
|
*
|
||||||
|
* Event emited as a result of the get_permissions method.
|
||||||
|
*
|
||||||
|
* \param param the parameter
|
||||||
|
*/
|
||||||
|
void (*permissions) (void *object, const struct spa_dict *dict);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Client */
|
/** Client */
|
||||||
|
|
@ -703,7 +712,59 @@ pw_client_proxy_add_listener(struct pw_client_proxy *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
#define pw_client_resource_info(r,...) pw_resource_notify(r,struct pw_client_proxy_events,info,__VA_ARGS__)
|
#define pw_client_resource_info(r,...) pw_resource_notify(r,struct pw_client_proxy_events,info,__VA_ARGS__)
|
||||||
|
#define pw_client_resource_permissions(r,...) pw_resource_notify(r,struct pw_client_proxy_events,permissions,__VA_ARGS__)
|
||||||
|
|
||||||
|
#define PW_CLIENT_PROXY_METHOD_ERROR 0
|
||||||
|
#define PW_CLIENT_PROXY_METHOD_GET_PERMISSIONS 1
|
||||||
|
#define PW_CLIENT_PROXY_METHOD_UPDATE_PERMISSIONS 2
|
||||||
|
#define PW_CLIENT_PROXY_METHOD_NUM 3
|
||||||
|
|
||||||
|
/** Client methods */
|
||||||
|
struct pw_client_proxy_methods {
|
||||||
|
#define PW_VERSION_CLIENT_PROXY_METHODS 0
|
||||||
|
uint32_t version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an error to a client
|
||||||
|
*
|
||||||
|
* \param id the global id to report the error on
|
||||||
|
* \param res an errno style error code
|
||||||
|
* \param error an error string
|
||||||
|
*/
|
||||||
|
void (*error) (void *object, uint32_t id, int res, const char *error);
|
||||||
|
/**
|
||||||
|
* Get client permissions
|
||||||
|
*
|
||||||
|
* A permissions event will be emited with the permissions.
|
||||||
|
*/
|
||||||
|
void (*get_permissions) (void *object);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update client permissions
|
||||||
|
*
|
||||||
|
* \param dict list of permissions to update
|
||||||
|
*/
|
||||||
|
void (*update_permissions) (void *object, const struct spa_dict *dict);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Client permissions */
|
||||||
|
static inline void
|
||||||
|
pw_client_proxy_error(struct pw_client_proxy *client, uint32_t id, int res, const char *error)
|
||||||
|
{
|
||||||
|
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, error, id, res, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pw_client_proxy_get_permissions(struct pw_client_proxy *client)
|
||||||
|
{
|
||||||
|
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, get_permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
pw_client_proxy_update_permissions(struct pw_client_proxy *client, const struct spa_dict *dict)
|
||||||
|
{
|
||||||
|
pw_proxy_do((struct pw_proxy*)client, struct pw_client_proxy_methods, update_permissions, dict);
|
||||||
|
}
|
||||||
|
|
||||||
#define PW_VERSION_LINK 0
|
#define PW_VERSION_LINK 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -230,8 +230,9 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
|
||||||
if (current == NULL || spa_pod_compare(current, format) != 0) {
|
if (current == NULL || spa_pod_compare(current, format) != 0) {
|
||||||
pw_log_debug("link %p: output format change, renegotiate", this);
|
pw_log_debug("link %p: output format change, renegotiate", this);
|
||||||
if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) {
|
if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG)) {
|
||||||
spa_debug_format(2, NULL, current);
|
if (current)
|
||||||
spa_debug_format(2, NULL, format);
|
spa_debug_pod(2, NULL, current);
|
||||||
|
spa_debug_pod(2, NULL, format);
|
||||||
}
|
}
|
||||||
pw_node_set_state(output->node, PW_NODE_STATE_SUSPENDED);
|
pw_node_set_state(output->node, PW_NODE_STATE_SUSPENDED);
|
||||||
out_state = PW_PORT_STATE_CONFIGURE;
|
out_state = PW_PORT_STATE_CONFIGURE;
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,7 @@ static bool do_create_link(struct data *data, const char *cmd, char *args, char
|
||||||
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_node_params(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_node_params(struct data *data, const char *cmd, char *args, char **error);
|
||||||
static bool do_port_params(struct data *data, const char *cmd, char *args, char **error);
|
static bool do_port_params(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 struct command command_list[] = {
|
static struct command command_list[] = {
|
||||||
{ "help", "Show this help", do_help },
|
{ "help", "Show this help", do_help },
|
||||||
|
|
@ -194,6 +195,7 @@ static struct command command_list[] = {
|
||||||
{ "export-node", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
|
{ "export-node", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
|
||||||
{ "node-params", "Enumerate params of a node <node-id> [<param-id-name>]", do_node_params },
|
{ "node-params", "Enumerate params of a node <node-id> [<param-id-name>]", do_node_params },
|
||||||
{ "port-params", "Enumerate params of a port <port-id> [<param-id-name>]", do_port_params },
|
{ "port-params", "Enumerate params of a port <port-id> [<param-id-name>]", do_port_params },
|
||||||
|
{ "permissions", "Set permissions for a client <client-id> <permissions>", do_permissions },
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool do_help(struct data *data, const char *cmd, char *args, char **error)
|
static bool do_help(struct data *data, const char *cmd, char *args, char **error)
|
||||||
|
|
@ -1133,10 +1135,10 @@ static bool do_port_params(struct data *data, const char *cmd, char *args, char
|
||||||
asprintf(error, "%s <object-id> [<param-id-name>]", cmd);
|
asprintf(error, "%s <object-id> [<param-id-name>]", cmd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (n == 2)
|
if (n < 2)
|
||||||
param_id = SPA_PARAM_List;
|
param_id = SPA_PARAM_List;
|
||||||
else
|
else
|
||||||
param_id = SPA_PARAM_List;
|
param_id = atoi(a[1]);
|
||||||
|
|
||||||
id = atoi(a[0]);
|
id = atoi(a[0]);
|
||||||
global = pw_map_lookup(&rd->globals, id);
|
global = pw_map_lookup(&rd->globals, id);
|
||||||
|
|
@ -1159,6 +1161,43 @@ static bool do_port_params(struct data *data, const char *cmd, char *args, char
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error)
|
||||||
|
{
|
||||||
|
struct remote_data *rd = data->current;
|
||||||
|
char *a[2];
|
||||||
|
int n;
|
||||||
|
uint32_t id;
|
||||||
|
struct global *global;
|
||||||
|
struct spa_dict_item items[1];
|
||||||
|
|
||||||
|
n = pw_split_ip(args, WHITESPACE, 2, a);
|
||||||
|
if (n < 2) {
|
||||||
|
asprintf(error, "%s <client-id> <permission>", cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
id = atoi(a[0]);
|
||||||
|
global = pw_map_lookup(&rd->globals, id);
|
||||||
|
if (global == NULL) {
|
||||||
|
asprintf(error, "%s: unknown global %d", cmd, id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (global->type != PW_TYPE_INTERFACE_Client) {
|
||||||
|
asprintf(error, "object %d is not a client", atoi(a[0]));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (global->proxy == NULL) {
|
||||||
|
if (!bind_global(rd, global, error))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
items[0] = SPA_DICT_ITEM_INIT(PW_CORE_PROXY_PERMISSIONS_GLOBAL, a[1]);
|
||||||
|
pw_client_proxy_update_permissions((struct pw_client_proxy*)global->proxy,
|
||||||
|
&SPA_DICT_INIT(items, 1));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool parse(struct data *data, char *buf, size_t size, char **error)
|
static bool parse(struct data *data, char *buf, size_t size, char **error)
|
||||||
{
|
{
|
||||||
char *a[2];
|
char *a[2];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue