pipewire/src/modules/module-client-node/v0/protocol-native.c

519 lines
15 KiB
C
Raw Normal View History

protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
/* PipeWire
* Copyright (C) 2017 Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <errno.h>
#include <spa/pod/parser.h>
#include "pipewire/pipewire.h"
#include "pipewire/interfaces.h"
#include "pipewire/protocol.h"
#include "pipewire/impl-client.h"
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
#include "pipewire/private.h"
#include "extensions/protocol-native.h"
#include "ext-client-node.h"
#include "transport.h"
#define PW_PROTOCOL_NATIVE_FLAG_REMAP (1<<0)
2019-12-11 11:21:43 +01:00
extern uint32_t pw_protocol_native0_find_type(struct pw_impl_client *client, const char *type);
extern int pw_protocol_native0_pod_to_v2(struct pw_impl_client *client, const struct spa_pod *pod,
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
struct spa_pod_builder *b);
2019-12-11 11:21:43 +01:00
extern uint32_t pw_protocol_native0_type_to_v2(struct pw_impl_client *client,
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
const struct spa_type_info *info, uint32_t type);
static void
client_node_marshal_add_mem(void *object,
uint32_t mem_id,
uint32_t type,
int memfd, uint32_t flags)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
const char *typename;
switch (type) {
case SPA_DATA_MemFd:
typename = "Spa:Enum:DataType:Fd:MemFd";
break;
case SPA_DATA_DmaBuf:
typename = "Spa:Enum:DataType:Fd:DmaBuf";
break;
default:
case SPA_DATA_MemPtr:
return;
}
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_ADD_MEM, NULL);
spa_pod_builder_add_struct(b,
"i", mem_id,
"I", pw_protocol_native0_find_type(resource->client, typename),
"i", pw_protocol_native_add_resource_fd(resource, memfd),
"i", flags);
pw_protocol_native_end_resource(resource, b);
}
static void client_node_marshal_transport(void *object, uint32_t node_id, int readfd, int writefd,
struct pw_client_node0_transport *transport)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct pw_client_node0_transport_info info;
pw_client_node0_transport_get_info(transport, &info);
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_TRANSPORT, NULL);
spa_pod_builder_add_struct(b,
"i", node_id,
"i", pw_protocol_native_add_resource_fd(resource, readfd),
"i", pw_protocol_native_add_resource_fd(resource, writefd),
"i", pw_protocol_native_add_resource_fd(resource, info.memfd),
"i", info.offset,
"i", info.size);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_set_param(void *object, uint32_t seq, uint32_t id, uint32_t flags,
const struct spa_pod *param)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_SET_PARAM, NULL);
spa_pod_builder_add_struct(b,
"i", seq,
"I", id,
"i", flags,
"P", param);
pw_protocol_native_end_resource(resource, b);
}
static void client_node_marshal_event_event(void *object, const struct spa_event *event)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_EVENT, NULL);
spa_pod_builder_add_struct(b, "P", event);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_command(void *object, uint32_t seq, const struct spa_command *command)
{
struct pw_resource *resource = object;
2019-12-11 11:21:43 +01:00
struct pw_impl_client *client = resource->client;
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_COMMAND, NULL);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b, "i", seq, NULL);
pw_protocol_native0_pod_to_v2(client, (struct spa_pod *)command, b);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_add_port(void *object,
uint32_t seq, enum spa_direction direction, uint32_t port_id)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_ADD_PORT, NULL);
spa_pod_builder_add_struct(b,
"i", seq,
"i", direction,
"i", port_id);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_remove_port(void *object,
uint32_t seq, enum spa_direction direction, uint32_t port_id)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_REMOVE_PORT, NULL);
spa_pod_builder_add_struct(b,
"i", seq,
"i", direction,
"i", port_id);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_port_set_param(void *object,
uint32_t seq,
enum spa_direction direction,
uint32_t port_id,
uint32_t id,
uint32_t flags,
const struct spa_pod *param)
{
struct pw_resource *resource = object;
2019-12-11 11:21:43 +01:00
struct pw_impl_client *client = resource->client;
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
struct spa_pod_builder *b;
struct spa_pod_frame f;
const char *typename;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_PORT_SET_PARAM, NULL);
switch (id) {
case SPA_PARAM_Props:
typename = "Spa:Enum:ParamId:Props";
break;
case SPA_PARAM_Format:
typename = "Spa:Enum:ParamId:Format";
break;
default:
return;
}
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"i", seq,
"i", direction,
"i", port_id,
"I", pw_protocol_native0_find_type(client, typename),
"i", flags, NULL);
pw_protocol_native0_pod_to_v2(client, param, b);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_port_use_buffers(void *object,
uint32_t seq,
enum spa_direction direction,
uint32_t port_id,
uint32_t n_buffers, struct pw_client_node0_buffer *buffers)
{
struct pw_resource *resource = object;
2019-12-11 11:21:43 +01:00
struct pw_impl_client *client = resource->client;
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, j;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_PORT_USE_BUFFERS, NULL);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"i", seq,
"i", direction,
"i", port_id,
"i", n_buffers, NULL);
for (i = 0; i < n_buffers; i++) {
struct spa_buffer *buf = buffers[i].buffer;
spa_pod_builder_add(b,
"i", buffers[i].mem_id,
"i", buffers[i].offset,
"i", buffers[i].size,
"i", i,
"i", buf->n_metas, NULL);
for (j = 0; j < buf->n_metas; j++) {
struct spa_meta *m = &buf->metas[j];
spa_pod_builder_add(b,
"I", pw_protocol_native0_type_to_v2(client, spa_type_meta_type, m->type),
"i", m->size, NULL);
}
spa_pod_builder_add(b, "i", buf->n_datas, NULL);
for (j = 0; j < buf->n_datas; j++) {
struct spa_data *d = &buf->datas[j];
spa_pod_builder_add(b,
"I", pw_protocol_native0_type_to_v2(client, spa_type_data_type, d->type),
"i", SPA_PTR_TO_UINT32(d->data),
"i", d->flags,
"i", d->mapoffset,
"i", d->maxsize, NULL);
}
}
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_port_command(void *object,
uint32_t direction,
uint32_t port_id,
const struct spa_command *command)
{
struct pw_resource *resource = object;
2019-12-11 11:21:43 +01:00
struct pw_impl_client *client = resource->client;
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
struct spa_pod_builder *b;
struct spa_pod_frame f;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_PORT_COMMAND, NULL);
spa_pod_builder_push_struct(b, &f);
spa_pod_builder_add(b,
"i", direction,
"i", port_id, NULL);
pw_protocol_native0_pod_to_v2(client, (struct spa_pod *)command, b);
spa_pod_builder_pop(b, &f);
pw_protocol_native_end_resource(resource, b);
}
static void
client_node_marshal_port_set_io(void *object,
uint32_t seq,
uint32_t direction,
uint32_t port_id,
uint32_t id,
uint32_t memid,
uint32_t offset,
uint32_t size)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
b = pw_protocol_native_begin_resource(resource, PW_CLIENT_NODE0_PROXY_EVENT_PORT_SET_IO, NULL);
spa_pod_builder_add_struct(b,
"i", seq,
"i", direction,
"i", port_id,
"I", id,
"i", memid,
"i", offset,
"i", size);
pw_protocol_native_end_resource(resource, b);
}
static int client_node_demarshal_done(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
uint32_t seq, res;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_get_struct(&prs,
"i", &seq,
"i", &res) < 0)
return -EINVAL;
return pw_resource_notify(resource, struct pw_client_node0_proxy_methods, done, 0, seq, res);
}
static int client_node_demarshal_update(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f;
uint32_t change_mask, max_input_ports, max_output_ports, n_params;
const struct spa_pod **params;
uint32_t i;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
spa_pod_parser_get(&prs,
"i", &change_mask,
"i", &max_input_ports,
"i", &max_output_ports,
"i", &n_params, NULL) < 0)
return -EINVAL;
params = alloca(n_params * sizeof(struct spa_pod *));
for (i = 0; i < n_params; i++)
if (spa_pod_parser_get(&prs, "O", &params[i], NULL) < 0)
return -EINVAL;
return pw_resource_notify(resource, struct pw_client_node0_proxy_methods, update, 0, change_mask,
max_input_ports,
max_output_ports,
n_params,
params);
}
static int client_node_demarshal_port_update(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_pod_frame f[2];
uint32_t i, direction, port_id, change_mask, n_params;
const struct spa_pod **params = NULL;
struct spa_port_info info = { 0 }, *infop = NULL;
struct spa_dict props;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
spa_pod_parser_get(&prs,
"i", &direction,
"i", &port_id,
"i", &change_mask,
"i", &n_params, NULL) < 0)
return -EINVAL;
params = alloca(n_params * sizeof(struct spa_pod *));
for (i = 0; i < n_params; i++)
if (spa_pod_parser_get(&prs, "O", &params[i], NULL) < 0)
return -EINVAL;
if (spa_pod_parser_push_struct(&prs, &f[1]) >= 0) {
infop = &info;
if (spa_pod_parser_get(&prs,
"i", &info.flags,
"i", &info.rate,
"i", &props.n_items, NULL) < 0)
return -EINVAL;
if (props.n_items > 0) {
info.props = &props;
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;
}
}
}
return pw_resource_notify(resource, struct pw_client_node0_proxy_methods, port_update, 0, direction,
port_id,
change_mask,
n_params,
params, infop);
}
static int client_node_demarshal_set_active(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
int active;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_get_struct(&prs,
"b", &active) < 0)
return -EINVAL;
return pw_resource_notify(resource, struct pw_client_node0_proxy_methods, set_active, 0, active);
}
static int client_node_demarshal_event_method(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
struct spa_event *event;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_get_struct(&prs,
"O", &event) < 0)
return -EINVAL;
return pw_resource_notify(resource, struct pw_client_node0_proxy_methods, event, 0, event);
}
static int client_node_demarshal_destroy(void *object, const struct pw_protocol_native_message *msg)
{
struct pw_resource *resource = object;
struct spa_pod_parser prs;
int res;
spa_pod_parser_init(&prs, msg->data, msg->size);
if (spa_pod_parser_get_struct(&prs, NULL) < 0)
return -EINVAL;
res = pw_resource_notify(resource, struct pw_client_node0_proxy_methods, destroy, 0);
pw_resource_destroy(resource);
return res;
}
static const struct pw_protocol_native_demarshal pw_protocol_native_client_node_method_demarshal[] = {
{ &client_node_demarshal_done, 0, 0 },
{ &client_node_demarshal_update, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP },
{ &client_node_demarshal_port_update, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP },
{ &client_node_demarshal_set_active, 0, 0 },
{ &client_node_demarshal_event_method, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP },
{ &client_node_demarshal_destroy, 0, 0 },
};
static const struct pw_client_node0_proxy_events pw_protocol_native_client_node_event_marshal = {
PW_VERSION_CLIENT_NODE0_PROXY_EVENTS,
&client_node_marshal_add_mem,
&client_node_marshal_transport,
&client_node_marshal_set_param,
&client_node_marshal_event_event,
&client_node_marshal_command,
&client_node_marshal_add_port,
&client_node_marshal_remove_port,
&client_node_marshal_port_set_param,
&client_node_marshal_port_use_buffers,
&client_node_marshal_port_command,
&client_node_marshal_port_set_io,
};
static const struct pw_protocol_marshal pw_protocol_native_client_node_marshal = {
PW_TYPE_INTERFACE_ClientNode,
PW_VERSION_CLIENT_NODE0,
PW_CLIENT_NODE0_PROXY_METHOD_NUM,
PW_CLIENT_NODE0_PROXY_EVENT_NUM,
0,
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
NULL,
.server_demarshal = &pw_protocol_native_client_node_method_demarshal,
.server_marshal = &pw_protocol_native_client_node_event_marshal,
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
NULL,
};
struct pw_protocol *pw_protocol_native_ext_client_node0_init(struct pw_context *context)
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
{
struct pw_protocol *protocol;
protocol = pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native);
protocol: add v0 compatibility For flatpaks we need to be able to support older v0 protocol clients. To handle this we have: - the connection detects an old client when it receives the first message. It can do this by checking the sequence number, on old versions it contains the message size and is never 0, on new clients the sequence number is 0. - We add a new signal at the start of the connection with the detected version number. This installs the right version of the core proxy. We also move the binding of the client until the hello message is received. This way we can have a new client connect (portal), hand over the connection to an old client, which then removes the client binding again in the hello request with a v0 version. There are some changes to the passing of fds in v0 vs v3 which need to investigated some more. - bump version of our interfaces to 3. This makes it possible to have v0 and v3 protocol marshal functions. - Add version number in the proxy. This is mostly automatically done internally based on the version numbers the library is compiled with. Where the version number was in the API before, it is now actually used to look up the right protocol marshal functions. For Proxies there is usually just 1 version, the current one. It is the server that will support different versions. - Add v0 compat marshal functions to convert from and to v0 format. This has some complications. v0 has a type map it keeps in sync with the server. For this we have a static type map with mappings to our own v3 types. Pods are mostly the same except for objects that used to have arbitrary pods in v0 vs spa_pod_prop in v3. Also convert between v0 spa_pod_prop and v3 spa_pod_choice. Formats and commands are also slightly different so handle those mappings as well. We only have marshal functions for the server side (resource) v0 functions. - Add v0 compatible client-node again. It's a bit tricky to map, v0 client-node basically lets the server to the mixing and teeing and just does the processing of the internal node.
2019-10-08 22:52:25 +02:00
if (protocol == NULL)
return NULL;
pw_protocol_add_marshal(protocol, &pw_protocol_native_client_node_marshal);
return protocol;
}